KinematicUnitDynamicSimulation.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * Copyright (C) 2013-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5  *
6  * ArmarX is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * ArmarX is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * @package ArmarXSimulation::ArmarXObjects::KinematicUnitDynamicSimulation
19  * @author Nikolaus ( vahrenkamp at kit dot edu )
20  * @date 2013
21  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22  * GNU General Public License
23  */
24 
26 
27 #include <algorithm>
28 
29 #include <VirtualRobot/Nodes/RobotNode.h>
30 #include <VirtualRobot/RobotNodeSet.h>
31 #include <VirtualRobot/VirtualRobot.h>
32 #include <VirtualRobot/VirtualRobotException.h>
33 #include <VirtualRobot/XML/RobotIO.h>
34 
36 
37 using namespace armarx;
38 
39 void
41 {
42  ARMARX_VERBOSE << "Init with RNS " << robotNodeSetName << std::endl;
43 
44  for (auto& robotNode : robotNodes)
45  {
46  std::string jointName = robotNode->getName();
47  ARMARX_VERBOSE << "* " << jointName << flush;
48  nodeNames.insert(jointName);
49  }
50 
51  if (robot)
52  {
53  robotTopicName = "Simulator_Robot_";
54  robotName =
55  hasProperty("RobotName") ? getProperty<std::string>("RobotName") : robot->getName();
57  ARMARX_INFO << "Simulator Robot topic: " << robotTopicName << std::endl;
59  }
60  else
61  {
62  ARMARX_WARNING << "No robot loaded..." << std::endl;
63  }
64 
65  mapVelToPosVel = getProperty<bool>("MapVelocityToPositionVelocity").getValue();
66 
67  simulatorPrxName = getProperty<std::string>("SimulatorName").getValue();
69 }
70 
71 void
73 {
74  // subscribe topic in order to receive the simulator reports
75  ARMARX_INFO << "Using simulator proxy: " << simulatorPrxName << flush;
76  simulatorPrx = getProxy<SimulatorInterfacePrx>(simulatorPrxName);
77 
78  // periodic task setup
79  cycleTime = 1000.f / getProperty<float>("ControlFrequency").getValue();
80 
81  if (execTask)
82  {
83  execTask->stop();
84  }
85 
87  this,
89  cycleTime,
90  false,
91  "KinematicUnitDynamicSimulation");
92  execTask->start();
93  execTask->setDelayWarningTolerance(100);
94 }
95 
96 void
98 {
99  if (execTask)
100  {
101  execTask->stop();
102  }
103 }
104 
105 void
106 KinematicUnitDynamicSimulation::reportState(SimulatedRobotState const& state, const Ice::Current&)
107 {
108  NameValueMap angleValues;
109  NameValueMap velocitiyValues;
110  NameValueMap torqueValues;
111 
112  {
113  // Calculate results with lock, publish later without lock
114  std::scoped_lock scoped_lock(accessMutex);
115 
116  // Joint angles
117  if (state.jointAngles.size() > 0)
118  {
119  // check which joints are covered
120  for (const auto& actualJointAngle : state.jointAngles)
121  {
122  if (nodeNames.find(actualJointAngle.first) != nodeNames.end())
123  {
124  angleValues[actualJointAngle.first] = actualJointAngle.second;
125  }
126 
127  currentJointValues[actualJointAngle.first] = actualJointAngle.second;
128  }
129  }
130 
131  // Joint velocities
132  // check which jonts are covered
133  for (const auto& actualVelocity : state.jointVelocities)
134  {
135  if (nodeNames.find(actualVelocity.first) != nodeNames.end())
136  {
137  velocitiyValues[actualVelocity.first] = actualVelocity.second;
138  }
139  }
140 
141  // Joint torques
142  // check which jonts are covered
143  for (const auto& actualJointTorque : state.jointTorques)
144  {
145  if (nodeNames.find(actualJointTorque.first) != nodeNames.end())
146  {
147  torqueValues[actualJointTorque.first] = actualJointTorque.second;
148  }
149  }
150  }
151 
152  // FIXME: Use Ice batching to optimize
153  if (angleValues.size() > 0)
154  {
155  listenerPrx->reportJointAngles(angleValues, state.timestampInMicroSeconds, true);
156  }
157  if (velocitiyValues.size() > 0)
158  {
159  listenerPrx->reportJointVelocities(velocitiyValues, state.timestampInMicroSeconds, true);
160  }
161  if (torqueValues.size() > 0)
162  {
163  listenerPrx->reportJointTorques(torqueValues, state.timestampInMicroSeconds, true);
164  }
165 }
166 
167 NameControlModeMap
169 {
170  NameControlModeMap result;
171 
172  for (const auto& nodeName : nodeNames)
173  {
174  auto c = currentControlModes.find(nodeName);
175 
176  // if not specified, we assume position control
177  if (c == currentControlModes.end())
178  {
179  result[nodeName] = ePositionControl;
180  }
181  else
182  {
183  result[nodeName] = c->second;
184  }
185  }
186 
187  return result;
188 }
189 
190 void
191 KinematicUnitDynamicSimulation::switchControlMode(const NameControlModeMap& targetJointModes,
192  const Ice::Current& c)
193 {
194  std::scoped_lock scoped_lock(accessMutex);
195 
196  //currentControlModes = targetJointModes;
197  NameControlModeMap::const_iterator itAng = targetJointModes.begin();
198 
199  while (itAng != targetJointModes.end())
200  {
201  currentControlModes[itAng->first] = itAng->second;
202  itAng++;
203  }
204 
205  listenerPrx->reportControlModeChanged(
206  targetJointModes, IceUtil::Time::now().toMicroSeconds(), true);
207 }
208 
209 void
211  const Ice::Current& c)
212 {
213  std::scoped_lock scoped_lock(accessMutex);
214 
215 
216  // store current joint angles
217  NameValueMap::const_iterator itAng = targetJointAngles.begin();
218 
219  while (itAng != targetJointAngles.end())
220  {
221  currentJointTargets[itAng->first] = itAng->second;
222  itAng++;
223  }
224 }
225 
226 void
228  const Ice::Current& c)
229 {
230  std::scoped_lock scoped_lock(accessMutex);
231  NameValueMap::const_iterator itVel = targetJointVelocities.begin();
232 
233  while (itVel != targetJointVelocities.end())
234  {
235  currentJointVelTargets[itVel->first] = itVel->second;
236  itVel++;
237  }
238 }
239 
240 void
242  const Ice::Current& c)
243 {
244  std::scoped_lock scoped_lock(accessMutex);
245 
246  // store current joint torques
247  NameValueMap::const_iterator itAng = targetJointTorques.begin();
248 
249  while (itAng != targetJointTorques.end())
250  {
251  currentJointTorqueTargets[itAng->first] = itAng->second;
252  itAng++;
253  }
254 }
255 
256 void
258  const Ice::Current& c)
259 {
260 }
261 
262 void
264  const Ice::Current& c)
265 {
266 }
267 
268 void
269 KinematicUnitDynamicSimulation::requestJoints(const Ice::StringSeq& joints, const Ice::Current& c)
270 {
271  std::scoped_lock scoped_lock(accessMutex);
272 
273  // if one of the joints belongs to this unit, lock access to this unit for other components except for the requesting one
274  for (const auto& joint : joints)
275  {
276  if (nodeNames.find(joint) != nodeNames.end())
277  {
279  return;
280  }
281  }
282 }
283 
284 void
285 KinematicUnitDynamicSimulation::releaseJoints(const Ice::StringSeq& joints, const Ice::Current& c)
286 {
287  std::scoped_lock scoped_lock(accessMutex);
288 
289  // if one of the joints belongs to this unit, unlock access
290  for (const auto& joint : joints)
291  {
292  if (nodeNames.find(joint) != nodeNames.end())
293  {
295  return;
296  }
297  }
298 }
299 
300 void
302 {
303  if (!simulatorPrx)
304  {
305  return;
306  }
307 
308  float loopTime = (float)execTask->getInterval() / 1000.0f; // in s
309  float factorLoopTime = 1.1f;
310 
311  {
312  std::scoped_lock lock(accessMutex);
313 
314  NameValueMap applyPosMap;
315  NameValueMap applyVelMap;
316  NameValueMap applyPosVelMap_pos;
317  NameValueMap applyPosVelMap_vel;
318  NameValueMap applyTorMap;
319  NameControlModeMap::const_iterator itMode = currentControlModes.begin();
320 
321  while (itMode != currentControlModes.end())
322  {
323  switch (itMode->second)
324  {
325  case ePositionControl:
326  if (currentJointTargets.find(itMode->first) != currentJointTargets.end())
327  {
328  applyPosMap[itMode->first] =
329  currentJointTargets.find(itMode->first)->second;
330  }
331 
332  break;
333 
334  case eVelocityControl:
335  {
336  auto it = currentJointVelTargets.find(itMode->first);
337  if (it != currentJointVelTargets.end())
338  {
339  if (mapVelToPosVel)
340  {
341  // compute pos
342  if (currentJointValues.find(itMode->first) != currentJointValues.end())
343  {
344  float posTarget = currentJointValues[itMode->first] +
345  it->second * loopTime * factorLoopTime;
346  applyPosVelMap_pos[itMode->first] = posTarget;
347  applyPosVelMap_vel[itMode->first] = it->second;
348  }
349  }
350  else
351  {
352  // just use velocity
353  applyVelMap[itMode->first] =
354  currentJointVelTargets.find(itMode->first)->second;
355  }
356  }
357  }
358 
359  break;
360 
361  case eTorqueControl:
362  if (currentJointTorqueTargets.find(itMode->first) !=
364  {
365  applyTorMap[itMode->first] =
366  currentJointTorqueTargets.find(itMode->first)->second;
367  }
368 
369  break;
370 
371  case ePositionVelocityControl:
372  if (currentJointVelTargets.find(itMode->first) !=
373  currentJointVelTargets.end() &&
374  currentJointTargets.find(itMode->first) != currentJointTargets.end())
375  {
376  applyPosVelMap_pos[itMode->first] =
377  currentJointTargets.find(itMode->first)->second;
378  applyPosVelMap_vel[itMode->first] =
379  currentJointVelTargets.find(itMode->first)->second;
380  }
381 
382  break;
383 
384  case eUnknown:
385  case eDisabled:
386  default:
387  // do nothing
388  ;
389  }
390 
391  itMode++;
392  }
393  auto batchPrx = simulatorPrx->ice_batchOneway();
394  if (applyPosMap.size() > 0)
395  {
396  batchPrx->actuateRobotJointsPos(robotName, applyPosMap);
397  }
398 
399  if (applyVelMap.size() > 0)
400  {
401  batchPrx->actuateRobotJointsVel(robotName, applyVelMap);
402  }
403 
404  if (applyTorMap.size() > 0)
405  {
406  batchPrx->actuateRobotJointsTorque(robotName, applyTorMap);
407  }
408 
409  if (applyPosVelMap_pos.size() > 0)
410  {
411  batchPrx->actuateRobotJoints(robotName, applyPosVelMap_pos, applyPosVelMap_vel);
412  }
413  batchPrx->ice_flushBatchRequests();
414 
415  // command only once
416  if (!mapVelToPosVel) // dont clear this in pos-velo mode because it is needed to calculate next position target
417  {
418  currentJointVelTargets.clear();
419  }
420  currentJointTargets.clear();
422  }
423 }
424 
425 armarx::DebugInfo
427 {
428  const ::armarx::SimulatedRobotState robotState = simulatorPrx->getRobotState(robotName);
429 
430  ::armarx::NameStatusMap jointStatus;
431  for (const auto& [jointName, _] : currentControlModes)
432  {
433  jointStatus[jointName] = {
434  .operation = eOnline,
435  .error = eOk,
436  .enabled = true,
437  .emergencyStop = false // TODO: implement
438  };
439  }
440 
441  return {.jointModes = currentControlModes,
442  .jointAngles = robotState.jointAngles,
443  .jointVelocities = robotState.jointVelocities,
444  .jointAccelerations = {}, // not available
445  .jointTorques = robotState.jointTorques,
446  .jointCurrents = {}, // not available
447  .jointMotorTemperatures = {}, // not available
448  .jointStatus = jointStatus};
449 }
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:187
armarx::KinematicUnitDynamicSimulation::execTask
PeriodicTask< KinematicUnitDynamicSimulation >::pointer_type execTask
Definition: KinematicUnitDynamicSimulation.h:135
armarx::KinematicUnitDynamicSimulation::currentControlModes
NameControlModeMap currentControlModes
Definition: KinematicUnitDynamicSimulation.h:157
armarx::KinematicUnitDynamicSimulation::periodicExec
void periodicExec()
Definition: KinematicUnitDynamicSimulation.cpp:301
armarx::KinematicUnitDynamicSimulation::currentJointTargets
NameValueMap currentJointTargets
Definition: KinematicUnitDynamicSimulation.h:154
armarx::SensorActorUnit::release
void release(const Ice::Current &c=Ice::emptyCurrent) override
Release exclusive access to current unit.
Definition: SensorActorUnit.cpp:149
armarx::KinematicUnitDynamicSimulation::mapVelToPosVel
bool mapVelToPosVel
Definition: KinematicUnitDynamicSimulation.h:163
armarx::KinematicUnit::robotNodeSetName
std::string robotNodeSetName
Definition: KinematicUnit.h:156
armarx::KinematicUnitDynamicSimulation::robotTopicName
std::string robotTopicName
Definition: KinematicUnitDynamicSimulation.h:151
armarx::KinematicUnitDynamicSimulation::onExitKinematicUnit
void onExitKinematicUnit() override
Definition: KinematicUnitDynamicSimulation.cpp:97
armarx::SensorActorUnit::request
void request(const Ice::Current &c=Ice::emptyCurrent) override
Request exclusive access to current unit.
Definition: SensorActorUnit.cpp:130
armarx::KinematicUnitDynamicSimulation::onStartKinematicUnit
void onStartKinematicUnit() override
Definition: KinematicUnitDynamicSimulation.cpp:72
c
constexpr T c
Definition: UnscentedKalmanFilterTest.cpp:46
armarx::KinematicUnitDynamicSimulation::currentJointValues
NameValueMap currentJointValues
Definition: KinematicUnitDynamicSimulation.h:161
armarx::KinematicUnitDynamicSimulation::accessMutex
std::recursive_mutex accessMutex
Definition: KinematicUnitDynamicSimulation.h:165
armarx::PropertyUser::hasProperty
bool hasProperty(const std::string &name)
Definition: PropertyUser.cpp:234
armarx::KinematicUnitDynamicSimulation::simulatorPrx
SimulatorInterfacePrx simulatorPrx
Definition: KinematicUnitDynamicSimulation.h:167
KinematicUnitDynamicSimulation.h
armarx::KinematicUnitDynamicSimulation::requestJoints
void requestJoints(const Ice::StringSeq &joints, const Ice::Current &c=Ice::emptyCurrent) override
Definition: KinematicUnitDynamicSimulation.cpp:269
armarx::KinematicUnitDynamicSimulation::setJointAngles
void setJointAngles(const NameValueMap &targetJointAngles, const Ice::Current &c=Ice::emptyCurrent) override
Definition: KinematicUnitDynamicSimulation.cpp:210
armarx::KinematicUnitDynamicSimulation::getDebugInfo
DebugInfo getDebugInfo(const Ice::Current &c=Ice::emptyCurrent) const override
Definition: KinematicUnitDynamicSimulation.cpp:426
armarx::KinematicUnitDynamicSimulation::currentJointTorqueTargets
NameValueMap currentJointTorqueTargets
Definition: KinematicUnitDynamicSimulation.h:156
armarx::KinematicUnitDynamicSimulation::setJointAccelerations
void setJointAccelerations(const NameValueMap &targetJointAccelerations, const Ice::Current &c=Ice::emptyCurrent) override
Definition: KinematicUnitDynamicSimulation.cpp:257
armarx::KinematicUnitDynamicSimulation::switchControlMode
void switchControlMode(const NameControlModeMap &targetJointModes, const Ice::Current &c=Ice::emptyCurrent) override
Definition: KinematicUnitDynamicSimulation.cpp:191
armarx::KinematicUnitDynamicSimulation::currentJointVelTargets
NameValueMap currentJointVelTargets
Definition: KinematicUnitDynamicSimulation.h:155
armarx::flush
const LogSender::manipulator flush
Definition: LogSender.h:251
armarx::KinematicUnitDynamicSimulation::releaseJoints
void releaseJoints(const Ice::StringSeq &joints, const Ice::Current &c=Ice::emptyCurrent) override
Definition: KinematicUnitDynamicSimulation.cpp:285
armarx::KinematicUnitDynamicSimulation::setJointDecelerations
void setJointDecelerations(const NameValueMap &targetJointDecelerations, const Ice::Current &c=Ice::emptyCurrent) override
Definition: KinematicUnitDynamicSimulation.cpp:263
armarx::KinematicUnitDynamicSimulation::simulatorPrxName
std::string simulatorPrxName
Definition: KinematicUnitDynamicSimulation.h:152
armarx::KinematicUnitDynamicSimulation::robotName
std::string robotName
Definition: KinematicUnitDynamicSimulation.h:150
armarx::KinematicUnitDynamicSimulation::cycleTime
int cycleTime
Definition: KinematicUnitDynamicSimulation.h:159
armarx::control::njoint_controller::platform::platform_follower_controller::NameValueMap
std::map< std::string, float > NameValueMap
Definition: PlatformFollowerController.h:88
armarx::ManagedIceObject::usingTopic
void usingTopic(const std::string &name, bool orderedPublishing=false)
Registers a proxy for subscription after initialization.
Definition: ManagedIceObject.cpp:254
armarx::KinematicUnitDynamicSimulation::setJointVelocities
void setJointVelocities(const NameValueMap &targetJointVelocities, const Ice::Current &c=Ice::emptyCurrent) override
Definition: KinematicUnitDynamicSimulation.cpp:227
armarx::KinematicUnit::listenerPrx
KinematicUnitListenerPrx listenerPrx
Definition: KinematicUnit.h:152
float
#define float
Definition: 16_Level.h:22
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
armarx::KinematicUnitDynamicSimulation::getControlModes
NameControlModeMap getControlModes(const Ice::Current &c=Ice::emptyCurrent) override
Definition: KinematicUnitDynamicSimulation.cpp:168
armarx::KinematicUnitDynamicSimulation::onInitKinematicUnit
void onInitKinematicUnit() override
Definition: KinematicUnitDynamicSimulation.cpp:40
armarx::PeriodicTask
Definition: ArmarXManager.h:70
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:193
ArmarXDataPath.h
armarx::KinematicUnitDynamicSimulation::nodeNames
std::set< std::string > nodeNames
Definition: KinematicUnitDynamicSimulation.h:149
armarx::ManagedIceObject::usingProxy
bool usingProxy(const std::string &name, const std::string &endpoints="")
Registers a proxy for retrieval after initialization and adds it to the dependency list.
Definition: ManagedIceObject.cpp:154
armarx::KinematicUnit::robot
VirtualRobot::RobotPtr robot
Definition: KinematicUnit.h:155
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:27
armarx::KinematicUnitDynamicSimulation::reportState
void reportState(SimulatedRobotState const &state, const Ice::Current &) override
Definition: KinematicUnitDynamicSimulation.cpp:106
armarx::KinematicUnit::robotNodes
std::vector< VirtualRobot::RobotNodePtr > robotNodes
Definition: KinematicUnit.h:158
armarx::KinematicUnitDynamicSimulation::setJointTorques
void setJointTorques(const NameValueMap &targetJointTorques, const Ice::Current &c=Ice::emptyCurrent) override
Definition: KinematicUnitDynamicSimulation.cpp:241