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