CollisionFreeJointControl.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 RobotSkillTemplates::MotionControlGroup
17  * @author Mirko Waechter ( mirko dot waechter 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 
24 
27 
28 #include <RobotAPI/interface/components/TrajectoryPlayerInterface.h>
29 //#include <ArmarXCore/observers/variant/DatafieldRef.h>
30 
31 #include <VirtualRobot/CollisionDetection/CDManager.h>
32 #include <VirtualRobot/RobotNodeSet.h>
33 #include <VirtualRobot/TimeOptimalTrajectory/TimeOptimalTrajectory.h>
34 
36 
39 
41 #include <MotionPlanning/CSpace/CSpacePath.h>
42 #include <MotionPlanning/CSpace/CSpaceSampled.h>
43 #include <MotionPlanning/Planner/BiRrt.h>
44 #include <MotionPlanning/PostProcessing/ShortcutProcessor.h>
45 
46 using namespace armarx;
47 using namespace MotionControlGroup;
48 
49 // DO NOT EDIT NEXT LINE
50 CollisionFreeJointControl::SubClassRegistry
51  CollisionFreeJointControl::Registry(CollisionFreeJointControl::GetName(),
53 
54 void
56 {
57  // put your user code for the enter-point here
58  // execution time should be short (<100ms)
59 }
60 
61 void
63 {
64  // put your user code for the execution-phase here
65  // runs in seperate thread, thus can do complex operations
66  // should check constantly whether isRunningTaskStopped() returns true
67  TIMING_START(FullCalc);
68 
70  getContext<MotionControlGroupStatechartContext>();
71  std::set<std::string> jointNameSet;
72  if (!in.isSingleGoalConfigSet() && !in.isGoalConfigSet())
73  {
74  ARMARX_WARNING << "Either GoalConfig or SingleGoalConfig input parameter must be set!";
75  emitFailure();
76  return;
77  }
78  ARMARX_INFO << VAROUT(in.isGoalConfigSet()) << VAROUT(in.isSingleGoalConfigSet());
79  if (in.isSingleGoalConfigSet())
80  {
81  ARMARX_INFO << VAROUT(in.getSingleGoalConfig());
82  }
83  std::vector<StringValueMapPtr> goalConfig;
84  if (in.isGoalConfigSet())
85  {
86  goalConfig = in.getGoalConfig();
87  }
88  else
89  {
90  auto mapPtr = StringValueMap::FromStdMap(in.getSingleGoalConfig());
92  goalConfig.push_back(mapPtr);
93  }
94  // check for joint conflict
95  ARMARX_INFO << VAROUT(goalConfig.size());
96  for (auto goalConfigMapPtr : goalConfig)
97  {
98  ARMARX_CHECK_EXPRESSION(goalConfigMapPtr);
99  auto goalConfigMap = goalConfigMapPtr->toStdMap<float>();
100  for (auto pair : goalConfigMap)
101  {
102  if (jointNameSet.count(pair.first) != 0)
103  {
104  ARMARX_ERROR << "joint " << pair.first << " is used twice!";
105  emitFailure();
106  return;
107  }
108  jointNameSet.insert(pair.first);
109  }
110  }
111 
112  float timeStep = in.getTimestep();
113  std::vector<TrajectoryPtr> solutions;
114  TIMING_START(robotCloning);
115 
116  auto robot = context->getRobotPool()->getRobot(in.getSafetyMargin());
117  TIMING_END(robotCloning);
118  // TIMING_START(robotInflation);
119  // for (auto& node : robot->getRobotNodes())
120  // {
121  // if (node->getCollisionModel())
122  // {
123  // node->getCollisionModel()->inflateModel(30);
124  // }
125  // }
126  // // robot->inflateCollisionModel(30);
127  // TIMING_END(robotInflation);
128  if (!in.isCollisionSetNamesSet() && !in.isCollisionSetPairsSet())
129  {
130  throw LocalException()
131  << "You need to either specify CollisionSetNames or CollisionSetPairs!";
132  }
133 
134  VirtualRobot::CDManagerPtr cdm(new VirtualRobot::CDManager(robot->getCollisionChecker()));
135 
136 
137  auto rnsList = in.isCollisionSetNamesSet() ? in.getCollisionSetNames() : Ice::StringSeq();
138  for (size_t i = 0; i < rnsList.size(); ++i)
139  {
140  auto rns1 = robot->getRobotNodeSet(rnsList.at(i));
141  ARMARX_CHECK_NOT_NULL(rns1);
142  cdm->addCollisionModel(rns1);
143  // for (size_t j = i + 1; j < rnsList.size(); ++j)
144  // {
145  // auto rns1 = robot->getRobotNodeSet(rnsList.at(i));
146  // auto rns2 = robot->getRobotNodeSet(rnsList.at(j));
147  // ARMARX_CHECK_NOT_NULL(rns1);
148  // ARMARX_CHECK_NOT_NULL(rns2);
149  // ARMARX_INFO << "Adding: " << rns1->getName() << " and " << rns2->getName();
150  // cdm->addCollisionModelPair(rns1, rns2);
151  // }
152  }
153 
154  auto rnsPairList = in.getCollisionSetPairs();
155  for (auto& subList : rnsPairList)
156  {
157  ARMARX_CHECK_EQUAL(subList->getSize(), 2);
158  auto getRns = [&](const std::string& name)
159  {
160  VirtualRobot::RobotNodeSetPtr rns;
161  if (robot->hasRobotNodeSet(name))
162  {
163  rns = robot->getRobotNodeSet(name);
164  }
165  else
166  {
167  if (robot->hasRobotNode(name))
168  {
169  auto node = robot->getRobotNode(name);
170  rns = VirtualRobot::RobotNodeSet::createRobotNodeSet(
171  robot, node->getName(), {node});
172  }
173  }
174  ARMARX_CHECK_EXPRESSION(rns) << name;
175  return rns;
176  };
177 
178  auto rns1 = getRns(subList->getVariant(0)->getString());
179  auto rns2 = getRns(subList->getVariant(1)->getString());
180 
181  cdm->addCollisionModelPair(rns1, rns2);
182  }
183 
184  for (auto goalConfigMapPtr : goalConfig)
185  {
186  if (isRunningTaskStopped())
187  {
188  break;
189  }
190  auto goalConfigMap = goalConfigMapPtr->toStdMap<float>();
191  Ice::StringSeq jointNames = getMapKeys(goalConfigMap);
192 
193 
194  auto rns = VirtualRobot::RobotNodeSet::createRobotNodeSet(
195  robot, "tempset", jointNames, robot->getRootNode()->getName());
196  // auto rns = robot->getRobotNodeSet(in.getKinematicChain());
197  // auto jointNames = rns->getNodeNames();
198  Saba::CSpaceSampledPtr cspace(new Saba::CSpaceSampled(robot, cdm, rns, 1000000));
199 
200  Saba::BiRrt rrt(cspace, Saba::Rrt::eExtend);
201  rrt.setPlanningTimeout(in.getTimeoutMs());
203 
204  Eigen::VectorXf goalConfig(rns->getSize());
205  for (std::size_t i = 0; i < rns->getSize(); ++i)
206  {
207  goalConfig(i) = goalConfigMap.at(rns->getNode(i)->getName());
208  }
209  rrt.setStart(rns->getJointValuesEigen());
210  rrt.setGoal(goalConfig);
211  TIMING_START(Planning);
212  auto planningOk = rrt.plan();
213  TIMING_END(Planning);
214  Saba::CSpacePathPtr solutionOptimized;
215  if (planningOk)
216  {
217  ARMARX_INFO << " Planning succeeded ";
218  auto solution = rrt.getSolution();
219  TIMING_START(ShortCutting);
220 
221  // Saba::ElasticBandProcessorPtr postProcessing(new Saba::ElasticBandProcessor(solution, cspace, false));
222  Saba::ShortcutProcessorPtr postProcessing(
223  new Saba::ShortcutProcessor(solution, cspace, false));
224  solutionOptimized = postProcessing->shortenSolutionRandom(
225  in.getOptimizationSteps(), in.getOptimizationMaxStepSize());
226  TIMING_END(ShortCutting);
227  }
228  else
229  {
230  ARMARX_INFO << " Planning failed";
231  emitPlanningFailed();
232  return;
233  }
234 
235 
236  auto waypoints = solutionOptimized->getPoints();
237  ARMARX_INFO << "Waypoint Count: " << waypoints.size();
238  TrajectoryPtr waypointTraj = new Trajectory();
239  LimitlessStateSeq limitlessStates;
240  for (std::size_t i = 0; i < rns->getSize(); ++i)
241  {
242  auto node = rns->getNode(i);
243  limitlessStates.push_back(LimitlessState{
244  node->isLimitless(), node->getJointLimitLow(), node->getJointLimitHigh()});
245  }
246  waypointTraj->setDimensionNames(jointNames);
247  waypointTraj->setLimitless(limitlessStates);
248  int t = 0;
249  for (auto waypoint : waypoints)
250  {
251  for (std::size_t i = 0; i < rns->getSize(); ++i)
252  {
253  waypointTraj->setPositionEntry(t, i, waypoint(i));
254  }
255  t++;
256  }
258 
259  Eigen::VectorXd maxVelocities =
260  Eigen::VectorXd::Constant(rns->getSize(), (double)in.getMaxVelocity());
261  Eigen::VectorXd maxAcceleration =
262  Eigen::VectorXd::Constant(rns->getSize(), (double)in.getMaxAcceleration());
263  if (in.isJointScaleSet())
264  {
265  auto scalingMap = in.getJointScale();
266  for (size_t i = 0; i < rns->getSize(); ++i)
267  {
268  if (scalingMap.at(rns->getNode(i)->getName()) > 0)
269  {
270  auto scale = scalingMap.at(rns->getNode(i)->getName());
271  maxVelocities(i) *= scale;
272  maxAcceleration(i) *= scale;
273  }
274  }
275  }
276  auto newTraj =
277  waypointTraj->calculateTimeOptimalTrajectory(maxVelocities,
278  maxAcceleration,
279  in.getMaxDeviation(),
280  IceUtil::Time::secondsDouble(timeStep));
282  solutions.push_back(newTraj);
283  }
284  TrajectoryPtr combinedTraj(new Trajectory());
285  Ice::StringSeq jointNames;
286  int fullTrajDim = 0;
287  for (auto& sol : solutions)
288  {
289  size_t dims = sol->dim();
290  Ice::DoubleSeq timestamps = sol->getTimestamps();
291 
292  for (size_t d = 0; d < dims; ++d)
293  {
294  combinedTraj->addPositionsToDimension(
295  fullTrajDim, sol->getDimensionData(d), timestamps);
296  jointNames.push_back(sol->getDimensionName(d));
297  fullTrajDim++;
298  }
299  }
300  combinedTraj->setDimensionNames(jointNames);
301  double duration = combinedTraj->getTimeLength();
302  auto rns = VirtualRobot::RobotNodeSet::createRobotNodeSet(
303  robot, "tempset", jointNames, robot->getRootNode()->getName());
304  LimitlessStateSeq limitlessStates;
305  for (std::size_t i = 0; i < rns->getSize(); ++i)
306  {
307  auto node = rns->getNode(i);
308  limitlessStates.push_back(LimitlessState{
309  node->isLimitless(), node->getJointLimitLow(), node->getJointLimitHigh()});
310  }
311  combinedTraj->setLimitless(limitlessStates);
312 
313  TIMING_END(FullCalc);
314  ARMARX_INFO << "traj: " << combinedTraj->output();
315 
316  NameValueMap targetVelocities;
317 
318  if (in.getUseTrajectoryPlayerComponent())
319  {
320  TrajectoryPlayerInterfacePrx trajPlayer =
321  context->getProxy<TrajectoryPlayerInterfacePrx>(in.getTrajectoryPlayerName());
322  trajPlayer->resetTrajectoryPlayer(false);
323  trajPlayer->considerConstraints(false);
324  trajPlayer->setLoopPlayback(false);
325  trajPlayer->loadJointTraj(combinedTraj);
326  trajPlayer->startTrajectoryPlayer();
327  auto endTime = trajPlayer->getEndTime();
328  double currentTime = 0;
329  do
330  {
331  ARMARX_INFO << deactivateSpam(1) << "CurrentTime: " << currentTime
332  << " endTime: " << endTime;
333  usleep(10000);
334  currentTime = trajPlayer->getCurrentTime();
335  } while (currentTime < endTime && !isRunningTaskStopped());
336  if (!isRunningTaskStopped() && currentTime >= endTime)
337  {
338  if (in.getWaitTimeAfterExecution() > 0)
339  {
340  ARMARX_INFO << "Waiting for " << in.getWaitTimeAfterExecution();
341  TimeUtil::MSSleep(in.getWaitTimeAfterExecution());
342  }
343  trajPlayer->pauseTrajectoryPlayer();
344  emitSuccess();
345  }
346  else if (isRunningTaskStopped())
347  {
348  trajPlayer->pauseTrajectoryPlayer();
349  }
350  }
351  else
352  {
353  TrajectoryController ctrl(combinedTraj, in.getKp());
354 
355  CycleUtil cycle(timeStep * 1000);
356  NameControlModeMap modes;
357 
358  for (auto& jointName : jointNames)
359  {
360  modes[jointName] = eVelocityControl;
361  }
362  context->getKinematicUnit()->switchControlMode(modes);
363  // uncomment this if you need a continous run function. Make sure to use sleep or use blocking wait to reduce cpu load.
364  while (!isRunningTaskStopped()) // stop run function if returning true
365  {
366  // do your calculations
368 
369  Eigen::VectorXf velocityTargets = ctrl.update(timeStep, rns->getJointValuesEigen());
370  int i = 0;
371  for (auto& jointName : jointNames)
372  {
373  targetVelocities[jointName] = velocityTargets(i);
374  i++;
375  }
376  context->getKinematicUnit()->setJointVelocities(targetVelocities);
377  // context->getDebugDrawerTopicProxy()->setSphereVisu("trajectory", "timestep" + std::to_string(), new )
378  ARMARX_INFO << deactivateSpam(2) << "timestep: " << ctrl.getCurrentTimestamp()
379  << " Duration: " << duration;
380  if (ctrl.getCurrentTimestamp() >= duration)
381  {
382  ARMARX_INFO << "Reached Goal!";
383  emitSuccess();
384  break;
385  }
386  cycle.waitForCycleDuration();
387  }
388  for (auto& jointName : jointNames)
389  {
390  targetVelocities[jointName] = 0;
391  }
392  context->getKinematicUnit()->setJointVelocities(targetVelocities);
393  }
395 
396  for (auto goalConfigMapPtr : goalConfig)
397  {
398  auto goalConfigMap = goalConfigMapPtr->toStdMap<float>();
399  NameValueMap errors;
400  for (auto& pair : goalConfigMap)
401  {
402  errors[pair.first] = robot->getRobotNode(pair.first)->getJointValue();
403  }
404  ARMARX_INFO << VAROUT(errors) << VAROUT(goalConfigMap);
405  }
406 }
407 
408 void
410 {
411  // put your user code for the breaking point here
412  // execution time should be short (<100ms)
413  if (in.getUseTrajectoryPlayerComponent())
414  {
416  getContext<MotionControlGroupStatechartContext>();
417  TrajectoryPlayerInterfacePrx trajPlayer =
418  context->getProxy<TrajectoryPlayerInterfacePrx>(in.getTrajectoryPlayerName());
419  trajPlayer->stopTrajectoryPlayer();
420  }
421 }
422 
423 void
425 {
426  // put your user code for the exit point here
427  // execution time should be short (<100ms)
428 }
429 
430 // DO NOT EDIT NEXT FUNCTION
433 {
434  return XMLStateFactoryBasePtr(new CollisionFreeJointControl(stateData));
435 }
TIMING_START
#define TIMING_START(name)
Definition: TimeUtil.h:289
algorithm.h
armarx::TrajectoryController
Subcontroller which handles all program interaction with the modle, communicates with other controlle...
Definition: TrajectoryController.h:32
TIMING_END
#define TIMING_END(name)
Definition: TimeUtil.h:306
armarx::MotionControlGroup::MotionControlGroupStatechartContext
Definition: MotionControlGroupStatechartContext.h:75
armarx::RemoteRobot::synchronizeLocalClone
static bool synchronizeLocalClone(VirtualRobot::RobotPtr robot, RobotStateComponentInterfacePrx robotStatePrx)
Definition: RemoteRobot.cpp:522
armarx::MotionControlGroup::CollisionFreeJointControl::Registry
static SubClassRegistry Registry
Definition: CollisionFreeJointControl.h:46
armarx::MotionControlGroup::CollisionFreeJointControl::onBreak
void onBreak() override
Definition: CollisionFreeJointControl.cpp:409
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::TrajectoryController::FoldLimitlessJointPositions
static void FoldLimitlessJointPositions(TrajectoryPtr traj)
Definition: TrajectoryController.cpp:178
armarx::TimeUtil::MSSleep
static void MSSleep(int durationMS)
lock the calling thread for a given duration (like usleep(...) but using Timeserver time)
Definition: TimeUtil.cpp:100
armarx::XMLStateConstructorParams
Definition: XMLState.h:49
armarx::CycleUtil
This util class helps with keeping a cycle time during a control cycle.
Definition: CycleUtil.h:40
armarx::MotionControlGroup::CollisionFreeJointControl::onExit
void onExit() override
Definition: CollisionFreeJointControl.cpp:424
armarx::XMLStateFactoryBasePtr
IceInternal::Handle< XMLStateFactoryBase > XMLStateFactoryBasePtr
Definition: XMLState.h:64
armarx::MotionControlGroup::MotionControlGroupStatechartContext::getRobotPool
const RobotPoolPtr & getRobotPool() const
Robot Pool containing collision robots.
Definition: MotionControlGroupStatechartContext.h:160
armarx::TrajectoryController::getCurrentTimestamp
double getCurrentTimestamp() const
Definition: TrajectoryController.cpp:129
IceInternal::Handle< Trajectory >
deactivateSpam
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
Definition: Logging.cpp:75
armarx::StringValueMap::FromStdMap
static StringValueMapPtr FromStdMap(const std::map< std::string, Type > &map)
FromStdMap creates a StringValueMap from a std::map<std::string, Type>.
Definition: StringValueMap.h:203
armarx::MotionControlGroup::MotionControlGroupStatechartContext::getRobotStateComponent
RobotStateComponentInterfacePrx getRobotStateComponent()
Definition: MotionControlGroupStatechartContext.h:114
armarx::TrajectoryController::UnfoldLimitlessJointPositions
static void UnfoldLimitlessJointPositions(TrajectoryPtr traj)
Definition: TrajectoryController.cpp:141
armarx::MotionControlGroup::CollisionFreeJointControl::CreateInstance
static XMLStateFactoryBasePtr CreateInstance(XMLStateConstructorParams stateData)
Definition: CollisionFreeJointControl.cpp:432
CollisionFreeJointControl.h
armarx::CycleUtil::waitForCycleDuration
IceUtil::Time waitForCycleDuration()
This function will wait (virtual or system time) until the cycle time is reached.
Definition: CycleUtil.cpp:53
armarx::TrajectoryController::update
const Eigen::VectorXf & update(double deltaT, const Eigen::VectorXf &currentPosition)
Definition: TrajectoryController.cpp:67
ARMARX_ERROR
#define ARMARX_ERROR
Definition: Logging.h:196
MotionControlGroupStatechartContext.h
armarx::VariantType::Trajectory
const VariantTypeId Trajectory
Definition: Trajectory.h:44
armarx::MotionControlGroup::CollisionFreeJointControl::CollisionFreeJointControl
CollisionFreeJointControl(const XMLStateConstructorParams &stateData)
Definition: CollisionFreeJointControl.h:32
CycleUtil.h
armarx::control::njoint_controller::platform::platform_follower_controller::NameValueMap
std::map< std::string, float > NameValueMap
Definition: PlatformFollowerController.h:88
Trajectory.h
armarx::MotionControlGroup::MotionControlGroupStatechartContext::getKinematicUnit
KinematicUnitInterfacePrx getKinematicUnit()
Definition: MotionControlGroupStatechartContext.h:120
armarx::MotionControlGroup::CollisionFreeJointControl::run
void run() override
Definition: CollisionFreeJointControl.cpp:62
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
TimeUtil.h
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
VAROUT
#define VAROUT(x)
Definition: StringHelpers.h:198
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:193
armarx::ManagedIceObject::getProxy
Ice::ObjectPrx getProxy(long timeoutMs=0, bool waitForScheduler=true) const
Returns the proxy of this object (optionally it waits for the proxy)
Definition: ManagedIceObject.cpp:407
TrajectoryController.h
armarx::MotionControlGroup::CollisionFreeJointControl::onEnter
void onEnter() override
Definition: CollisionFreeJointControl.cpp:55
armarx::getMapKeys
void getMapKeys(const MapType &map, OutputIteratorType it)
Definition: algorithm.h:173
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:27