From 89d83047e8e8e8cacad12ab803bfc1aa1869dd8b Mon Sep 17 00:00:00 2001 From: Raphael <ufdrv@student.kit.edu> Date: Thu, 9 Feb 2017 18:48:41 +0100 Subject: [PATCH] added lvl1 passthroughcontroller added more metainfo to lvl1 (for the robot unit) added helperfunctions to the robot unit + updated the recommended implementation all functions called in rt now have the rt prefix --- source/RobotAPI/interface/CMakeLists.txt | 5 +- .../LVL1Controller.ice | 0 .../RTControllers/PassThroughController.ice | 42 ++++ .../RobotUnitInterface.ice | 2 +- .../BasicRTControllers/CMakeLists.txt | 20 ++ .../PassThroughController.cpp | 25 ++ .../PassThroughController.h | 220 ++++++++++++++++ source/RobotAPI/libraries/CMakeLists.txt | 4 +- .../CMakeLists.txt | 17 +- .../Constants.h | 0 .../ControlModes.h | 8 +- .../DataUnits/ForceTorqueDataUnit.h | 0 .../DataUnits/HapticDataUnit.h | 0 .../DataUnits/IMUDataUnit.h | 0 .../DataUnits/KinematicDataUnit.h | 0 .../DataUnits/PlatformDataUnit.h | 0 .../LVL0Controller.cpp | 0 .../LVL0Controller.h | 0 .../LVL1Controller.cpp | 19 ++ .../LVL1Controller.h | 43 +++- .../RobotUnit.cpp | 234 ++++++++++++++++-- .../RobotUnit.h | 172 ++++++++----- .../SyntaxCheck.cpp | 0 .../Targets/JointPositionTarget.h | 6 +- .../Targets/JointTargetBase.h | 6 +- .../Targets/JointTorqueTarget.h | 6 +- .../Targets/JointVelocityTarget.h | 6 +- 27 files changed, 711 insertions(+), 124 deletions(-) rename source/RobotAPI/interface/libraries/{Controllers => RTControllers}/LVL1Controller.ice (100%) create mode 100644 source/RobotAPI/interface/libraries/RTControllers/PassThroughController.ice rename source/RobotAPI/interface/libraries/{Controllers => RTControllers}/RobotUnitInterface.ice (97%) create mode 100644 source/RobotAPI/libraries/BasicRTControllers/CMakeLists.txt create mode 100644 source/RobotAPI/libraries/BasicRTControllers/PassThroughController.cpp create mode 100644 source/RobotAPI/libraries/BasicRTControllers/PassThroughController.h rename source/RobotAPI/libraries/{Controllers => RobotRTControllers}/CMakeLists.txt (63%) rename source/RobotAPI/libraries/{Controllers => RobotRTControllers}/Constants.h (100%) rename source/RobotAPI/libraries/{Controllers => RobotRTControllers}/ControlModes.h (78%) rename source/RobotAPI/libraries/{Controllers => RobotRTControllers}/DataUnits/ForceTorqueDataUnit.h (100%) rename source/RobotAPI/libraries/{Controllers => RobotRTControllers}/DataUnits/HapticDataUnit.h (100%) rename source/RobotAPI/libraries/{Controllers => RobotRTControllers}/DataUnits/IMUDataUnit.h (100%) rename source/RobotAPI/libraries/{Controllers => RobotRTControllers}/DataUnits/KinematicDataUnit.h (100%) rename source/RobotAPI/libraries/{Controllers => RobotRTControllers}/DataUnits/PlatformDataUnit.h (100%) rename source/RobotAPI/libraries/{Controllers => RobotRTControllers}/LVL0Controller.cpp (100%) rename source/RobotAPI/libraries/{Controllers => RobotRTControllers}/LVL0Controller.h (100%) rename source/RobotAPI/libraries/{Controllers => RobotRTControllers}/LVL1Controller.cpp (75%) rename source/RobotAPI/libraries/{Controllers => RobotRTControllers}/LVL1Controller.h (83%) rename source/RobotAPI/libraries/{Controllers => RobotRTControllers}/RobotUnit.cpp (65%) rename source/RobotAPI/libraries/{Controllers => RobotRTControllers}/RobotUnit.h (66%) rename source/RobotAPI/libraries/{Controllers => RobotRTControllers}/SyntaxCheck.cpp (100%) rename source/RobotAPI/libraries/{Controllers => RobotRTControllers}/Targets/JointPositionTarget.h (91%) rename source/RobotAPI/libraries/{Controllers => RobotRTControllers}/Targets/JointTargetBase.h (90%) rename source/RobotAPI/libraries/{Controllers => RobotRTControllers}/Targets/JointTorqueTarget.h (91%) rename source/RobotAPI/libraries/{Controllers => RobotRTControllers}/Targets/JointVelocityTarget.h (91%) diff --git a/source/RobotAPI/interface/CMakeLists.txt b/source/RobotAPI/interface/CMakeLists.txt index 448c67665..1ccbfdb6b 100644 --- a/source/RobotAPI/interface/CMakeLists.txt +++ b/source/RobotAPI/interface/CMakeLists.txt @@ -39,8 +39,9 @@ set(SLICE_FILES visualization/DebugDrawerInterface.ice - libraries/Controllers/LVL1Controller.ice - libraries/Controllers/RobotUnitInterface.ice + libraries/RTControllers/LVL1Controller.ice + libraries/RTControllers/PassThroughController.ice + libraries/RTControllers/RobotUnitInterface.ice ) #core/RobotIK.ice diff --git a/source/RobotAPI/interface/libraries/Controllers/LVL1Controller.ice b/source/RobotAPI/interface/libraries/RTControllers/LVL1Controller.ice similarity index 100% rename from source/RobotAPI/interface/libraries/Controllers/LVL1Controller.ice rename to source/RobotAPI/interface/libraries/RTControllers/LVL1Controller.ice diff --git a/source/RobotAPI/interface/libraries/RTControllers/PassThroughController.ice b/source/RobotAPI/interface/libraries/RTControllers/PassThroughController.ice new file mode 100644 index 000000000..7566f8c32 --- /dev/null +++ b/source/RobotAPI/interface/libraries/RTControllers/PassThroughController.ice @@ -0,0 +1,42 @@ +/* + * This file is part of ArmarX. + * + * ArmarX is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * ArmarX is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * @package RobotAPI::PassThroughController + * @author Raphael Grimm ( raphael dot grimm at student dot kit dot edu ) + * @date 2017 + * @copyright http://www.gnu.org/licenses/gpl-2.0.txt + * GNU General Public License + */ + +#ifndef _ARMARX_ROBOTAPI_PassThroughController_SLICE_ +#define _ARMARX_ROBOTAPI_PassThroughController_SLICE_ + +#include <ArmarXCore/interface/core/BasicTypes.ice> +#include <RobotAPI/interface/libraries/RTControllers/LVL1Controller.ice> + +module armarx +{ + class PassThroughControllerConfig extends LVL1ControllerConfig + { + Ice::StringSeq jointNames; + }; + + interface PassThroughControllerInterface extends LVL1ControllerInterface + { + idempotent void setJoint(string joint, float value) throws InvalidArgumentException; + idempotent void setJoints(StringFloatDictionary values) throws InvalidArgumentException; + }; +}; +#endif diff --git a/source/RobotAPI/interface/libraries/Controllers/RobotUnitInterface.ice b/source/RobotAPI/interface/libraries/RTControllers/RobotUnitInterface.ice similarity index 97% rename from source/RobotAPI/interface/libraries/Controllers/RobotUnitInterface.ice rename to source/RobotAPI/interface/libraries/RTControllers/RobotUnitInterface.ice index b78a9e2f4..aeeae71cc 100644 --- a/source/RobotAPI/interface/libraries/Controllers/RobotUnitInterface.ice +++ b/source/RobotAPI/interface/libraries/RTControllers/RobotUnitInterface.ice @@ -25,7 +25,7 @@ #include <ArmarXCore/interface/core/UserException.ice> -#include <RobotAPI/interface/libraries/Controllers/LVL1Controller.ice> +#include <RobotAPI/interface/libraries/RTControllers/LVL1Controller.ice> #include <RobotAPI/interface/units/KinematicUnitInterface.ice> #include <RobotAPI/interface/units/ForceTorqueUnit.ice> diff --git a/source/RobotAPI/libraries/BasicRTControllers/CMakeLists.txt b/source/RobotAPI/libraries/BasicRTControllers/CMakeLists.txt new file mode 100644 index 000000000..5ed672502 --- /dev/null +++ b/source/RobotAPI/libraries/BasicRTControllers/CMakeLists.txt @@ -0,0 +1,20 @@ +armarx_component_set_name("BasicRTControllers") +armarx_set_target("Library: BasicRTControllers") + +set(LIB_NAME BasicRTControllers) + +set(LIBS + ArmarXCoreInterfaces + ArmarXCore + RobotAPIInterfaces + RobotRTControllers +) + +set(LIB_FILES + PassThroughController.cpp +) +set(LIB_HEADERS + PassThroughController.h +) + +armarx_add_library("${LIB_NAME}" "${LIB_FILES}" "${LIB_HEADERS}" "${LIBS}") diff --git a/source/RobotAPI/libraries/BasicRTControllers/PassThroughController.cpp b/source/RobotAPI/libraries/BasicRTControllers/PassThroughController.cpp new file mode 100644 index 000000000..268586743 --- /dev/null +++ b/source/RobotAPI/libraries/BasicRTControllers/PassThroughController.cpp @@ -0,0 +1,25 @@ +/* + * This file is part of ArmarX. + * + * ArmarX is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * ArmarX is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * @package RobotAPI::ArmarXObjects::PassThroughController + * @author Raphael ( ufdrv at student dot kit dot edu ) + * @date 2017 + * @copyright http://www.gnu.org/licenses/gpl-2.0.txt + * GNU General Public License + */ + +#include "PassThroughController.h" + +using namespace armarx; diff --git a/source/RobotAPI/libraries/BasicRTControllers/PassThroughController.h b/source/RobotAPI/libraries/BasicRTControllers/PassThroughController.h new file mode 100644 index 000000000..05c70890c --- /dev/null +++ b/source/RobotAPI/libraries/BasicRTControllers/PassThroughController.h @@ -0,0 +1,220 @@ +/* + * This file is part of ArmarX. + * + * ArmarX is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * ArmarX is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * @package RobotAPI::ArmarXObjects::PassThroughController + * @author Raphael ( ufdrv at student dot kit dot edu ) + * @date 2017 + * @copyright http://www.gnu.org/licenses/gpl-2.0.txt + * GNU General Public License + */ + +#ifndef _ARMARX_LIB_RobotAPI_PassThroughController_H +#define _ARMARX_LIB_RobotAPI_PassThroughController_H + +#include <atomic> +#include <ArmarXCore/core/util/algorithm.h> +#include <ArmarXCore/core/exceptions/local/ExpressionException.h> +#include <RobotAPI/libraries/RobotRTControllers/LVL1Controller.h> +#include <RobotAPI/libraries/RobotRTControllers/RobotUnit.h> +#include <RobotAPI/interface/libraries/RTControllers/PassThroughController.h> + +#include <RobotAPI/libraries/RobotRTControllers/Targets/JointPositionTarget.h> +#include <RobotAPI/libraries/RobotRTControllers/Targets/JointTorqueTarget.h> +#include <RobotAPI/libraries/RobotRTControllers/Targets/JointVelocityTarget.h> +#include <RobotAPI/libraries/RobotRTControllers/DataUnits/KinematicDataUnit.h> + +namespace armarx +{ + template <typename T> + struct AtomicWrapper + { + std::atomic<T> val; + + AtomicWrapper( ):val{ }{} + AtomicWrapper(const T& v ):val{v }{} + AtomicWrapper(const std::atomic<T> &val ):val{val.load() }{} + AtomicWrapper(const AtomicWrapper &other):val{other.val.load()}{} + + AtomicWrapper &operator=(const AtomicWrapper &other) + { + val.store(other.val.load()); + return *this; + } + }; + + template <typename TargetType> + struct PassThroughControllerTargetTypeTraits; + + template <typename TargetType> + class PassThroughController: + virtual public LVL1Controller, + virtual public PassThroughControllerInterface + { + public: + using Traits = PassThroughControllerTargetTypeTraits<TargetType>; + + inline PassThroughController(IceInternal::Handle<RobotUnit> robotUnit, LVL1ControllerConfigPtr config); + + inline virtual void rtRun(const IceUtil::Time&, const IceUtil::Time&) override; + inline virtual void rtSwapBufferAndRun(const IceUtil::Time& sensorValuesTimestamp, const IceUtil::Time& timeSinceLastIteration) override; + inline virtual void rtPreActivateController() override; + + //ice interface + inline virtual std::string getClassName(const Ice::Current& = GlobalIceCurrent) const override; + inline virtual void setJoint(const std::string& name, Ice::Float value, const Ice::Current & = GlobalIceCurrent) override; + inline virtual void setJoints(const StringFloatDictionary& values, const Ice::Current & = GlobalIceCurrent) override; + protected: + std::vector<float*> lvl0Targets; + std::vector<const float*> jointStates; + std::vector<AtomicWrapper<float>> iceTargets; + std::unordered_map<std::string, std::size_t> indices; + + virtual void onInitComponent() override {} + virtual void onConnectComponent() override {} + }; + + template <> + struct PassThroughControllerTargetTypeTraits<JointVelocityTarget> + { + static float* getTargetDatamember(JointVelocityTarget& t) + { + return &t.velocity; + } + static std::vector<const float*> getSensorValues(const KinematicDataUnitInterface* ku, const std::vector<std::string>& v) + { + return ku->getJointVelocities(v); + } + static std::string getControlMode() + { + return ControlModes::VelocityMode; + } + }; + template <> + struct PassThroughControllerTargetTypeTraits<JointTorqueTarget> + { + static float* getTargetDatamember(JointTorqueTarget& t) + { + return &t.torque; + } + static std::vector<const float*> getSensorValues(const KinematicDataUnitInterface* ku, const std::vector<std::string>& v) + { + return ku->getJointTorques(v); + } + static std::string getControlMode() + { + return ControlModes::TorqueMode; + } + }; + template <> + struct PassThroughControllerTargetTypeTraits<JointPositionTarget> + { + static float* getTargetDatamember(JointPositionTarget& t) + { + return &t.position; + } + static std::vector<const float*> getSensorValues(const KinematicDataUnitInterface* ku, const std::vector<std::string>& v) + { + return ku->getJointAngles(v); + } + static std::string getControlMode() + { + return ControlModes::PositionMode; + } + }; + + LVL1ControllerRegistration<PassThroughController<JointPositionTarget>> registrationSomeControllerPositionPassThroughController("PositionPassThroughController"); + LVL1ControllerRegistration<PassThroughController<JointVelocityTarget>> registrationSomeControllerVelocityPassThroughController("VelocityPassThroughController"); + LVL1ControllerRegistration<PassThroughController<JointTorqueTarget >> registrationSomeControllerJointPassThroughController ("JointPassThroughController"); + + template <typename TargetType> + std::string PassThroughController<TargetType>::getClassName(const Ice::Current&) const + { + return "PassThroughController_" + Traits::getControlMode(); + } + + template <typename TargetType> + PassThroughController<TargetType>::PassThroughController(IceInternal::Handle<RobotUnit> robotUnit, LVL1ControllerConfigPtr config) + { + PassThroughControllerConfigPtr cfg = PassThroughControllerConfigPtr::dynamicCast(config); + ARMARX_CHECK_EXPRESSION_W_HINT(cfg, + "The provided config has the wrong type! The type is " << config->ice_id() + << " instead of " << PassThroughControllerConfig::ice_staticId()); + + //make sure the used units are supported + auto kinunit = robotUnit->getRTKinematicDataUnit(); + ARMARX_CHECK_EXPRESSION_W_HINT(kinunit, "The RobotUnit " << robotUnit->getName() << " has no kinematic data unit"); + //get pointers to sensor values from units + jointStates = Traits::getSensorValues(kinunit, cfg->jointNames) ; + + //not initialized, this is done in rtPreActivateController + iceTargets.resize(cfg->jointNames.size(),0); + + //get pointers for the results of this controller + lvl0Targets.reserve(cfg->jointNames.size()); + for (const auto & j : cfg->jointNames) + { + auto target = dynamic_cast<TargetType*>(robotUnit->getJointTarget(j, Traits::getControlMode())); + ARMARX_CHECK_EXPRESSION_W_HINT(target, "The joint " << j << " has no controll mode " << Traits::getControlMode()); + lvl0Targets.emplace_back(Traits::getTargetDatamember(*target)); + } + indices = toIndexMap(cfg->jointNames); + } + + template <typename TargetType> + void PassThroughController<TargetType>::rtRun(const IceUtil::Time&, const IceUtil::Time&) + { + for (std::size_t i = 0; i < iceTargets.size(); ++i) + { + *lvl0Targets.at(i) = iceTargets.at(i).val.load(); + } + } + + template <typename TargetType> + void PassThroughController<TargetType>::rtSwapBufferAndRun(const IceUtil::Time& sensorValuesTimestamp, const IceUtil::Time& timeSinceLastIteration) + { + rtRun(sensorValuesTimestamp, timeSinceLastIteration); + } + + template <typename TargetType> + void PassThroughController<TargetType>::rtPreActivateController() + { + for (std::size_t i = 0; i < jointStates.size(); ++i) + { + iceTargets.at(i).val.store(*jointStates.at(i)); + } + } + + template <typename TargetType> + void PassThroughController<TargetType>::setJoint(const std::string& name, Ice::Float value, const Ice::Current &) + { + auto targetIt = indices.find(name); + if(targetIt == indices.end()) + { + throw InvalidArgumentException{"The joint " + name + " is not controlled by this (" + getName() + ") controller"}; + } + iceTargets.at(targetIt->second).val.store(value); + } + + template <typename TargetType> + void PassThroughController<TargetType>::setJoints(const StringFloatDictionary& values, const Ice::Current &) + { + for(const auto& value:values) + { + setJoint(value.first, value.second); + } + } + +} +#endif diff --git a/source/RobotAPI/libraries/CMakeLists.txt b/source/RobotAPI/libraries/CMakeLists.txt index a9bcbc478..6d274fa76 100644 --- a/source/RobotAPI/libraries/CMakeLists.txt +++ b/source/RobotAPI/libraries/CMakeLists.txt @@ -1,3 +1,5 @@ add_subdirectory(core) add_subdirectory(widgets) -add_subdirectory(Controllers) +add_subdirectory(RobotRTControllers) +add_subdirectory(BasicRTControllers) + diff --git a/source/RobotAPI/libraries/Controllers/CMakeLists.txt b/source/RobotAPI/libraries/RobotRTControllers/CMakeLists.txt similarity index 63% rename from source/RobotAPI/libraries/Controllers/CMakeLists.txt rename to source/RobotAPI/libraries/RobotRTControllers/CMakeLists.txt index edb54d7b2..1ca0215a8 100644 --- a/source/RobotAPI/libraries/Controllers/CMakeLists.txt +++ b/source/RobotAPI/libraries/RobotRTControllers/CMakeLists.txt @@ -1,16 +1,7 @@ -armarx_component_set_name("Controllers") -armarx_set_target("Library: Controllers") - -set(LIB_NAME Controllers) - -#find_package(MyLib QUIET) -#armarx_build_if(MyLib_FOUND "MyLib not available") -# -# all include_directories must be guarded by if(Xyz_FOUND) -# for multiple libraries write: if(X_FOUND AND Y_FOUND).... -#if(MyLib_FOUND) -# include_directories(${MyLib_INCLUDE_DIRS}) -#endif() +armarx_component_set_name("RobotRTControllers") +armarx_set_target("Library: RobotRTControllers") + +set(LIB_NAME RobotRTControllers) set(LIBS ArmarXCoreInterfaces diff --git a/source/RobotAPI/libraries/Controllers/Constants.h b/source/RobotAPI/libraries/RobotRTControllers/Constants.h similarity index 100% rename from source/RobotAPI/libraries/Controllers/Constants.h rename to source/RobotAPI/libraries/RobotRTControllers/Constants.h diff --git a/source/RobotAPI/libraries/Controllers/ControlModes.h b/source/RobotAPI/libraries/RobotRTControllers/ControlModes.h similarity index 78% rename from source/RobotAPI/libraries/Controllers/ControlModes.h rename to source/RobotAPI/libraries/RobotRTControllers/ControlModes.h index 3cdd7d8d1..c81774b41 100644 --- a/source/RobotAPI/libraries/Controllers/ControlModes.h +++ b/source/RobotAPI/libraries/RobotRTControllers/ControlModes.h @@ -29,10 +29,10 @@ namespace armarx { namespace ControlModes { - static const std::string VelocityMode = "VelocityMode"; - static const std::string PositionMode = "PositionMode"; - static const std::string TorqueMode = "TorqueMode"; - static const std::string EmergencyStopMode = "EmergencyStopMode"; + static const std::string VelocityMode = "VelocityMode"; + static const std::string PositionMode = "PositionMode"; + static const std::string TorqueMode = "TorqueMode"; + static const std::string EmergencyStopMode = "EmergencyStopMode"; } } diff --git a/source/RobotAPI/libraries/Controllers/DataUnits/ForceTorqueDataUnit.h b/source/RobotAPI/libraries/RobotRTControllers/DataUnits/ForceTorqueDataUnit.h similarity index 100% rename from source/RobotAPI/libraries/Controllers/DataUnits/ForceTorqueDataUnit.h rename to source/RobotAPI/libraries/RobotRTControllers/DataUnits/ForceTorqueDataUnit.h diff --git a/source/RobotAPI/libraries/Controllers/DataUnits/HapticDataUnit.h b/source/RobotAPI/libraries/RobotRTControllers/DataUnits/HapticDataUnit.h similarity index 100% rename from source/RobotAPI/libraries/Controllers/DataUnits/HapticDataUnit.h rename to source/RobotAPI/libraries/RobotRTControllers/DataUnits/HapticDataUnit.h diff --git a/source/RobotAPI/libraries/Controllers/DataUnits/IMUDataUnit.h b/source/RobotAPI/libraries/RobotRTControllers/DataUnits/IMUDataUnit.h similarity index 100% rename from source/RobotAPI/libraries/Controllers/DataUnits/IMUDataUnit.h rename to source/RobotAPI/libraries/RobotRTControllers/DataUnits/IMUDataUnit.h diff --git a/source/RobotAPI/libraries/Controllers/DataUnits/KinematicDataUnit.h b/source/RobotAPI/libraries/RobotRTControllers/DataUnits/KinematicDataUnit.h similarity index 100% rename from source/RobotAPI/libraries/Controllers/DataUnits/KinematicDataUnit.h rename to source/RobotAPI/libraries/RobotRTControllers/DataUnits/KinematicDataUnit.h diff --git a/source/RobotAPI/libraries/Controllers/DataUnits/PlatformDataUnit.h b/source/RobotAPI/libraries/RobotRTControllers/DataUnits/PlatformDataUnit.h similarity index 100% rename from source/RobotAPI/libraries/Controllers/DataUnits/PlatformDataUnit.h rename to source/RobotAPI/libraries/RobotRTControllers/DataUnits/PlatformDataUnit.h diff --git a/source/RobotAPI/libraries/Controllers/LVL0Controller.cpp b/source/RobotAPI/libraries/RobotRTControllers/LVL0Controller.cpp similarity index 100% rename from source/RobotAPI/libraries/Controllers/LVL0Controller.cpp rename to source/RobotAPI/libraries/RobotRTControllers/LVL0Controller.cpp diff --git a/source/RobotAPI/libraries/Controllers/LVL0Controller.h b/source/RobotAPI/libraries/RobotRTControllers/LVL0Controller.h similarity index 100% rename from source/RobotAPI/libraries/Controllers/LVL0Controller.h rename to source/RobotAPI/libraries/RobotRTControllers/LVL0Controller.h diff --git a/source/RobotAPI/libraries/Controllers/LVL1Controller.cpp b/source/RobotAPI/libraries/RobotRTControllers/LVL1Controller.cpp similarity index 75% rename from source/RobotAPI/libraries/Controllers/LVL1Controller.cpp rename to source/RobotAPI/libraries/RobotRTControllers/LVL1Controller.cpp index f2ebd3f92..0b8b25547 100644 --- a/source/RobotAPI/libraries/Controllers/LVL1Controller.cpp +++ b/source/RobotAPI/libraries/RobotRTControllers/LVL1Controller.cpp @@ -26,3 +26,22 @@ using namespace armarx; + +void LVL1Controller::rtActivateController() +{ + if (!isActive) + { + rtPreActivateController(); + isActive = true; + } +} + +void LVL1Controller::rtDeactivateController() +{ + if (isActive) + { + isActive = false; + rtPostDeactivateController(); + } +} + diff --git a/source/RobotAPI/libraries/Controllers/LVL1Controller.h b/source/RobotAPI/libraries/RobotRTControllers/LVL1Controller.h similarity index 83% rename from source/RobotAPI/libraries/Controllers/LVL1Controller.h rename to source/RobotAPI/libraries/RobotRTControllers/LVL1Controller.h index e894ca8e2..c765dbf48 100644 --- a/source/RobotAPI/libraries/Controllers/LVL1Controller.h +++ b/source/RobotAPI/libraries/RobotRTControllers/LVL1Controller.h @@ -32,7 +32,7 @@ #include <ArmarXCore/core/util/Registrar.h> #include <ArmarXCore/core/util/TripleBuffer.h> -#include <RobotAPI/interface/libraries/Controllers/LVL1Controller.h> +#include <RobotAPI/interface/libraries/RTControllers/LVL1Controller.h> #include "Targets/JointTargetBase.h" @@ -61,11 +61,41 @@ namespace armarx //c++ interface (local calls) (can only be called in the rt thread) virtual void rtRun(const IceUtil::Time& sensorValuesTimestamp, const IceUtil::Time& timeSinceLastIteration) = 0; virtual void rtSwapBufferAndRun(const IceUtil::Time& sensorValuesTimestamp, const IceUtil::Time& timeSinceLastIteration) = 0; + /** + * @brief This function is called before the controller is activated. + * You can use it to activate a thread again (DO NOT SPAWN NEW THREADS!) e.g. via a std::atomic_bool. + */ + virtual void rtPreActivateController() {} + /** + * @brief This function is called after the controller is deactivated. + * You can use it to deactivate a thread (DO NOT JOIN THREADS!) e.g. via a std::atomic_bool. + */ + virtual void rtPostDeactivateController() {} + + bool rtUsesJoint(std::size_t jointindex) const + { + return std::find(jointIndices.begin(), jointIndices.end(), jointindex) == jointIndices.end(); + } + const std::vector<std::size_t>& rtGetJointIndices() const + { + return jointIndices; + } private: friend class RobotUnit; + void rtActivateController(); + void rtDeactivateController(); + //this data is filled by the robot unit to provide convenience functions std::atomic_bool isActive {false}; JointNameToControlModeDictionary jointControlModeMap; + std::vector<std::size_t> jointIndices; + + // ManagedIceObject interface + protected: + std::string getDefaultName() const + { + return getClassName(); + } }; using LVL1ControllerPtr = IceInternal::Handle<LVL1Controller>; @@ -85,12 +115,12 @@ namespace armarx }; /** - * @defgroup Library-Controllers Controllers + * @defgroup Library-RobotRTControllers RobotRTControllers * @ingroup RobotAPI - * A description of the library Controllers. + * A description of the library RobotRTControllers. * * @class LVL1Controller - * @ingroup Library-Controllers + * @ingroup Library-RobotRTControllers * @brief Brief description of class LVL1Controller. * * Detailed description of class LVL1Controller. @@ -137,9 +167,9 @@ namespace armarx //read the config someParamSetViaConfig = someConfig->parameterSetViaIceCalls //make sure the used units are supported - ARMARX_CHECK_EXPRESSION_W_HINT(robotUnit->getKinematicDataUnit(), "The RobotUnit " << robotUnit->getName() << " has no kinematic data unit"); + ARMARX_CHECK_EXPRESSION_W_HINT(robotUnit->getRTKinematicDataUnit(), "The RobotUnit " << robotUnit->getName() << " has no kinematic data unit"); //get pointers to sensor values from units - jointValuePtrs = robotUnit->getKinematicDataUnit()->getJointAngles({"jointX", "jointY"}); + jointValuePtrs = robotUnit->getRTKinematicDataUnit()->getJointAngles({"jointX", "jointY"}); //get pointers for the results of this controller targetJointXPtr = dynamic_cast<JointVelocityTarget*>(robotUnit->getJointTarget("jointX", ControlModes::VelocityMode)); @@ -169,6 +199,7 @@ namespace armarx } } //register the controller + //this line has to appear in some cpp of your lib to do its registration (including it is enough) LVL1ControllerRegistration<SomeController> registrationSomeController("SomeController"); } * \endcode diff --git a/source/RobotAPI/libraries/Controllers/RobotUnit.cpp b/source/RobotAPI/libraries/RobotRTControllers/RobotUnit.cpp similarity index 65% rename from source/RobotAPI/libraries/Controllers/RobotUnit.cpp rename to source/RobotAPI/libraries/RobotRTControllers/RobotUnit.cpp index 7ea9bdb26..99718eaf2 100644 --- a/source/RobotAPI/libraries/Controllers/RobotUnit.cpp +++ b/source/RobotAPI/libraries/RobotRTControllers/RobotUnit.cpp @@ -33,13 +33,18 @@ armarx::PropertyDefinitionsPtr armarx::RobotUnit::createPropertyDefinitions() void armarx::RobotUnit::addLVL0Controller(const std::string& jointName, armarx::LVL0ControllerBase& lvl0Controller) { + std::string controlMode = lvl0Controller.getControlMode(); GuardType guard {dataMutex}; - if (hasLVL0Controller(jointName, lvl0Controller.getControlMode())) + if (hasLVL0Controller(jointName, controlMode)) { - ARMARX_ERROR << "A LVL0Controller for " + jointName + "(" + lvl0Controller.getControlMode() + ") does already exist!"; - throw std::invalid_argument {"A LVL0Controller for " + jointName + "(" + lvl0Controller.getControlMode() + ") does already exist!"}; + ARMARX_ERROR << "A LVL0Controller for " + jointName + "(" + controlMode + ") does already exist!"; + throw std::invalid_argument {"A LVL0Controller for " + jointName + "(" + controlMode + ") does already exist!"}; + } + lvl0Controllers[jointName][controlMode] = &lvl0Controller; + if(controlMode == ControlModes::EmergencyStopMode) + { + lvl0ControllersEmergencyStop.at(jointNameIndices.at(jointName)) = &lvl0Controller; } - lvl0Controllers[jointName][lvl0Controller.getControlMode()] = &lvl0Controller; } const armarx::LVL0ControllerBase& armarx::RobotUnit::getLVL0Controller(const std::string& jointName, const std::string& controlMode) const @@ -54,6 +59,14 @@ armarx::LVL0ControllerBase& armarx::RobotUnit::getLVL0Controller(const std::stri return *lvl0Controllers.at(jointName).at(controlMode); } +armarx::RobotUnit::RobotUnit(const std::vector<std::string> &jointNames): + jointNames{jointNames}, + jointNameIndices{toIndexMap(jointNames)}, + controllersRequested{jointNames.size()}, + controllersActivated{jointNames.size()}, + lvl0ControllersEmergencyStop{jointNames.size()} +{} + Ice::StringSeq armarx::RobotUnit::getControllersKnown(const Ice::Current&) const { return LVL1ControllerRegistry::getKeys(); @@ -75,9 +88,12 @@ Ice::StringSeq armarx::RobotUnit::getControllerNamesRequested(const Ice::Current GuardType guard {dataMutex}; Ice::StringSeq result; result.reserve(lvl1Controllers.size()); - for (const auto & lvl1 : controllersRequested.getWriteBuffer().lvl1Controllers) + for (const auto & lvl1 : getRequestedLVL1Controllers()) { - result.emplace_back(lvl1->getName()); + if(lvl1) + { + result.emplace_back(lvl1->getName()); + } } return result; } @@ -86,7 +102,7 @@ Ice::StringSeq armarx::RobotUnit::getControllerNamesActivated(const Ice::Current GuardType guard {dataMutex}; Ice::StringSeq result; result.reserve(lvl1Controllers.size()); - for (const auto & lvl1 : controllersActivated.getUpToDateReadBuffer().lvl1Controllers) + for (const auto & lvl1 : getActivatedLVL1Controllers()) { result.emplace_back(lvl1->getName()); } @@ -107,9 +123,12 @@ armarx::StringLVL1ControllerPrxDictionary armarx::RobotUnit::getControllersReque { GuardType guard {dataMutex}; StringLVL1ControllerPrxDictionary result; - for (const auto & lvl1 : controllersRequested.getWriteBuffer().lvl1Controllers) + for (const auto & lvl1 : getRequestedLVL1Controllers()) { - result[lvl1->getName()] = LVL1ControllerInterfacePrx::uncheckedCast(lvl1->getProxy()); + if(lvl1) + { + result[lvl1->getName()] = LVL1ControllerInterfacePrx::uncheckedCast(lvl1->getProxy()); + } } return result; } @@ -117,7 +136,7 @@ armarx::StringLVL1ControllerPrxDictionary armarx::RobotUnit::getControllersActiv { GuardType guard {dataMutex}; StringLVL1ControllerPrxDictionary result; - for (const auto & lvl1 : controllersActivated.getUpToDateReadBuffer().lvl1Controllers) + for (const auto & lvl1 : getActivatedLVL1Controllers()) { result[lvl1->getName()] = LVL1ControllerInterfacePrx::uncheckedCast(lvl1->getProxy()); } @@ -128,7 +147,7 @@ armarx::JointNameToLVL1Dictionary armarx::RobotUnit::getControllerJointAssignmen { GuardType guard {dataMutex}; JointNameToLVL1Dictionary result; - for (const auto & lvl1 : controllersActivated.getUpToDateReadBuffer().lvl1Controllers) + for (const auto & lvl1 : getActivatedLVL1Controllers()) { for (const auto & jointMode : lvl1->jointControlModeMap) { @@ -142,7 +161,7 @@ armarx::JointNameToControlModeDictionary armarx::RobotUnit::getJointControlModes { GuardType guard {dataMutex}; JointNameToControlModeDictionary result; - const auto& requestedModes = controllersRequested.getWriteBuffer().lvl0Controllers; + const auto& requestedModes = getRequestedLVL0Controllers(); ARMARX_CHECK_AND_THROW(jointNames.size() == requestedModes.size(), std::logic_error); for (std::size_t i = 0; i < jointNames.size(); ++i) { @@ -154,7 +173,7 @@ armarx::JointNameToControlModeDictionary armarx::RobotUnit::getJointControlModes { GuardType guard {dataMutex}; JointNameToControlModeDictionary result; - const auto& activatedModes = controllersActivated.getUpToDateReadBuffer().lvl0Controllers; + const auto& activatedModes = getActivatedLVL0Controllers(); ARMARX_CHECK_AND_THROW(jointNames.size() == activatedModes.size(), std::logic_error); for (std::size_t i = 0; i < jointNames.size(); ++i) { @@ -247,25 +266,25 @@ void armarx::RobotUnit::switchSetup(const Ice::StringSeq& controllerRequestedNam } } //verify (warn for orphant joints) + populate controllersRequested.lvl0Controllers - controllersRequested.getWriteBuffer().lvl0Controllers.resize(jointNames.size()); + getRequestedLVL0Controllers().resize(jointNames.size()); for (std::size_t i = 0; i < jointNames.size(); ++i) { const auto& joint = jointNames.at(i); if (lvl1ControllerAssignement[joint].empty()) { - controllersRequested.getWriteBuffer().lvl0Controllers.at(i) = &getLVL0Controller(joint, ControlModes::EmergencyStopMode); + getRequestedLVL0Controllers().at(i) = &getLVL0Controller(joint, ControlModes::EmergencyStopMode); ARMARX_WARNING << "Joint '" << joint << "' has no lvl1 controller assigned!"; continue; } const auto& lvl0Mode = lvl1Controllers.at(lvl1ControllerAssignement[joint])->jointControlModeMap.at(joint); - controllersRequested.getWriteBuffer().lvl0Controllers.at(i) = &getLVL0Controller(joint, lvl0Mode); + getRequestedLVL0Controllers().at(i) = &getLVL0Controller(joint, lvl0Mode); } //populate controllersRequested.lvl1Controllers - controllersRequested.getWriteBuffer().lvl1Controllers.clear(); - controllersRequested.getWriteBuffer().lvl1Controllers.reserve(controllersToActivate.size()); + getRequestedLVL1Controllers().clear(); + getRequestedLVL1Controllers().reserve(controllersToActivate.size()); for (const auto & lvl1 : controllersToActivate) { - controllersRequested.getWriteBuffer().lvl1Controllers.emplace_back(lvl1Controllers.at(lvl1)); + getRequestedLVL1Controllers().emplace_back(lvl1Controllers.at(lvl1)); } //now change the assignement @@ -303,6 +322,13 @@ armarx::LVL1ControllerInterfacePrx armarx::RobotUnit::loadController(const std:: jointsUsedByLVL1Controler.clear(); LVL1ControllerPtr lvl1 = factory(this, config); lvl1->jointControlModeMap = jointsUsedByLVL1Controler; + lvl1->jointIndices.clear(); + lvl1->jointIndices.reserve(jointsUsedByLVL1Controler.size()); + for(const auto& j: jointsUsedByLVL1Controler) + { + lvl1->jointIndices.emplace_back(jointNameIndices.at(j.first)); + } + getArmarXManager()->addObject(lvl1, instanceName); const auto prx = lvl1->getProxy(-1); lvl1Controllers[instanceName] = lvl1; @@ -328,6 +354,18 @@ bool armarx::RobotUnit::hasLVL1Controller(const std::string& name) const return lvl1Controllers.end() != lvl1Controllers.find(name); } +void armarx::RobotUnit::setLVL1ControllerActive(const armarx::LVL1ControllerPtr& lvl1, bool isActive) +{ + if (isActive) + { + lvl1->rtActivateController(); + } + else + { + lvl1->rtDeactivateController(); + } +} + bool armarx::RobotUnit::hasLVL0Controller(const std::string& jointName, const std::string& controlMode) const { GuardType guard {dataMutex}; @@ -413,3 +451,161 @@ bool armarx::RobotUnit::loadLibFromPackage(const std::string& package, const std ARMARX_ERROR << "Could not find library " << name << " in package " << package; return false; } + +bool armarx::RobotUnit::rtControllersWereSwitched() const +{ + return controllersRequested.getUpToDateData(); +} + +std::vector<armarx::LVL0ControllerBase *> &armarx::RobotUnit::getRequestedLVL0Controllers() +{ + return controllersRequested.getWriteBuffer().lvl0Controllers; +} + +std::vector<armarx::LVL1ControllerPtr> &armarx::RobotUnit::getRequestedLVL1Controllers() +{ + return controllersRequested.getWriteBuffer().lvl1Controllers; +} + +const std::vector<armarx::LVL0ControllerBase *> &armarx::RobotUnit::getRequestedLVL0Controllers() const +{ + return controllersRequested.getWriteBuffer().lvl0Controllers; +} + +const std::vector<armarx::LVL1ControllerPtr> &armarx::RobotUnit::getRequestedLVL1Controllers() const +{ + return controllersRequested.getWriteBuffer().lvl1Controllers; +} + +const std::vector<armarx::LVL0ControllerBase *> &armarx::RobotUnit::getActivatedLVL0Controllers() const +{ + return controllersActivated.getUpToDateReadBuffer().lvl0Controllers; +} + +const std::vector<armarx::LVL1ControllerPtr> &armarx::RobotUnit::getActivatedLVL1Controllers() const +{ + return controllersActivated.getUpToDateReadBuffer().lvl1Controllers; +} + +const std::vector<armarx::LVL0ControllerBase *> &armarx::RobotUnit::rtGetRequestedLVL0Controllers() const +{ + return controllersRequested.getReadBuffer().lvl0Controllers; +} + +const std::vector<armarx::LVL1ControllerPtr> &armarx::RobotUnit::rtGetRequestedLVL1Controllers() const +{ + return controllersRequested.getReadBuffer().lvl1Controllers; +} + +std::vector<armarx::LVL0ControllerBase *> &armarx::RobotUnit::rtGetActivatedLVL0Controllers() +{ + return controllersActivated.getWriteBuffer().lvl0Controllers; +} + +std::vector<armarx::LVL1ControllerPtr> &armarx::RobotUnit::rtGetActivatedLVL1Controllers() +{ + return controllersActivated.getWriteBuffer().lvl1Controllers; +} + +const std::vector<armarx::LVL0ControllerBase *> &armarx::RobotUnit::rtGetActivatedLVL0Controllers() const +{ + return controllersActivated.getWriteBuffer().lvl0Controllers; +} + +const std::vector<armarx::LVL1ControllerPtr> &armarx::RobotUnit::rtGetActivatedLVL1Controllers() const +{ + return controllersActivated.getWriteBuffer().lvl1Controllers; +} + +void armarx::RobotUnit::rtCommitActivatedLVL1Controllers() +{ + controllersActivated.commitWrite(); +} + +bool armarx::RobotUnit::rtSwitchSetup() +{ + if(!rtControllersWereSwitched()) + { + return false; + } + //handle lvl1 + for(std::size_t i = 0; i < rtGetRequestedLVL1Controllers().size(); ++i) + { + //deactivate old + if(rtGetActivatedLVL1Controllers().at(i)) + { + rtGetActivatedLVL1Controllers().at(i)->rtDeactivateController(); + } + //activate new + if(rtGetRequestedLVL1Controllers().at(i)) + { + rtGetRequestedLVL1Controllers().at(i)->rtActivateController(); + } + //update activated + rtGetActivatedLVL1Controllers().at(i) = rtGetRequestedLVL1Controllers().at(i); + } + //handle lvl0 + for(std::size_t i = 0; i < rtGetRequestedLVL0Controllers().size(); ++i) + { + if(rtGetRequestedLVL0Controllers().at(i) != rtGetActivatedLVL0Controllers().at(i)) + { + rtSwitchLVL0Controller(i, rtGetActivatedLVL0Controllers().at(i), rtGetRequestedLVL0Controllers().at(i)); + rtGetActivatedLVL0Controllers().at(i) = rtGetRequestedLVL0Controllers().at(i); + } + } + return true; +} + +void armarx::RobotUnit::rtRunLVL1Controllers(const IceUtil::Time &sensorValuesTimestamp, const IceUtil::Time &timeSinceLastIteration) +{ + for(LVL1ControllerPtr& lvl1: rtGetActivatedLVL1Controllers()) + { + if(!lvl1) + { + continue; + } + lvl1->rtSwapBufferAndRun(sensorValuesTimestamp, timeSinceLastIteration); + } +} + +void armarx::RobotUnit::rtDeactivateAssignedLVL1Controller(std::size_t index) +{ + for(std::size_t i = 0; i < rtGetRequestedLVL1Controllers().size(); ++i) + { + if(!rtGetRequestedLVL1Controllers().at(i)) + { + continue; + } + if(rtGetRequestedLVL1Controllers().at(i)->rtUsesJoint(index)) + { + rtGetRequestedLVL1Controllers().at(i)->rtDeactivateController(); + for(auto used:rtGetRequestedLVL1Controllers().at(i)->rtGetJointIndices()) + { + rtSwitchLVL0Controller(used, rtGetActivatedLVL0Controllers().at(i), lvl0ControllersEmergencyStop.at(i)); + rtGetActivatedLVL0Controllers().at(i) = lvl0ControllersEmergencyStop.at(i); + } + rtGetActivatedLVL1Controllers().at(i) = nullptr; + return; + } + } +} + +void armarx::RobotUnit::rtRunLVL0Controllers() +{ + for(LVL0ControllerBase* lvl0: rtGetActivatedLVL0Controllers()) + { + lvl0->run(); + } +} + +bool armarx::RobotUnit::rtValidateLVL0ControllerSetup() const +{ + for(const auto& lvl0: lvl0ControllersEmergencyStop) + { + if(!lvl0) + { + return false; + } + } + return true; +} diff --git a/source/RobotAPI/libraries/Controllers/RobotUnit.h b/source/RobotAPI/libraries/RobotRTControllers/RobotUnit.h similarity index 66% rename from source/RobotAPI/libraries/Controllers/RobotUnit.h rename to source/RobotAPI/libraries/RobotRTControllers/RobotUnit.h index 58fc29c02..7672f0cee 100644 --- a/source/RobotAPI/libraries/Controllers/RobotUnit.h +++ b/source/RobotAPI/libraries/RobotRTControllers/RobotUnit.h @@ -36,7 +36,7 @@ #include <ArmarXCore/core/util/algorithm.h> #include <ArmarXCore/core/util/TripleBuffer.h> -#include <RobotAPI/interface/libraries/Controllers/RobotUnitInterface.h> +#include <RobotAPI/interface/libraries/RTControllers/RobotUnitInterface.h> #include "LVL0Controller.h" #include "LVL1Controller.h" @@ -102,64 +102,61 @@ namespace armarx * { * try * { - * initYourCommunication(); + * initYourCommunication();//implement this + * passYourLVL0ControllersToTheRobotUnit();//implement this + * if(!rtValidateLVL0ControllerSetup()) + * { + * //report errors + * throw std::logic_error{"lvl0 controller setup invalid"}; + * } * IceUtil::Time currentStateTimestamp = TimeUtil::GetTime(); * IceUtil::Time lastStateTimestamp = TimeUtil::GetTime(); - * getTheCurrentRobotState(); + * getTheCurrentRobotState();//implement this * while(isNotStopped()) * { * const IceUtil::Time startIteration = TimeUtil::GetTime(); - * if(controllersRequested.getUpToDateData()) - * { - * //the controllers were switched - * //change the joint controll modes (they should use the new lvl0 controllers) - * //update controllersActivated to inform the user which controllers are in use - * controllersActivated.getWriteBuffer().lvl0Controllers = ...; - * controllersActivated.getWriteBuffer().lvl1Controllers = controllersRequested.getReadBuffer().lvl1Controllers; - * controllersActivated.commitWrite(); - * } - * //run the lvl1 controllers - * for(LVL1ControllerPtr& lvl1: controllersActivated.getWriteBuffer().lvl1Controllers) + * //switching controllers + * if(rtSwitchSetup()) * { - * if(!lvl1) + * if(switchSetupError) * { - * continue; + * //report this error and exit + * throw std::logic_error{"switching the controller setup failed"}; * } - * lvl1->rtSwapBufferAndRun(currentStateTimestamp, currentStateTimestamp - lastStateTimestamp); + * //validate the setup if you need to + * //if you had to change something, call rtCommitActivatedLVL1Controllers(); * } + * //run the lvl1 controllers + * rtRunLVL1Controllers(currentStateTimestamp, currentStateTimestamp - lastStateTimestamp); * //validate targets - * for(LVL0ControllerBase* lvl0: controllersActivated.getWriteBuffer().lvl0Controllers) + * for(std::size_t i = 0; i<rtGetActivatedLVL0Controllers().size(); ++i) * { - * if(!lvl0->isTargetVaild()) + * if(!rtGetActivatedLVL0Controllers().at(i)->isTargetVaild()) * { * //handle this error! * //you probably should log this error to some error struct - * //then identify the misbehaving lvl1 controller - * //set all lvl0 controllers controlled by it to ControlModes::EmergencyStopMode - * //update controllersActivated.getWriteBuffer().lvl0Controllers - * //remove the lvl controller from controllersActivated.getWriteBuffer().lvl1Controllers (set it to nullptr) - * controllersActivated.commitWrite() + * rtDeactivateAssignedLVL1Controller(i); + * rtCommitActivatedLVL1Controllers(); * } * } - * for(LVL0ControllerBase* lvl0: controllersActivated.getWriteBuffer().lvl0Controllers) - * { - * lvl0->run(); - * } + * //run lvl0 + * rtRunLVL0Controllers(); * + * //time keeping + communicating * currentStateTimestamp = TimeUtil::GetTime(); * lastStateTimestamp = currentStateTimestamp; - * getTheCurrentRobotStateAndSendTheCurrentControllCommands(); - * communicateWithYourPublisherThread(); + * getTheCurrentRobotStateAndSendTheCurrentControllCommands();//implement this + * communicateWithYourPublisherThread();//implement this * //maybe meassure how long a loop took and log this information to your error struct * TimeUtil::Sleep(IceUtil::Time::microSeconds(1000)-(currentStateTimestamp-startIteration)); * } * } * catch(...) * { - * emergencyStop(); - * dumpDebuggingData(); - * doSomeErrorHandling(); - * shutEverythingGracefullyDown(); + * emergencyStop();//implement this + * dumpDebuggingData();//implement this + * doSomeErrorHandling();//implement this + * shutEverythingGracefullyDown();//implement this * } * } * \endcode @@ -191,6 +188,9 @@ namespace armarx public: using MutexType = std::recursive_mutex; using GuardType = std::lock_guard<MutexType>; + + RobotUnit(const std::vector<std::string>& jointNames); + //controllers virtual Ice::StringSeq getControllersKnown(const Ice::Current& = GlobalIceCurrent) const override; virtual Ice::StringSeq getControllerNamesLoaded(const Ice::Current& = GlobalIceCurrent) const override; @@ -205,30 +205,66 @@ namespace armarx virtual JointNameToControlModeDictionary getJointControlModesRequested(const Ice::Current& = GlobalIceCurrent) const override; virtual JointNameToControlModeDictionary getJointControlModesActivated(const Ice::Current& = GlobalIceCurrent) const override; virtual JointNameToControlModesDictionary getJointControlModesSupported(const Ice::Current& = GlobalIceCurrent) const override; - //loading and switching + //loading and switching (ice) virtual void switchSetup(const Ice::StringSeq& controllerRequestedNames, const Ice::Current& = GlobalIceCurrent) override; virtual LVL1ControllerInterfacePrx loadController(const std::string& className, const std::string& instanceName, const LVL1ControllerConfigPtr& config, const Ice::Current& = GlobalIceCurrent) override; virtual bool loadLibFromPath(const std::string& path, const Ice::Current& = GlobalIceCurrent) override; virtual bool loadLibFromPackage(const std::string& package, const std::string& lib, const Ice::Current& = GlobalIceCurrent) override; + //get buffers (ice) + /// @return The requested lvl0 controllers (none is null) + std::vector<LVL0ControllerBase*>& getRequestedLVL0Controllers(); + /// @return The requested lvl1 controllers (some may be null) + std::vector<LVL1ControllerPtr >& getRequestedLVL1Controllers(); + /// @return The requested lvl0 controllers (none is null) + const std::vector<LVL0ControllerBase*>& getRequestedLVL0Controllers() const; + /// @return The requested lvl1 controllers (some may be null) + const std::vector<LVL1ControllerPtr >& getRequestedLVL1Controllers() const; + /// @return The activated lvl0 controllers (none is null) + const std::vector<LVL0ControllerBase*>& getActivatedLVL0Controllers() const; + /// @return The activated lvl1 controllers (some may be null) + const std::vector<LVL1ControllerPtr >& getActivatedLVL1Controllers() const; + //buffers (rt) + bool rtControllersWereSwitched() const; + /// @return The requested lvl0 controllers (none is null) + const std::vector<LVL0ControllerBase*>& rtGetRequestedLVL0Controllers() const; + /// @return The requested lvl1 controllers (some may be null) + const std::vector<LVL1ControllerPtr >& rtGetRequestedLVL1Controllers() const; + /// @return The activated lvl0 controllers (none is null) + std::vector<LVL0ControllerBase*>& rtGetActivatedLVL0Controllers(); + /// @return The activated lvl1 controllers (some may be null) + std::vector<LVL1ControllerPtr >& rtGetActivatedLVL1Controllers(); + /// @return The activated lvl0 controllers (none is null) + const std::vector<LVL0ControllerBase*>& rtGetActivatedLVL0Controllers() const; + /// @return The activated lvl1 controllers (some may be null) + const std::vector<LVL1ControllerPtr >& rtGetActivatedLVL1Controllers() const; + void rtCommitActivatedLVL1Controllers(); + + //switching (rt) + bool rtSwitchSetup(); + void rtRunLVL1Controllers(const IceUtil::Time& sensorValuesTimestamp, const IceUtil::Time& timeSinceLastIteration); + void rtDeactivateAssignedLVL1Controller(std::size_t index); + void rtRunLVL0Controllers(); + + virtual void rtSwitchLVL0Controller(std::size_t index, LVL0ControllerBase* oldLVL0, LVL0ControllerBase* newLVL0) = 0; + //checks (rt) + virtual bool rtValidateLVL0ControllerSetup() const; //units (ice) virtual KinematicUnitInterfacePrx getKinematicUnit(const Ice::Current& = GlobalIceCurrent) const = 0; virtual ForceTorqueUnitInterfacePrx getForceTorqueUnit(const Ice::Current& = GlobalIceCurrent) const = 0; virtual InertialMeasurementUnitInterfacePrx getInertialMeasurementUnit(const Ice::Current& = GlobalIceCurrent) const = 0; virtual PlatformUnitInterfacePrx getPlatformUnitInterface(const Ice::Current& = GlobalIceCurrent) const = 0; - //units (rt) - virtual const ForceTorqueDataUnitInterface& getRTForceTorqueDataUnit() const = 0; - virtual const HapticDataUnitInterface& getRTHapticDataUnit() const = 0; - virtual const IMUDataUnitInterface& getRTIMUDataUnit() const = 0; - virtual const KinematicDataUnitInterface& getRTKinematicDataUnit() const = 0; - virtual const PlatformDataUnitInterface& getRTPlatformDataUnit() const = 0; - //targets + //units (ice but results are used in rt) + virtual const ForceTorqueDataUnitInterface* getRTForceTorqueDataUnit() const = 0; + virtual const HapticDataUnitInterface* getRTHapticDataUnit() const = 0; + virtual const IMUDataUnitInterface* getRTIMUDataUnit() const = 0; + virtual const KinematicDataUnitInterface* getRTKinematicDataUnit() const = 0; + virtual const PlatformDataUnitInterface* getRTPlatformDataUnit() const = 0; + //targets (ice) JointTargetBase* getJointTarget(const std::string& jointName, const std::string& controlMode); protected: - /** - * @see PropertyUser::createPropertyDefinitions() - */ + /// @see PropertyUser::createPropertyDefinitions() virtual armarx::PropertyDefinitionsPtr createPropertyDefinitions() override; /** @@ -238,44 +274,41 @@ namespace armarx * @throw If you add two controllers withe the same control mode for one joint, an std::invalid_argument exception is thrown. */ void addLVL0Controller(const std::string& jointName, LVL0ControllerBase& lvl0Controller); - /** - * @return The LVL0Controller for given joint and control mode. - */ + + /// @return The LVL0Controller for given joint and control mode. const LVL0ControllerBase& getLVL0Controller(const std::string& jointName, const std::string& controlMode) const; - /** - * @return The LVL0Controller for given joint and control mode. - */ + + /// @return The LVL0Controller for given joint and control mode. LVL0ControllerBase& getLVL0Controller(const std::string& jointName, const std::string& controlMode); - /** - * @return Whether a LVL0Controller for given joint and control mode exists. - */ + + /// @return Whether a LVL0Controller for given joint and control mode exists. bool hasLVL0Controller(const std::string& jointName, const std::string& controlMode) const; - /** - * @return Whether a LVL1Controller for this name is loaded. - */ + /// @return Whether a LVL1Controller for this name is loaded. bool hasLVL1Controller(const std::string& name) const; - - static void setLVL1ControllerActive(const LVL1ControllerPtr& lvl1, bool isActive = 1) - { - lvl1->isActive = isActive; - } + static void setLVL1ControllerActive(const LVL1ControllerPtr& lvl1, bool isActive = 1); struct LVL0AndLVL1ControllerList { + LVL0AndLVL1ControllerList(std::size_t size): + lvl0Controllers{size,nullptr}, + lvl1Controllers{size,nullptr} + {} + + LVL0AndLVL1ControllerList() = default; + LVL0AndLVL1ControllerList(const LVL0AndLVL1ControllerList&) = default; + std::vector<LVL0ControllerBase*> lvl0Controllers; std::vector<LVL1ControllerPtr > lvl1Controllers; }; mutable MutexType dataMutex; //data accessible in RT and nonRT const std::vector<std::string> jointNames; + const std::unordered_map<std::string, std::size_t> jointNameIndices; + /// @brief std::atomic_bool switchSetupError {false}; //used to communicate with rt - /// @brief Controllers the RT thread is supposed to activate (direction nonRT -> RT) - TripleBuffer<LVL0AndLVL1ControllerList> controllersRequested; - /// @brief Controllers the RT thread is currently running (direction RT -> nonRT) - TripleBuffer<LVL0AndLVL1ControllerList> controllersActivated; //non rt data /** * @brief Holds pointer to all lvl0 controllers. (index: [jointname][controlmode]) @@ -292,7 +325,14 @@ namespace armarx private: bool loadLibFromAbsolutePath(const std::string& path); + /// @brief Stores joints accessed via getJointTarget JointNameToControlModeDictionary jointsUsedByLVL1Controler; + /// @brief Controllers the RT thread is supposed to activate (direction nonRT -> RT) (some lvl1 controllers may be null) + TripleBuffer<LVL0AndLVL1ControllerList> controllersRequested; + /// @brief Controllers the RT thread is currently running (direction RT -> nonRT) (some lvl1 controllers may be null) + TripleBuffer<LVL0AndLVL1ControllerList> controllersActivated; + /// @brief LVL0Controllers for Emergency stop + std::vector<LVL0ControllerBase*> lvl0ControllersEmergencyStop; }; using RobotUnitPtr = IceInternal::Handle<RobotUnit>; diff --git a/source/RobotAPI/libraries/Controllers/SyntaxCheck.cpp b/source/RobotAPI/libraries/RobotRTControllers/SyntaxCheck.cpp similarity index 100% rename from source/RobotAPI/libraries/Controllers/SyntaxCheck.cpp rename to source/RobotAPI/libraries/RobotRTControllers/SyntaxCheck.cpp diff --git a/source/RobotAPI/libraries/Controllers/Targets/JointPositionTarget.h b/source/RobotAPI/libraries/RobotRTControllers/Targets/JointPositionTarget.h similarity index 91% rename from source/RobotAPI/libraries/Controllers/Targets/JointPositionTarget.h rename to source/RobotAPI/libraries/RobotRTControllers/Targets/JointPositionTarget.h index e599de3fc..6e7205de9 100644 --- a/source/RobotAPI/libraries/Controllers/Targets/JointPositionTarget.h +++ b/source/RobotAPI/libraries/RobotRTControllers/Targets/JointPositionTarget.h @@ -28,12 +28,12 @@ namespace armarx { /** - * @defgroup Library-Controllers Controllers + * @defgroup Library-RobotRTControllers RobotRTControllers * @ingroup RobotAPI - * A description of the library Controllers. + * A description of the library RobotRTControllers. * * @class JointPositionTarget - * @ingroup Library-Controllers + * @ingroup Library-RobotRTControllers * @brief Brief description of class JointPositionTarget. * * Detailed description of class JointPositionTarget. diff --git a/source/RobotAPI/libraries/Controllers/Targets/JointTargetBase.h b/source/RobotAPI/libraries/RobotRTControllers/Targets/JointTargetBase.h similarity index 90% rename from source/RobotAPI/libraries/Controllers/Targets/JointTargetBase.h rename to source/RobotAPI/libraries/RobotRTControllers/Targets/JointTargetBase.h index eb1d49e79..3f9736b89 100644 --- a/source/RobotAPI/libraries/Controllers/Targets/JointTargetBase.h +++ b/source/RobotAPI/libraries/RobotRTControllers/Targets/JointTargetBase.h @@ -30,12 +30,12 @@ namespace armarx { /** - * @defgroup Library-Controllers Controllers + * @defgroup Library-RobotRTControllers RobotRTControllers * @ingroup RobotAPI - * A description of the library Controllers. + * A description of the library RobotRTControllers. * * @class JointTargetBase - * @ingroup Library-Controllers + * @ingroup Library-RobotRTControllers * @brief Brief description of class JointTargetBase. * * Detailed description of class JointTargetBase. diff --git a/source/RobotAPI/libraries/Controllers/Targets/JointTorqueTarget.h b/source/RobotAPI/libraries/RobotRTControllers/Targets/JointTorqueTarget.h similarity index 91% rename from source/RobotAPI/libraries/Controllers/Targets/JointTorqueTarget.h rename to source/RobotAPI/libraries/RobotRTControllers/Targets/JointTorqueTarget.h index ab7548ba1..9421f2218 100644 --- a/source/RobotAPI/libraries/Controllers/Targets/JointTorqueTarget.h +++ b/source/RobotAPI/libraries/RobotRTControllers/Targets/JointTorqueTarget.h @@ -28,12 +28,12 @@ namespace armarx { /** - * @defgroup Library-Controllers Controllers + * @defgroup Library-RobotRTControllers RobotRTControllers * @ingroup RobotAPI - * A description of the library Controllers. + * A description of the library RobotRTControllers. * * @class JointTorqueTarget - * @ingroup Library-Controllers + * @ingroup Library-RobotRTControllers * @brief Brief description of class JointTorqueTarget. * * Detailed description of class JointTorqueTarget. diff --git a/source/RobotAPI/libraries/Controllers/Targets/JointVelocityTarget.h b/source/RobotAPI/libraries/RobotRTControllers/Targets/JointVelocityTarget.h similarity index 91% rename from source/RobotAPI/libraries/Controllers/Targets/JointVelocityTarget.h rename to source/RobotAPI/libraries/RobotRTControllers/Targets/JointVelocityTarget.h index 7c5d3100f..a4b307de9 100644 --- a/source/RobotAPI/libraries/Controllers/Targets/JointVelocityTarget.h +++ b/source/RobotAPI/libraries/RobotRTControllers/Targets/JointVelocityTarget.h @@ -28,12 +28,12 @@ namespace armarx { /** - * @defgroup Library-Controllers Controllers + * @defgroup Library-RobotRTControllers RobotRTControllers * @ingroup RobotAPI - * A description of the library Controllers. + * A description of the library RobotRTControllers. * * @class JointVelocityTarget - * @ingroup Library-Controllers + * @ingroup Library-RobotRTControllers * @brief Brief description of class JointVelocityTarget. * * Detailed description of class JointVelocityTarget. -- GitLab