RobotUnitModuleDevices.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * ArmarX is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * ArmarX is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  *
16  * @package RobotAPI::ArmarXObjects::RobotUnit
17  * @author Raphael Grimm ( raphael dot grimm at kit dot edu )
18  * @date 2018
19  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20  * GNU General Public License
21  */
22 
23 #include "RobotUnitModuleDevices.h"
24 
27 
29 
32 
34 {
35  const std::string Devices::rtThreadTimingsSensorDeviceName = "RTThreadTimings";
36 
37  ControlDeviceDescription
38  Devices::getControlDeviceDescription(const std::string& name, const Ice::Current&) const
39  {
40  throwIfInControlThread(BOOST_CURRENT_FUNCTION);
41  throwIfDevicesNotReady(__FUNCTION__);
42  std::lock_guard<MutexType> guard{controlDevicesMutex};
43  if (!controlDevices.has(name))
44  {
45  std::stringstream ss;
46  ss << "getControlDeviceDescription: There is no ControlDevice '" << name
47  << "'. There are these ControlDevices: " << controlDevices.keys();
48  throw InvalidArgumentException{ss.str()};
49  }
50  return getControlDeviceDescription(controlDevices.index(name));
51  }
52 
53  ControlDeviceDescriptionSeq
54  Devices::getControlDeviceDescriptions(const Ice::Current&) const
55  {
56  throwIfInControlThread(BOOST_CURRENT_FUNCTION);
57  if (!areDevicesReady())
58  {
59  return {};
60  }
61  std::lock_guard<MutexType> guard{controlDevicesMutex};
62  ControlDeviceDescriptionSeq r;
63  r.reserve(getNumberOfControlDevices());
64  for (auto idx : getIndices(controlDevices.values()))
65  {
66  r.emplace_back(getControlDeviceDescription(idx));
67  }
68  throwIfDevicesNotReady(__FUNCTION__);
69  return r;
70  }
71 
72  std::size_t
74  {
75  throwIfInControlThread(BOOST_CURRENT_FUNCTION);
76  throwIfDevicesNotReady(__FUNCTION__);
77  return controlDevices.size();
78  }
79 
80  std::size_t
82  {
83  throwIfInControlThread(BOOST_CURRENT_FUNCTION);
84  throwIfDevicesNotReady(__FUNCTION__);
85  return sensorDevices.size();
86  }
87 
88  std::size_t
89  Devices::getSensorDeviceIndex(const std::string& deviceName) const
90  {
91  throwIfInControlThread(BOOST_CURRENT_FUNCTION);
92  throwIfDevicesNotReady(__FUNCTION__);
93  std::lock_guard<MutexType> guard{sensorDevicesMutex};
94  ARMARX_CHECK_EXPRESSION(sensorDevices.has(deviceName));
95  return sensorDevices.index(deviceName);
96  }
97 
98  std::size_t
99  Devices::getControlDeviceIndex(const std::string& deviceName) const
100  {
101  throwIfInControlThread(BOOST_CURRENT_FUNCTION);
102  throwIfDevicesNotReady(__FUNCTION__);
103  std::lock_guard<MutexType> guard{controlDevicesMutex};
104  ARMARX_CHECK_EXPRESSION(controlDevices.has(deviceName));
105  return controlDevices.index(deviceName);
106  }
107 
109  Devices::getSensorDevice(const std::string& sensorDeviceName) const
110  {
111  throwIfInControlThread(BOOST_CURRENT_FUNCTION);
112  throwIfDevicesNotReady(__FUNCTION__);
113  std::lock_guard<MutexType> guard{sensorDevicesMutex};
114  return sensorDevices.at(sensorDeviceName, SensorDevice::NullPtr);
115  }
116 
118  Devices::getControlDevice(const std::string& deviceName) const
119  {
120  throwIfInControlThread(BOOST_CURRENT_FUNCTION);
121  throwIfDevicesNotReady(__FUNCTION__);
122  std::lock_guard<MutexType> guard{controlDevicesMutex};
123  return controlDevices.at(deviceName, ControlDevice::NullPtr);
124  }
125 
126  Ice::StringSeq
127  Devices::getControlDeviceNames(const Ice::Current&) const
128  {
129  throwIfInControlThread(BOOST_CURRENT_FUNCTION);
130  throwIfDevicesNotReady(__FUNCTION__);
131  std::lock_guard<MutexType> guard{controlDevicesMutex};
132  return controlDevices.keys();
133  }
134 
135  ControlDeviceDescription
137  {
138  throwIfInControlThread(BOOST_CURRENT_FUNCTION);
139  throwIfDevicesNotReady(__FUNCTION__);
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())
146  {
147  data.contolModeToTargetType[jointCtrl->getControlMode()].targetType =
148  jointCtrl->getControlTarget()->getControlTargetType();
149  data.contolModeToTargetType[jointCtrl->getControlMode()].hardwareControlMode =
150  jointCtrl->getHardwareControlMode();
151  }
152  throwIfDevicesNotReady(__FUNCTION__);
153  return data;
154  }
155 
156  ControlDeviceStatus
157  Devices::getControlDeviceStatus(std::size_t idx) const
158  {
159  throwIfInControlThread(BOOST_CURRENT_FUNCTION);
160  throwIfDevicesNotReady(__FUNCTION__);
161  std::lock_guard<MutexType> guard{controlDevicesMutex};
162  const ControlDevicePtr& controlDevice = controlDevices.at(idx);
163  ControlDeviceStatus status;
164  const auto activeJointCtrl =
165  _module<ControlThreadDataBuffer>().getActivatedJointControllers().at(idx);
166  status.activeControlMode = activeJointCtrl ? activeJointCtrl->getControlMode()
167  : std::string{"!!JointController is nullptr!!"};
168  status.deviceName = controlDevice->getDeviceName();
169  const auto requestedJointControllers =
170  _module<ControlThreadDataBuffer>().copyRequestedJointControllers();
171  ARMARX_CHECK_EXPRESSION(requestedJointControllers.at(idx));
172  status.requestedControlMode = requestedJointControllers.at(idx)->getControlMode();
173  for (const auto& targ :
174  _module<ControlThreadDataBuffer>().getSensorAndControlBuffer().control.at(idx))
175  {
176  status.controlTargetValues[targ->getControlMode()] =
177  targ->toVariants(_module<ControlThreadDataBuffer>()
178  .getSensorAndControlBuffer()
179  .sensorValuesTimestamp);
180  }
181  status.timestampUSec = TimeUtil::GetTime(true).toMicroSeconds();
182  throwIfDevicesNotReady(__FUNCTION__);
183  return status;
184  }
185 
186  ControlDeviceStatus
187  Devices::getControlDeviceStatus(const std::string& name, const Ice::Current&) const
188  {
189  throwIfInControlThread(BOOST_CURRENT_FUNCTION);
190  throwIfDevicesNotReady(__FUNCTION__);
191  std::lock_guard<MutexType> guard{controlDevicesMutex};
192  if (!controlDevices.has(name))
193  {
194  std::stringstream ss;
195  ss << "getControlDeviceStatus: There is no ControlDevice '" << name
196  << "'. There are these ControlDevices: " << controlDevices.keys();
197  throw InvalidArgumentException{ss.str()};
198  }
199  return getControlDeviceStatus(controlDevices.index(name));
200  }
201 
202  ControlDeviceStatusSeq
203  Devices::getControlDeviceStatuses(const Ice::Current&) const
204  {
205  throwIfInControlThread(BOOST_CURRENT_FUNCTION);
206  if (!areDevicesReady())
207  {
208  return {};
209  }
210  std::lock_guard<MutexType> guard{controlDevicesMutex};
211  ControlDeviceStatusSeq r;
212  r.reserve(getNumberOfControlDevices());
213  for (auto idx : getIndices(controlDevices.values()))
214  {
215  r.emplace_back(getControlDeviceStatus(idx));
216  }
217  throwIfDevicesNotReady(__FUNCTION__);
218  return r;
219  }
220 
221  Ice::StringSeq
222  Devices::getSensorDeviceNames(const Ice::Current&) const
223  {
224  throwIfInControlThread(BOOST_CURRENT_FUNCTION);
225  throwIfDevicesNotReady(__FUNCTION__);
226  std::lock_guard<MutexType> guard{sensorDevicesMutex};
227  return sensorDevices.keys();
228  }
229 
230  SensorDeviceDescription
231  Devices::getSensorDeviceDescription(std::size_t idx) const
232  {
233  throwIfInControlThread(BOOST_CURRENT_FUNCTION);
234  throwIfDevicesNotReady(__FUNCTION__);
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();
241  throwIfDevicesNotReady(__FUNCTION__);
242  return data;
243  }
244 
245  SensorDeviceStatus
246  Devices::getSensorDeviceStatus(std::size_t idx) const
247  {
248  throwIfInControlThread(BOOST_CURRENT_FUNCTION);
249  throwIfDevicesNotReady(__FUNCTION__);
250  std::lock_guard<MutexType> guard{sensorDevicesMutex};
251  const SensorDevicePtr& sensorDevice = sensorDevices.at(idx);
252  SensorDeviceStatus status;
253  status.deviceName = sensorDevice->getDeviceName();
254  status.sensorValue = _module<ControlThreadDataBuffer>()
255  .getSensorAndControlBuffer()
256  .sensors.at(idx)
257  ->toVariants(_module<ControlThreadDataBuffer>()
258  .getSensorAndControlBuffer()
259  .sensorValuesTimestamp);
260  status.timestampUSec = TimeUtil::GetTime(true).toMicroSeconds();
261  throwIfDevicesNotReady(__FUNCTION__);
262  return status;
263  }
264 
265  SensorDeviceDescription
266  Devices::getSensorDeviceDescription(const std::string& name, const Ice::Current&) const
267  {
268  throwIfInControlThread(BOOST_CURRENT_FUNCTION);
269  throwIfDevicesNotReady(__FUNCTION__);
270  std::lock_guard<MutexType> guard{sensorDevicesMutex};
271  if (!sensorDevices.has(name))
272  {
273  std::stringstream ss;
274  ss << "getSensorDeviceDescription: There is no SensorDevice '" << name
275  << "'. There are these SensorDevices: " << sensorDevices.keys();
276  throw InvalidArgumentException{ss.str()};
277  }
278  return getSensorDeviceDescription(sensorDevices.index(name));
279  }
280 
281  SensorDeviceDescriptionSeq
282  Devices::getSensorDeviceDescriptions(const Ice::Current&) const
283  {
284  throwIfInControlThread(BOOST_CURRENT_FUNCTION);
285  std::lock_guard<MutexType> guard{sensorDevicesMutex};
286  if (!areDevicesReady())
287  {
288  return {};
289  }
290  SensorDeviceDescriptionSeq r;
291  r.reserve(getNumberOfSensorDevices());
292  for (auto idx : getIndices(sensorDevices.values()))
293  {
294  r.emplace_back(getSensorDeviceDescription(idx));
295  }
296  return r;
297  }
298 
299  SensorDeviceStatus
300  Devices::getSensorDeviceStatus(const std::string& name, const Ice::Current&) const
301  {
302  throwIfInControlThread(BOOST_CURRENT_FUNCTION);
303  throwIfDevicesNotReady(__FUNCTION__);
304  std::lock_guard<MutexType> guard{sensorDevicesMutex};
305  if (!sensorDevices.has(name))
306  {
307  std::stringstream ss;
308  ss << "getSensorDeviceStatus: There is no SensorDevice '" << name
309  << "'. There are these SensorDevices: " << sensorDevices.keys();
310  throw InvalidArgumentException{ss.str()};
311  }
312  return getSensorDeviceStatus(sensorDevices.index(name));
313  }
314 
315  SensorDeviceStatusSeq
316  Devices::getSensorDeviceStatuses(const Ice::Current&) const
317  {
318  throwIfInControlThread(BOOST_CURRENT_FUNCTION);
319  if (!areDevicesReady())
320  {
321  return {};
322  }
323  std::lock_guard<MutexType> guard{sensorDevicesMutex};
324  SensorDeviceStatusSeq r;
325  r.reserve(getNumberOfSensorDevices());
326  for (auto idx : getIndices(sensorDevices.values()))
327  {
328  r.emplace_back(getSensorDeviceStatus(idx));
329  }
330  throwIfDevicesNotReady(__FUNCTION__);
331  return r;
332  }
333 
334  void
335  Devices::addControlDevice(const ControlDevicePtr& cd)
336  {
337  throwIfInControlThread(BOOST_CURRENT_FUNCTION);
338  ARMARX_DEBUG << "ControlDevice " << &cd;
340  {
341  std::lock_guard<MutexType> guard{controlDevicesMutex};
342  //check it
343  if (!cd)
344  {
345  std::stringstream ss;
346  ss << "armarx::RobotUnit::addControlDevice: ControlDevice is nullptr";
347  ARMARX_ERROR << ss.str();
348  throw InvalidArgumentException{ss.str()};
349  }
350  if (!cd->getJointEmergencyStopController())
351  {
352  std::stringstream ss;
353  ss << "armarx::RobotUnit::addControlDevice: ControlDevice " << cd->getDeviceName()
354  << " has null JointEmergencyStopController (this is not allowed)";
355  ARMARX_ERROR << ss.str();
356  throw InvalidArgumentException{ss.str()};
357  }
358  if (!cd->getJointStopMovementController())
359  {
360  std::stringstream ss;
361  ss << "armarx::RobotUnit::addControlDevice: ControlDevice " << cd->getDeviceName()
362  << " has null getJointStopMovementController (this is not allowed)";
363  ARMARX_ERROR << ss.str();
364  throw InvalidArgumentException{ss.str()};
365  }
366  //add it
367  ARMARX_DEBUG << "Adding the ControlDevice " << cd->getDeviceName() << " " << &cd;
368  controlDevices.add(cd->getDeviceName(), cd);
369  cd->owner = this;
370  ARMARX_INFO << "added ControlDevice " << cd->getDeviceName();
371  }
372  ARMARX_INFO << "added ControlDevice " << cd->getDeviceName();
374  }
375 
376  void
377  Devices::addSensorDevice(const SensorDevicePtr& sd)
378  {
379  throwIfInControlThread(BOOST_CURRENT_FUNCTION);
380  ARMARX_DEBUG << "SensorDevice " << &sd;
382  {
383  std::lock_guard<MutexType> guard{sensorDevicesMutex};
384  //check it
385  if (!sd)
386  {
387  std::stringstream ss;
388  ss << "armarx::RobotUnit::addSensorDevice: SensorDevice is nullptr";
389  ARMARX_ERROR << ss.str();
390  throw InvalidArgumentException{ss.str()};
391  }
392  if (!sd->getSensorValue())
393  {
394  std::stringstream ss;
395  ss << "armarx::RobotUnit::addSensorDevice: SensorDevice " << sd->getDeviceName()
396  << " has null SensorValue (this is not allowed)";
397  ARMARX_ERROR << ss.str();
398  throw InvalidArgumentException{ss.str()};
399  }
400  //add it
401  if (sd->getDeviceName() == rtThreadTimingsSensorDeviceName)
402  {
403  ARMARX_DEBUG << "Device is the " << rtThreadTimingsSensorDeviceName;
404  if (!std::dynamic_pointer_cast<RTThreadTimingsSensorDevice>(sd))
405  {
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)"};
409  }
410  //this checks if we already added such a device (do this before setting timingSensorDevice)
411  ARMARX_DEBUG << "Adding the SensorDevice " << sd->getDeviceName() << " " << &sd;
412  sensorDevices.add(sd->getDeviceName(), sd);
413  sd->owner = this;
414  rtThreadTimingsSensorDevice =
415  std::dynamic_pointer_cast<RTThreadTimingsSensorDevice>(sd);
416  }
417  else if (sd->getDeviceName() == GlobalRobotLocalizationSensorDevice::DeviceName())
418  {
419  ARMARX_DEBUG << "Device is the " << sd->getDeviceName();
420  if (!std::dynamic_pointer_cast<GlobalRobotLocalizationSensorDevice>(sd))
421  {
422  throw InvalidArgumentException{
423  "You tried to add a SensorDevice with the name " + sd->getDeviceName() +
424  " which does not derive from GlobalRobotLocalizationSensorDevice. (Don't "
425  "do this)"};
426  }
427  //this checks if we already added such a device (do this before setting timingSensorDevice)
428  ARMARX_DEBUG << "Adding the SensorDevice " << sd->getDeviceName() << " " << &sd;
429  sensorDevices.add(sd->getDeviceName(), sd);
430  sd->owner = this;
431  globalRobotLocalizationSensorDevice =
432  sd; //std::dynamic_pointer_cast<GlobalRobotLocalizationSensorDevice>(sd);
433  }
434  else
435  {
436  ARMARX_DEBUG << "Adding the SensorDevice " << sd->getDeviceName() << " " << &sd;
437  sensorDevices.add(sd->getDeviceName(), sd);
438  sd->owner = this;
439  }
440  }
441  ARMARX_INFO << "added SensorDevice " << sd->getDeviceName()
442  << " (valuetype = " << sd->getSensorValueType() << ")";
444  }
445 
446  RTThreadTimingsSensorDevicePtr
448  {
449  throwIfInControlThread(BOOST_CURRENT_FUNCTION);
450  return std::make_shared<RTThreadTimingsSensorDeviceImpl<>>(rtThreadTimingsSensorDeviceName);
451  }
452 
453  void
454  Devices::_postFinishRunning()
455  {
456  throwIfInControlThread(BOOST_CURRENT_FUNCTION);
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();
463  }
464 
465  std::vector<JointController*>
466  Devices::getStopMovementJointControllers() const
467  {
468  throwIfInControlThread(BOOST_CURRENT_FUNCTION);
469  throwIfDevicesNotReady(__FUNCTION__);
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())
474  {
476  controllers.emplace_back(dev->rtGetJointStopMovementController());
477  ARMARX_CHECK_NOT_NULL(controllers.back());
478  }
479  ARMARX_CHECK_EQUAL(controlDevices.size(), controllers.size());
480  throwIfDevicesNotReady(__FUNCTION__);
481  return controllers;
482  }
483 
484  std::vector<JointController*>
485  Devices::getEmergencyStopJointControllers() const
486  {
487  throwIfInControlThread(BOOST_CURRENT_FUNCTION);
488  throwIfDevicesNotReady(__FUNCTION__);
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())
493  {
495  controllers.emplace_back(dev->rtGetJointEmergencyStopController());
496  ARMARX_CHECK_NOT_NULL(controllers.back());
497  }
498  ARMARX_CHECK_EQUAL(controlDevices.size(), controllers.size());
499  throwIfDevicesNotReady(__FUNCTION__);
500  return controllers;
501  }
502 
503  void
504  Devices::_preFinishDeviceInitialization()
505  {
506  throwIfInControlThread(BOOST_CURRENT_FUNCTION);
507  std::lock_guard<MutexType> guardS{sensorDevicesMutex};
508  std::lock_guard<MutexType> guardC{controlDevicesMutex};
509  if (!sensorDevices.has(rtThreadTimingsSensorDeviceName))
510  {
512  }
513 
514  // this device will be used by the PlatformUnit to make the robot's global pose
515  // available to e.g. the NJointControllers.
516  addSensorDevice(std::make_shared<GlobalRobotPoseCorrectionSensorDevice>());
517  addSensorDevice(std::make_shared<GlobalRobotLocalizationSensorDevice>());
518  }
519 
520  void
521  Devices::_postFinishDeviceInitialization()
522  {
523  ARMARX_TRACE;
524  throwIfInControlThread(BOOST_CURRENT_FUNCTION);
525  std::lock_guard<MutexType> guardS{sensorDevicesMutex};
526  std::lock_guard<MutexType> guardC{controlDevicesMutex};
527  ARMARX_DEBUG << "checking " << controlDevices.size() << " ControlDevices:";
528  {
529  ARMARX_TRACE;
530  for (const ControlDevicePtr& controlDevice : controlDevices.values())
531  {
532  ARMARX_CHECK_EXPRESSION(controlDevice);
533  ARMARX_DEBUG << "----" << controlDevice->getDeviceName();
534  if (!controlDevice->hasJointController(ControlModes::EmergencyStop))
535  {
536  std::stringstream s;
537  s << "ControlDevice " << controlDevice->getDeviceName()
538  << " has no JointController with ControlMode " << ControlModes::EmergencyStop
539  << " (to fix this, add a JointController with this ControlMode to the "
540  "ControlDevice).\nAvailable controllers: "
541  << controlDevice->getControlModes();
542  ARMARX_ERROR << "--------" << s.str();
543  throw LogicError{s.str()};
544  }
545  if (!controlDevice->hasJointController(ControlModes::StopMovement))
546  {
547  std::stringstream s;
548  s << "ControlDevice " << controlDevice->getDeviceName()
549  << " has no JointController with ControlMode \"" << ControlModes::StopMovement
550  << "\" (to fix this, add a JointController with this ControlMode to the "
551  "ControlDevice) \nAvailable controllers: "
552  << controlDevice->getControlModes();
553  ARMARX_ERROR << "--------" << s.str();
554  throw LogicError{s.str()};
555  }
556  }
557  }
558  ARMARX_DEBUG << "checking " << controlDevices.size() << " SensorDevices:";
559  {
560  ARMARX_TRACE;
561  for (const SensorDevicePtr& sensorDevice : sensorDevices.values())
562  {
563  ARMARX_CHECK_EXPRESSION(sensorDevice);
564  ARMARX_DEBUG << "----" << sensorDevice->getDeviceName();
565  if (!sensorDevice->getSensorValue())
566  {
567  std::stringstream s;
568  s << "SensorDevice " << sensorDevice->getSensorValue()
569  << " has null SensorValue";
570  ARMARX_ERROR << "--------" << s.str();
571  throw LogicError{s.str()};
572  }
573  ARMARX_CHECK_EXPRESSION(sensorDevice);
574  }
575  }
576  ARMARX_DEBUG << "copying device ptrs to const ptr map";
577  {
578  ARMARX_TRACE;
579  for (const auto& dev : controlDevices.values())
580  {
581  controlDevicesConstPtr[dev->getDeviceName()] = dev;
582  }
583  for (const auto& dev : sensorDevices.values())
584  {
585  sensorDevicesConstPtr[dev->getDeviceName()] = dev;
586  }
587  }
588  ARMARX_DEBUG << "copy sensor values";
589  {
590  ARMARX_TRACE;
591  ARMARX_CHECK_EXPRESSION(sensorValues.empty());
592  sensorValues.reserve(sensorDevices.values().size());
593  for (const SensorDevicePtr& dev : sensorDevices.values())
594  {
596  sensorValues.emplace_back(dev->getSensorValue());
597  ARMARX_CHECK_NOT_NULL(sensorValues.back());
598  }
599  }
600  ARMARX_DEBUG << "copy control targets";
601  {
602  ARMARX_TRACE;
603  ARMARX_CHECK_EXPRESSION(controlTargets.empty());
604  controlTargets.reserve(controlDevices.values().size());
605  for (const ControlDevicePtr& dev : controlDevices.values())
606  {
608  controlTargets.emplace_back();
609  controlTargets.back().reserve(dev->rtGetJointControllers().size());
610  for (JointController* ctrl : dev->rtGetJointControllers())
611  {
612  ARMARX_CHECK_NOT_NULL(ctrl);
613  controlTargets.back().emplace_back(ctrl->getControlTarget());
614  ARMARX_CHECK_NOT_NULL(controlTargets.back().back().get());
615  }
616  }
617  }
618  ARMARX_DEBUG << "setup ControlDeviceHardwareControlModeGroups";
619  {
620  ARMARX_TRACE;
621  ctrlModeGroups.groupIndices.assign(getNumberOfControlDevices(), IndexSentinel());
622 
623  if (!ctrlModeGroups.groupsMerged.empty())
624  {
625  ARMARX_DEBUG << "Remove control devs from ControlDeviceHardwareControlModeGroups ("
626  << ctrlModeGroups.groups.size() << ")";
627  const auto groupsMerged = ctrlModeGroups.groupsMerged;
628  for (const auto& dev : groupsMerged)
629  {
630  if (controlDevices.has(dev))
631  {
632  continue;
633  }
634  ctrlModeGroups.groupsMerged.erase(dev);
635  for (auto& group : ctrlModeGroups.groups)
636  {
637  group.erase(dev);
638  }
639  ARMARX_DEBUG << "----removing nonexistent device: " << dev;
640  }
641  //remove empty groups
642  std::vector<std::set<std::string>> cleanedGroups;
643  cleanedGroups.reserve(ctrlModeGroups.groups.size());
644  for (auto& group : ctrlModeGroups.groups)
645  {
646  const auto sz = group.size();
647  if (sz == 1)
648  {
649  ARMARX_DEBUG << "----removing group with one dev: " << *group.begin();
650  }
651  else if (sz > 1)
652  {
653  cleanedGroups.emplace_back(std::move(group));
654  }
655  }
656  ctrlModeGroups.groups = cleanedGroups;
657  ARMARX_DEBUG << "----number of groups left: " << ctrlModeGroups.groups.size();
658  }
659  if (!ctrlModeGroups.groupsMerged.empty())
660  {
662  << "Checking control modes for ControlDeviceHardwareControlModeGroups ("
663  << ctrlModeGroups.groups.size() << ")";
664  ctrlModeGroups.deviceIndices.resize(ctrlModeGroups.groups.size());
665  //iterate over groups
666  for (std::size_t groupIdx = 0; groupIdx < ctrlModeGroups.groups.size(); ++groupIdx)
667  {
668  const std::set<std::string>& group = ctrlModeGroups.groups.at(groupIdx);
669  ctrlModeGroups.deviceIndices.at(groupIdx).reserve(group.size());
670  ARMARX_CHECK_EXPRESSION(!group.empty());
671  ARMARX_DEBUG << "----Group " << groupIdx << " size: " << group.size();
672  //gets a map of ControlMode->HardwareControlMode for the given device
673  const auto getControlModeToHWControlMode = [&](const std::string& devname)
674  {
675  std::map<std::string, std::string> controlModeToHWControlMode;
676  const ControlDevicePtr& cd = controlDevices.at(devname);
677  for (const auto& jointCtrl : cd->getJointControllers())
678  {
679  controlModeToHWControlMode[jointCtrl->getControlMode()] =
680  jointCtrl->getHardwareControlMode();
681  }
682  return controlModeToHWControlMode;
683  };
684  //get modes of first dev
685  const auto controlModeToHWControlMode =
686  getControlModeToHWControlMode(*group.begin());
687  //check other devs
688  for (const auto& devname : group)
689  {
690  ARMARX_CHECK_EXPRESSION(controlDevices.has(devname))
691  << "The ControlDeviceHardwareControlModeGroups property contains "
692  "device names not existent in the robot: "
693  << devname << "\navailable:\n"
694  << controlDevices.keys();
695  //Assert all devices in a group have the same control modes with the same hw controle modes
696  const auto controlModeToHWControlModeForDevice =
697  getControlModeToHWControlMode(devname);
698  ARMARX_CHECK_EXPRESSION(controlModeToHWControlModeForDevice ==
699  controlModeToHWControlMode)
700  << "Error for control modes of device '" << devname << "'\n"
701  << "it has the modes: " << controlModeToHWControlModeForDevice
702  << "\n but should have the modes: " << controlModeToHWControlMode;
703  //insert the device index into the device indices
704  const auto devIdx = controlDevices.index(devname);
705  ctrlModeGroups.deviceIndices.at(groupIdx).emplace_back(devIdx);
706  //insert the group index into the group indices (+ check the current group index is the sentinel
707  ARMARX_CHECK_EXPRESSION(ctrlModeGroups.groupIndices.size() > devIdx);
708  ARMARX_CHECK_EXPRESSION(ctrlModeGroups.groupIndices.at(devIdx) ==
709  IndexSentinel());
710  ctrlModeGroups.groupIndices.at(devIdx) = groupIdx;
711  ARMARX_DEBUG << "------- " << devname;
712  }
713  }
714  }
715  }
716  ARMARX_DEBUG << "create mapping from sensor values to robot nodes";
717  {
718  ARMARX_TRACE;
719  ARMARX_CHECK_EXPRESSION(simoxRobotSensorValueMapping.empty());
720  VirtualRobot::RobotPtr r = _module<RobotData>().cloneRobot();
721  const auto nodes = r->getRobotNodes();
722  for (std::size_t idxRobot = 0; idxRobot < nodes.size(); ++idxRobot)
723  {
724  const VirtualRobot::RobotNodePtr& node = nodes.at(idxRobot);
725  if (node->isJoint())
726  {
727  const auto& name = node->getName();
728  if (sensorDevices.has(name))
729  {
730  const auto& dev = sensorDevices.at(name);
731  if (dev->getSensorValue()->isA<SensorValue1DoFActuatorPosition>())
732  {
733  SimoxRobotSensorValueMapping m;
734  m.idxRobot = idxRobot;
735  m.idxSens = sensorDevices.index(name);
736  simoxRobotSensorValueMapping.emplace_back(m);
737  }
738  else
739  {
741  << "SensorValue for SensorDevice " << name << " is of type "
742  << dev->getSensorValueType()
743  << " which does not derive SensorValue1DoFActuatorPosition";
744  }
745  }
746  else
747  {
748  ARMARX_INFO << "No SensorDevice for RobotNode: " << name;
749  }
750  }
751  }
752  }
753 
754  ARMARX_VERBOSE << "ControlDevices:\n" << controlDevices.keys();
755  ARMARX_VERBOSE << "SensorDevices:\n" << sensorDevices.keys();
756  }
757 
758  void
759  Devices::_preOnInitRobotUnit()
760  {
761  throwIfInControlThread(BOOST_CURRENT_FUNCTION);
762  //ControlDeviceHardwareControlModeGroups
763  const std::string controlDeviceHardwareControlModeGroupsStr =
764  getProperty<std::string>("ControlDevices_HardwareControlModeGroups").getValue();
765  if (!controlDeviceHardwareControlModeGroupsStr.empty())
766  {
767  const auto numGroups = std::count(controlDeviceHardwareControlModeGroupsStr.begin(),
768  controlDeviceHardwareControlModeGroupsStr.end(),
769  ';') +
770  1;
771  ctrlModeGroups.groups.reserve(numGroups);
772  std::vector<std::string> strGroups =
773  Split(controlDeviceHardwareControlModeGroupsStr, ";");
774  for (const auto& gstr : strGroups)
775  {
776  bool trimDeviceNames = true;
777  std::vector<std::string> strElems = Split(gstr, ",", trimDeviceNames);
778  std::set<std::string> group;
779  for (auto& device : strElems)
780  {
781  ARMARX_CHECK_EXPRESSION(!device.empty())
782  << "The ControlDeviceHardwareControlModeGroups property contains empty "
783  "device names";
784  ARMARX_CHECK_EXPRESSION(!ctrlModeGroups.groupsMerged.count(device))
785  << "The ControlDeviceHardwareControlModeGroups property contains duplicate "
786  "device names: "
787  << device;
788  ctrlModeGroups.groupsMerged.emplace(device);
789  group.emplace(std::move(device));
790  }
791  if (!group.empty())
792  {
793  ARMARX_DEBUG << "adding device group:\n" << ARMARX_STREAM_PRINTER
794  {
795  for (const auto& elem : group)
796  {
797  out << " " << elem << "\n";
798  }
799  };
800  ctrlModeGroups.groups.emplace_back(std::move(group));
801  }
802  }
803  }
804  }
805 } // namespace armarx::RobotUnitModule
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:180
armarx::ControlDevice::NullPtr
static const ControlDevicePtr NullPtr
A static const nullptr in case a const ref to a nullptr needs to be returned.
Definition: ControlDevice.h:67
armarx::KeyValueVector::keys
KeyContT const & keys() const
Definition: KeyValueVector.h:164
armarx::SensorDevice::NullPtr
static const SensorDevicePtr NullPtr
A static const nullptr in case a const ref to a nullptr needs to be returned.
Definition: SensorDevice.h:63
algorithm.h
armarx::RobotUnitModule::Devices::getControlDevice
ConstControlDevicePtr getControlDevice(const std::string &deviceName) const
Returns the ControlDevice.
Definition: RobotUnitModuleDevices.cpp:118
armarx::KeyValueVector::at
ValT & at(IdxT i)
Definition: KeyValueVector.h:110
armarx::GlobalRobotLocalizationSensorDevice::DeviceName
static std::string DeviceName()
Definition: GlobalRobotPoseSensorDevice.cpp:109
ARMARX_CHECK_NOT_NULL
#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...
Definition: ExpressionException.h:206
armarx::getIndices
std::vector< KeyT > getIndices(const std::map< KeyT, ValT > &c)
Definition: algorithm.h:275
armarx::KeyValueVector::values
ValContT const & values() const
Definition: KeyValueVector.h:152
armarx::KeyValueVector::size
IdxT size() const
Definition: KeyValueVector.h:146
armarx::KeyValueVector::has
bool has(const KeyT &k) const
Definition: KeyValueVector.h:176
armarx::Split
std::vector< std::string > Split(const std::string &source, const std::string &splitBy, bool trimElements=false, bool removeEmptyElements=false)
Definition: StringHelperTemplates.h:35
armarx::KeyValueVector::index
IdxT index(const KeyT &k) const
Definition: KeyValueVector.h:104
armarx::RobotUnitModule::Devices::getControlDeviceStatuses
ControlDeviceStatusSeq getControlDeviceStatuses(const Ice::Current &=Ice::emptyCurrent) const override
Return the ControlDeviceStatuses for all ControlDevices.
Definition: RobotUnitModuleDevices.cpp:203
armarx::RobotUnitModule::Devices::ControlDeviceHardwareControlModeGroups::groupsMerged
std::set< std::string > groupsMerged
contains the names of all devices in any group
Definition: RobotUnitModuleDevices.h:453
StringHelpers.h
armarx::RobotUnitModule::Devices::getSensorDeviceStatus
SensorDeviceStatus getSensorDeviceStatus(const std::string &name, const Ice::Current &=Ice::emptyCurrent) const override
Return the SensorDeviceStatus for the given SensorDevice.
Definition: RobotUnitModuleDevices.cpp:300
RobotUnitModuleRobotData.h
ARMARX_TRACE
#define ARMARX_TRACE
Definition: trace.h:69
armarx::status
status
Definition: FiniteStateMachine.h:259
armarx::RobotUnitModule::Devices::getSensorDeviceNames
Ice::StringSeq getSensorDeviceNames(const Ice::Current &=Ice::emptyCurrent) const override
Returns the names of all SensorDevices for the robot.
Definition: RobotUnitModuleDevices.cpp:222
armarx::RobotUnitModule::Devices::getSensorDevice
ConstSensorDevicePtr getSensorDevice(const std::string &deviceName) const
TODO move to attorney for NJointControllerBase.
Definition: RobotUnitModuleDevices.cpp:109
armarx::KeyValueVector::add
void add(KeyT key, ValT value)
Definition: KeyValueVector.h:92
RobotUnitModuleDevices.h
armarx::RobotUnitModule::Devices::ControlDeviceHardwareControlModeGroups::deviceIndices
std::vector< std::vector< std::size_t > > deviceIndices
contains a vector per group.
Definition: RobotUnitModuleDevices.h:451
armarx::RobotUnitModule::Devices::getControlDeviceDescriptions
ControlDeviceDescriptionSeq getControlDeviceDescriptions(const Ice::Current &=Ice::emptyCurrent) const override
Return the ControlDeviceDescriptions for all ControlDevices.
Definition: RobotUnitModuleDevices.cpp:54
armarx::RobotUnitModule::ModuleBase::IndexSentinel
static constexpr std::size_t IndexSentinel()
Returns a sentinel value for an index (std::numeric_limits<std::size_t>::max())
Definition: RobotUnitModuleBase.h:720
data
uint8_t data[1]
Definition: EtherCATFrame.h:68
ARMARX_DEBUG
#define ARMARX_DEBUG
Definition: Logging.h:177
armarx::RobotUnitModule::Devices::ControlDeviceHardwareControlModeGroups::groupIndices
std::vector< std::size_t > groupIndices
contains the group index for each device (or the sentinel)
Definition: RobotUnitModuleDevices.h:455
armarx::RobotUnitModule::Devices::getSensorDeviceDescription
SensorDeviceDescription getSensorDeviceDescription(const std::string &name, const Ice::Current &=Ice::emptyCurrent) const override
Return the SensorDeviceDescription for the given SensorDevice.
Definition: RobotUnitModuleDevices.cpp:266
armarx::RobotUnitModule::Devices::getControlDeviceDescription
ControlDeviceDescription getControlDeviceDescription(const std::string &name, const Ice::Current &=Ice::emptyCurrent) const override
Return the ControlDeviceDescription for the given ControlDevice.
Definition: RobotUnitModuleDevices.cpp:38
armarx::RobotUnitModule::Devices::getSensorDeviceStatuses
SensorDeviceStatusSeq getSensorDeviceStatuses(const Ice::Current &=Ice::emptyCurrent) const override
Return the SensorDeviceStatuses for all SensorDevices.
Definition: RobotUnitModuleDevices.cpp:316
RobotUnitModuleControlThreadDataBuffer.h
armarx::RobotUnitModule::Devices::ControlDeviceHardwareControlModeGroups::groups
std::vector< std::set< std::string > > groups
contains a vector per group.
Definition: RobotUnitModuleDevices.h:448
armarx::RobotUnitModule::Devices::addSensorDevice
void addSensorDevice(const SensorDevicePtr &sd)
Adds a SensorDevice to the robot.
Definition: RobotUnitModuleDevices.cpp:377
ARMARX_ERROR
#define ARMARX_ERROR
Definition: Logging.h:189
armarx::RobotUnitModule::Devices::getSensorDeviceDescriptions
SensorDeviceDescriptionSeq getSensorDeviceDescriptions(const Ice::Current &=Ice::emptyCurrent) const override
Return the SensorDeviceDescriptions for all SensorDevices.
Definition: RobotUnitModuleDevices.cpp:282
armarx::KeyValueVector::clear
void clear()
Definition: KeyValueVector.h:182
armarx::TimeUtil::GetTime
static IceUtil::Time GetTime(TimeMode timeMode=TimeMode::VirtualTime)
Get the current time.
Definition: TimeUtil.cpp:42
armarx::RobotUnitModule::Devices::getControlDeviceIndex
std::size_t getControlDeviceIndex(const std::string &deviceName) const
Returns the ControlDevice's index.
Definition: RobotUnitModuleDevices.cpp:99
armarx::RobotUnitModule::Devices::getNumberOfSensorDevices
std::size_t getNumberOfSensorDevices() const
Returns the number of SensorDevices.
Definition: RobotUnitModuleDevices.cpp:81
armarx::RobotUnitModule::Devices::addControlDevice
void addControlDevice(const ControlDevicePtr &cd)
Adds a ControlDevice to the robot.
Definition: RobotUnitModuleDevices.cpp:335
ARMARX_CHECK_EXPRESSION
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
Definition: ExpressionException.h:73
armarx::RobotUnitModule::Devices::getControlDeviceStatus
ControlDeviceStatus getControlDeviceStatus(const std::string &name, const Ice::Current &=Ice::emptyCurrent) const override
Return the ControlDeviceStatus for the given ControlDevice.
Definition: RobotUnitModuleDevices.cpp:187
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
armarx::RobotUnitModule::ModuleBase::areDevicesReady
bool areDevicesReady() const
Returns whether Devices are ready.
Definition: RobotUnitModuleBase.cpp:403
armarx::RobotUnitState::InitializingDevices
@ InitializingDevices
armarx::RobotUnitModule::Devices::getSensorDeviceIndex
std::size_t getSensorDeviceIndex(const std::string &deviceName) const
Returns the SensorDevice's index.
Definition: RobotUnitModuleDevices.cpp:89
armarx::RobotUnitModule::ModuleBase::throwIfInControlThread
void throwIfInControlThread(const std::string &fnc) const
Throws if the current thread is the ControlThread.
Definition: RobotUnitModuleBase.cpp:416
armarx::RobotUnitModule::ModuleBase::throwIfDevicesNotReady
void throwIfDevicesNotReady(const std::string &fnc) const
Throws if the Devices are not ready.
Definition: RobotUnitModuleBase.cpp:530
GlobalRobotPoseSensorDevice.h
armarx::ConstSensorDevicePtr
std::shared_ptr< const class SensorDevice > ConstSensorDevicePtr
Definition: NJointControllerBase.h:77
armarx::RobotUnitModule::ModuleBase::throwIfStateIsNot
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.
Definition: RobotUnitModuleBase.cpp:456
armarx::RobotUnitModule
Definition: ControlDevice.h:34
armarx::RobotUnitModule::Devices::getControlDeviceNames
Ice::StringSeq getControlDeviceNames(const Ice::Current &=Ice::emptyCurrent) const override
Returns the names of all ControlDevices for the robot.
Definition: RobotUnitModuleDevices.cpp:127
ARMARX_CHECK_EQUAL
#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...
Definition: ExpressionException.h:130
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:186
control
This file is part of ArmarX.
armarx::ctrlutil::s
double s(double t, double s0, double v0, double a0, double j)
Definition: CtrlUtil.h:33
armarx::ConstControlDevicePtr
std::shared_ptr< const class ControlDevice > ConstControlDevicePtr
Definition: NJointControllerBase.h:76
armarx::RobotUnitModule::Devices::getNumberOfControlDevices
std::size_t getNumberOfControlDevices() const
Returns the number of ControlDevices.
Definition: RobotUnitModuleDevices.cpp:73
VirtualRobot::RobotPtr
std::shared_ptr< class Robot > RobotPtr
Definition: Bus.h:18
armarx::RobotUnitModule::Devices::createRTThreadTimingSensorDevice
virtual RTThreadTimingsSensorDevicePtr createRTThreadTimingSensorDevice() const
Creates the SensorDevice used to log timings in the ControlThread (This function is supposed to be us...
Definition: RobotUnitModuleDevices.cpp:447
ARMARX_STREAM_PRINTER
#define ARMARX_STREAM_PRINTER
use this macro to write output code that is executed when printed and thus not executed if the debug ...
Definition: Logging.h:304