35 const std::string Devices::rtThreadTimingsSensorDeviceName =
"RTThreadTimings";
37 ControlDeviceDescription
42 std::lock_guard<MutexType> guard{controlDevicesMutex};
43 if (!controlDevices.has(name))
46 ss <<
"getControlDeviceDescription: There is no ControlDevice '" << name
47 <<
"'. There are these ControlDevices: " << controlDevices.keys();
48 throw InvalidArgumentException{ss.str()};
53 ControlDeviceDescriptionSeq
61 std::lock_guard<MutexType> guard{controlDevicesMutex};
62 ControlDeviceDescriptionSeq r;
64 for (
auto idx :
getIndices(controlDevices.values()))
77 return controlDevices.size();
85 return sensorDevices.size();
93 std::lock_guard<MutexType> guard{sensorDevicesMutex};
95 return sensorDevices.index(deviceName);
103 std::lock_guard<MutexType> guard{controlDevicesMutex};
105 return controlDevices.index(deviceName);
113 std::lock_guard<MutexType> guard{sensorDevicesMutex};
122 std::lock_guard<MutexType> guard{controlDevicesMutex};
131 std::lock_guard<MutexType> guard{controlDevicesMutex};
132 return controlDevices.keys();
135 ControlDeviceDescription
140 std::lock_guard<MutexType> guard{controlDevicesMutex};
141 const ControlDevicePtr& controlDevice = controlDevices.at(idx);
142 ControlDeviceDescription
data;
143 data.deviceName = controlDevice->getDeviceName();
144 data.tags.assign(controlDevice->getTags().begin(), controlDevice->getTags().end());
145 for (
const auto& jointCtrl : controlDevice->getJointControllers())
147 data.contolModeToTargetType[jointCtrl->getControlMode()].targetType =
148 jointCtrl->getControlTarget()->getControlTargetType();
149 data.contolModeToTargetType[jointCtrl->getControlMode()].hardwareControlMode =
150 jointCtrl->getHardwareControlMode();
161 std::lock_guard<MutexType> guard{controlDevicesMutex};
162 const ControlDevicePtr& controlDevice = controlDevices.at(idx);
163 ControlDeviceStatus
status;
164 const auto activeJointCtrl =
166 status.activeControlMode = activeJointCtrl ? activeJointCtrl->getControlMode()
167 : std::string{
"!!JointController is nullptr!!"};
168 status.deviceName = controlDevice->getDeviceName();
169 const auto requestedJointControllers =
172 status.requestedControlMode = requestedJointControllers.at(idx)->getControlMode();
173 for (
const auto& targ :
176 status.controlTargetValues[targ->getControlMode()] =
178 .getSensorAndControlBuffer()
179 .sensorValuesTimestamp);
191 std::lock_guard<MutexType> guard{controlDevicesMutex};
192 if (!controlDevices.has(name))
194 std::stringstream ss;
195 ss <<
"getControlDeviceStatus: There is no ControlDevice '" << name
196 <<
"'. There are these ControlDevices: " << controlDevices.keys();
197 throw InvalidArgumentException{ss.str()};
202 ControlDeviceStatusSeq
210 std::lock_guard<MutexType> guard{controlDevicesMutex};
211 ControlDeviceStatusSeq r;
213 for (
auto idx :
getIndices(controlDevices.values()))
226 std::lock_guard<MutexType> guard{sensorDevicesMutex};
227 return sensorDevices.keys();
230 SensorDeviceDescription
235 std::lock_guard<MutexType> guard{sensorDevicesMutex};
236 const SensorDevicePtr& sensorDevice = sensorDevices.at(idx);
237 SensorDeviceDescription
data;
238 data.deviceName = sensorDevice->getDeviceName();
239 data.tags.assign(sensorDevice->getTags().begin(), sensorDevice->getTags().end());
240 data.sensorValueType = sensorDevice->getSensorValueType();
250 std::lock_guard<MutexType> guard{sensorDevicesMutex};
251 const SensorDevicePtr& sensorDevice = sensorDevices.at(idx);
252 SensorDeviceStatus
status;
253 status.deviceName = sensorDevice->getDeviceName();
255 .getSensorAndControlBuffer()
258 .getSensorAndControlBuffer()
259 .sensorValuesTimestamp);
265 SensorDeviceDescription
270 std::lock_guard<MutexType> guard{sensorDevicesMutex};
271 if (!sensorDevices.has(name))
273 std::stringstream ss;
274 ss <<
"getSensorDeviceDescription: There is no SensorDevice '" << name
275 <<
"'. There are these SensorDevices: " << sensorDevices.keys();
276 throw InvalidArgumentException{ss.str()};
281 SensorDeviceDescriptionSeq
285 std::lock_guard<MutexType> guard{sensorDevicesMutex};
290 SensorDeviceDescriptionSeq r;
292 for (
auto idx :
getIndices(sensorDevices.values()))
304 std::lock_guard<MutexType> guard{sensorDevicesMutex};
305 if (!sensorDevices.has(name))
307 std::stringstream ss;
308 ss <<
"getSensorDeviceStatus: There is no SensorDevice '" << name
309 <<
"'. There are these SensorDevices: " << sensorDevices.keys();
310 throw InvalidArgumentException{ss.str()};
315 SensorDeviceStatusSeq
323 std::lock_guard<MutexType> guard{sensorDevicesMutex};
324 SensorDeviceStatusSeq r;
326 for (
auto idx :
getIndices(sensorDevices.values()))
341 std::lock_guard<MutexType> guard{controlDevicesMutex};
345 std::stringstream ss;
346 ss <<
"armarx::RobotUnit::addControlDevice: ControlDevice is nullptr";
348 throw InvalidArgumentException{ss.str()};
350 if (!cd->getJointEmergencyStopController())
352 std::stringstream ss;
353 ss <<
"armarx::RobotUnit::addControlDevice: ControlDevice " << cd->getDeviceName()
354 <<
" has null JointEmergencyStopController (this is not allowed)";
356 throw InvalidArgumentException{ss.str()};
358 if (!cd->getJointStopMovementController())
360 std::stringstream ss;
361 ss <<
"armarx::RobotUnit::addControlDevice: ControlDevice " << cd->getDeviceName()
362 <<
" has null getJointStopMovementController (this is not allowed)";
364 throw InvalidArgumentException{ss.str()};
367 ARMARX_DEBUG <<
"Adding the ControlDevice " << cd->getDeviceName() <<
" " << &cd;
368 controlDevices.add(cd->getDeviceName(), cd);
370 ARMARX_INFO <<
"added ControlDevice " << cd->getDeviceName();
372 ARMARX_INFO <<
"added ControlDevice " << cd->getDeviceName();
383 std::lock_guard<MutexType> guard{sensorDevicesMutex};
387 std::stringstream ss;
388 ss <<
"armarx::RobotUnit::addSensorDevice: SensorDevice is nullptr";
390 throw InvalidArgumentException{ss.str()};
392 if (!sd->getSensorValue())
394 std::stringstream ss;
395 ss <<
"armarx::RobotUnit::addSensorDevice: SensorDevice " << sd->getDeviceName()
396 <<
" has null SensorValue (this is not allowed)";
398 throw InvalidArgumentException{ss.str()};
401 if (sd->getDeviceName() == rtThreadTimingsSensorDeviceName)
403 ARMARX_DEBUG <<
"Device is the " << rtThreadTimingsSensorDeviceName;
404 if (!std::dynamic_pointer_cast<RTThreadTimingsSensorDevice>(sd))
406 throw InvalidArgumentException{
407 "You tried to add a SensorDevice with the name " + sd->getDeviceName() +
408 " which does not derive from RTThreadTimingsSensorDevice. (Don't do this)"};
411 ARMARX_DEBUG <<
"Adding the SensorDevice " << sd->getDeviceName() <<
" " << &sd;
412 sensorDevices.add(sd->getDeviceName(), sd);
414 rtThreadTimingsSensorDevice =
415 std::dynamic_pointer_cast<RTThreadTimingsSensorDevice>(sd);
419 ARMARX_DEBUG <<
"Device is the " << sd->getDeviceName();
420 if (!std::dynamic_pointer_cast<GlobalRobotLocalizationSensorDevice>(sd))
422 throw InvalidArgumentException{
423 "You tried to add a SensorDevice with the name " + sd->getDeviceName() +
424 " which does not derive from GlobalRobotLocalizationSensorDevice. (Don't "
428 ARMARX_DEBUG <<
"Adding the SensorDevice " << sd->getDeviceName() <<
" " << &sd;
429 sensorDevices.add(sd->getDeviceName(), sd);
431 globalRobotLocalizationSensorDevice =
436 ARMARX_DEBUG <<
"Adding the SensorDevice " << sd->getDeviceName() <<
" " << &sd;
437 sensorDevices.add(sd->getDeviceName(), sd);
441 ARMARX_INFO <<
"added SensorDevice " << sd->getDeviceName()
442 <<
" (valuetype = " << sd->getSensorValueType() <<
")";
446 RTThreadTimingsSensorDevicePtr
450 return std::make_shared<RTThreadTimingsSensorDeviceImpl<>>(rtThreadTimingsSensorDeviceName);
454 Devices::_postFinishRunning()
457 std::lock_guard<MutexType> guardS{sensorDevicesMutex};
458 std::lock_guard<MutexType> guardC{controlDevicesMutex};
459 controlDevicesConstPtr.clear();
460 sensorDevicesConstPtr.clear();
461 sensorDevices.
clear();
462 controlDevices.
clear();
465 std::vector<JointController*>
466 Devices::getStopMovementJointControllers()
const
470 std::lock_guard<MutexType> guard{controlDevicesMutex};
471 std::vector<JointController*> controllers;
472 controllers.reserve(controlDevices.values().size());
473 for (
const ControlDevicePtr& dev : controlDevices.values())
476 controllers.emplace_back(dev->rtGetJointStopMovementController());
484 std::vector<JointController*>
485 Devices::getEmergencyStopJointControllers()
const
489 std::lock_guard<MutexType> guard{controlDevicesMutex};
490 std::vector<JointController*> controllers;
491 controllers.reserve(controlDevices.values().size());
492 for (
const ControlDevicePtr& dev : controlDevices.values())
495 controllers.emplace_back(dev->rtGetJointEmergencyStopController());
504 Devices::_preFinishDeviceInitialization()
507 std::lock_guard<MutexType> guardS{sensorDevicesMutex};
508 std::lock_guard<MutexType> guardC{controlDevicesMutex};
509 if (!sensorDevices.has(rtThreadTimingsSensorDeviceName))
518 addSensorDevice(std::make_shared<GlobalRobotPoseCorrectionSensorDevice>());
519 addSensorDevice(std::make_shared<GlobalRobotLocalizationSensorDevice>());
524 Devices::_postFinishDeviceInitialization()
528 std::lock_guard<MutexType> guardS{sensorDevicesMutex};
529 std::lock_guard<MutexType> guardC{controlDevicesMutex};
530 ARMARX_DEBUG <<
"checking " << controlDevices.size() <<
" ControlDevices:";
533 for (
const ControlDevicePtr& controlDevice : controlDevices.values())
536 ARMARX_DEBUG <<
"----" << controlDevice->getDeviceName();
537 if (!controlDevice->hasJointController(ControlModes::EmergencyStop))
540 s <<
"ControlDevice " << controlDevice->getDeviceName()
541 <<
" has no JointController with ControlMode " << ControlModes::EmergencyStop
542 <<
" (to fix this, add a JointController with this ControlMode to the "
543 "ControlDevice).\nAvailable controllers: "
544 << controlDevice->getControlModes();
546 throw LogicError{
s.str()};
548 if (!controlDevice->hasJointController(ControlModes::StopMovement))
551 s <<
"ControlDevice " << controlDevice->getDeviceName()
552 <<
" has no JointController with ControlMode \"" << ControlModes::StopMovement
553 <<
"\" (to fix this, add a JointController with this ControlMode to the "
554 "ControlDevice) \nAvailable controllers: "
555 << controlDevice->getControlModes();
557 throw LogicError{
s.str()};
561 ARMARX_DEBUG <<
"checking " << controlDevices.size() <<
" SensorDevices:";
564 for (
const SensorDevicePtr& sensorDevice : sensorDevices.values())
567 ARMARX_DEBUG <<
"----" << sensorDevice->getDeviceName();
568 if (!sensorDevice->getSensorValue())
571 s <<
"SensorDevice " << sensorDevice->getSensorValue()
572 <<
" has null SensorValue";
574 throw LogicError{
s.str()};
582 for (
const auto& dev : controlDevices.values())
584 controlDevicesConstPtr[dev->getDeviceName()] = dev;
586 for (
const auto& dev : sensorDevices.values())
588 sensorDevicesConstPtr[dev->getDeviceName()] = dev;
595 sensorValues.reserve(sensorDevices.values().size());
596 for (
const SensorDevicePtr& dev : sensorDevices.values())
599 sensorValues.emplace_back(dev->getSensorValue());
607 controlTargets.reserve(controlDevices.values().size());
608 for (
const ControlDevicePtr& dev : controlDevices.values())
611 controlTargets.emplace_back();
612 controlTargets.back().reserve(dev->rtGetJointControllers().size());
613 for (JointController* ctrl : dev->rtGetJointControllers())
616 controlTargets.back().emplace_back(ctrl->getControlTarget());
621 ARMARX_DEBUG <<
"setup ControlDeviceHardwareControlModeGroups";
626 if (!ctrlModeGroups.groupsMerged.empty())
628 ARMARX_DEBUG <<
"Remove control devs from ControlDeviceHardwareControlModeGroups ("
629 << ctrlModeGroups.groups.size() <<
")";
630 const auto groupsMerged = ctrlModeGroups.groupsMerged;
631 for (
const auto& dev : groupsMerged)
633 if (controlDevices.has(dev))
637 ctrlModeGroups.groupsMerged.erase(dev);
638 for (
auto& group : ctrlModeGroups.groups)
642 ARMARX_DEBUG <<
"----removing nonexistent device: " << dev;
645 std::vector<std::set<std::string>> cleanedGroups;
646 cleanedGroups.reserve(ctrlModeGroups.groups.size());
647 for (
auto& group : ctrlModeGroups.groups)
649 const auto sz = group.size();
652 ARMARX_DEBUG <<
"----removing group with one dev: " << *group.begin();
656 cleanedGroups.emplace_back(std::move(group));
659 ctrlModeGroups.groups = cleanedGroups;
660 ARMARX_DEBUG <<
"----number of groups left: " << ctrlModeGroups.groups.size();
662 if (!ctrlModeGroups.groupsMerged.empty())
665 <<
"Checking control modes for ControlDeviceHardwareControlModeGroups ("
666 << ctrlModeGroups.groups.size() <<
")";
667 ctrlModeGroups.deviceIndices.resize(ctrlModeGroups.groups.size());
669 for (std::size_t groupIdx = 0; groupIdx < ctrlModeGroups.groups.size(); ++groupIdx)
671 const std::set<std::string>& group = ctrlModeGroups.groups.at(groupIdx);
672 ctrlModeGroups.deviceIndices.at(groupIdx).reserve(group.size());
674 ARMARX_DEBUG <<
"----Group " << groupIdx <<
" size: " << group.size();
676 const auto getControlModeToHWControlMode = [&](
const std::string& devname)
678 std::map<std::string, std::string> controlModeToHWControlMode;
679 const ControlDevicePtr& cd = controlDevices.at(devname);
680 for (
const auto& jointCtrl : cd->getJointControllers())
682 controlModeToHWControlMode[jointCtrl->getControlMode()] =
683 jointCtrl->getHardwareControlMode();
685 return controlModeToHWControlMode;
688 const auto controlModeToHWControlMode =
689 getControlModeToHWControlMode(*group.begin());
691 for (
const auto& devname : group)
694 <<
"The ControlDeviceHardwareControlModeGroups property contains "
695 "device names not existent in the robot: "
696 << devname <<
"\navailable:\n"
697 << controlDevices.keys();
699 const auto controlModeToHWControlModeForDevice =
700 getControlModeToHWControlMode(devname);
702 controlModeToHWControlMode)
703 <<
"Error for control modes of device '" << devname <<
"'\n"
704 <<
"it has the modes: " << controlModeToHWControlModeForDevice
705 <<
"\n but should have the modes: " << controlModeToHWControlMode;
707 const auto devIdx = controlDevices.index(devname);
708 ctrlModeGroups.deviceIndices.at(groupIdx).emplace_back(devIdx);
713 ctrlModeGroups.groupIndices.at(devIdx) = groupIdx;
719 ARMARX_DEBUG <<
"create mapping from sensor values to robot nodes";
724 const auto nodes = r->getRobotNodes();
725 for (std::size_t idxRobot = 0; idxRobot < nodes.size(); ++idxRobot)
727 const VirtualRobot::RobotNodePtr& node = nodes.at(idxRobot);
730 const auto& name = node->getName();
731 if (sensorDevices.has(name))
733 const auto& dev = sensorDevices.at(name);
734 if (dev->getSensorValue()->isA<SensorValue1DoFActuatorPosition>())
736 SimoxRobotSensorValueMapping m;
737 m.idxRobot = idxRobot;
738 m.idxSens = sensorDevices.index(name);
739 simoxRobotSensorValueMapping.emplace_back(m);
744 <<
"SensorValue for SensorDevice " << name <<
" is of type "
745 << dev->getSensorValueType()
746 <<
" which does not derive SensorValue1DoFActuatorPosition";
751 ARMARX_INFO <<
"No SensorDevice for RobotNode: " << name;
762 Devices::_preOnInitRobotUnit()
766 const std::string controlDeviceHardwareControlModeGroupsStr =
768 if (!controlDeviceHardwareControlModeGroupsStr.empty())
770 const auto numGroups = std::count(controlDeviceHardwareControlModeGroupsStr.begin(),
771 controlDeviceHardwareControlModeGroupsStr.end(),
774 ctrlModeGroups.groups.reserve(numGroups);
775 std::vector<std::string> strGroups =
776 Split(controlDeviceHardwareControlModeGroupsStr,
";");
777 for (
const auto& gstr : strGroups)
779 bool trimDeviceNames =
true;
780 std::vector<std::string> strElems =
Split(gstr,
",", trimDeviceNames);
781 std::set<std::string> group;
782 for (
auto& device : strElems)
785 <<
"The ControlDeviceHardwareControlModeGroups property contains empty "
788 <<
"The ControlDeviceHardwareControlModeGroups property contains duplicate "
791 ctrlModeGroups.groupsMerged.emplace(device);
792 group.emplace(std::move(device));
798 for (
const auto& elem : group)
800 out <<
" " << elem <<
"\n";
803 ctrlModeGroups.groups.emplace_back(std::move(group));
#define ARMARX_STREAM_PRINTER
use this macro to write output code that is executed when printed and thus not executed if the debug ...
Property< PropertyType > getProperty(const std::string &name)
static const ControlDevicePtr NullPtr
A static const nullptr in case a const ref to a nullptr needs to be returned.
static std::string DeviceName()
Property< PropertyType > getProperty(const std::string &name)
Property creation and retrieval.
Ice::StringSeq getSensorDeviceNames(const Ice::Current &=Ice::emptyCurrent) const override
Returns the names of all SensorDevices for the robot.
Ice::StringSeq getControlDeviceNames(const Ice::Current &=Ice::emptyCurrent) const override
Returns the names of all ControlDevices for the robot.
ControlDeviceDescription getControlDeviceDescription(const std::string &name, const Ice::Current &=Ice::emptyCurrent) const override
Return the ControlDeviceDescription for the given ControlDevice.
SensorDeviceDescription getSensorDeviceDescription(const std::string &name, const Ice::Current &=Ice::emptyCurrent) const override
Return the SensorDeviceDescription for the given SensorDevice.
void addSensorDevice(const SensorDevicePtr &sd)
Adds a SensorDevice to the robot.
void addControlDevice(const ControlDevicePtr &cd)
Adds a ControlDevice to the robot.
std::size_t getNumberOfControlDevices() const
Returns the number of ControlDevices.
SensorDeviceDescriptionSeq getSensorDeviceDescriptions(const Ice::Current &=Ice::emptyCurrent) const override
Return the SensorDeviceDescriptions for all SensorDevices.
ControlDeviceStatusSeq getControlDeviceStatuses(const Ice::Current &=Ice::emptyCurrent) const override
Return the ControlDeviceStatuses for all ControlDevices.
std::size_t getSensorDeviceIndex(const std::string &deviceName) const
Returns the SensorDevice's index.
SensorDeviceStatusSeq getSensorDeviceStatuses(const Ice::Current &=Ice::emptyCurrent) const override
Return the SensorDeviceStatuses for all SensorDevices.
ConstSensorDevicePtr getSensorDevice(const std::string &deviceName) const
TODO move to attorney for NJointControllerBase.
ConstControlDevicePtr getControlDevice(const std::string &deviceName) const
Returns the ControlDevice.
virtual RTThreadTimingsSensorDevicePtr createRTThreadTimingSensorDevice() const
Creates the SensorDevice used to log timings in the ControlThread (This function is supposed to be us...
std::size_t getControlDeviceIndex(const std::string &deviceName) const
Returns the ControlDevice's index.
ControlDeviceStatus getControlDeviceStatus(const std::string &name, const Ice::Current &=Ice::emptyCurrent) const override
Return the ControlDeviceStatus for the given ControlDevice.
ControlDeviceDescriptionSeq getControlDeviceDescriptions(const Ice::Current &=Ice::emptyCurrent) const override
Return the ControlDeviceDescriptions for all ControlDevices.
SensorDeviceStatus getSensorDeviceStatus(const std::string &name, const Ice::Current &=Ice::emptyCurrent) const override
Return the SensorDeviceStatus for the given SensorDevice.
std::size_t getNumberOfSensorDevices() const
Returns the number of SensorDevices.
T & _module()
Returns this as ref to the given type.
bool areDevicesReady() const
Returns whether Devices are ready.
void throwIfInControlThread(const std::string &fnc) const
Throws if the current thread is the ControlThread.
void throwIfStateIsNot(const std::set< RobotUnitState > &stateSet, const std::string &fnc, bool onlyWarn=false) const
Throws an exception if the current state is not in.
static constexpr std::size_t IndexSentinel()
Returns a sentinel value for an index (std::numeric_limits<std::size_t>::max())
void throwIfDevicesNotReady(const std::string &fnc) const
Throws if the Devices are not ready.
static const SensorDevicePtr NullPtr
A static const nullptr in case a const ref to a nullptr needs to be returned.
static IceUtil::Time GetTime(TimeMode timeMode=TimeMode::VirtualTime)
Get the current time.
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
#define ARMARX_CHECK_NOT_NULL(ptr)
This macro evaluates whether ptr is not null and if it turns out to be false it will throw an Express...
#define ARMARX_CHECK_EQUAL(lhs, rhs)
This macro evaluates whether lhs is equal (==) rhs and if it turns out to be false it will throw an E...
#define ARMARX_INFO
The normal logging level.
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
#define ARMARX_VERBOSE
The logging level for verbose information.
std::shared_ptr< class Robot > RobotPtr
T getValue(nlohmann::json &userConfig, nlohmann::json &defaultConfig, const std::string &entryName)
double s(double t, double s0, double v0, double a0, double j)
std::vector< KeyT > getIndices(const std::map< KeyT, ValT > &c)
std::vector< std::string > Split(const std::string &source, const std::string &splitBy, bool trimElements=false, bool removeEmptyElements=false)
std::shared_ptr< const class ControlDevice > ConstControlDevicePtr
std::shared_ptr< const class SensorDevice > ConstSensorDevicePtr
This file is part of ArmarX.