Robowflex  v0.1
Making MoveIt Easy
space.cpp
Go to the documentation of this file.
1 /* Author: Zachary Kingston */
2 
3 #include <ompl/base/spaces/RealVectorStateProjections.h>
4 
7 
8 #include <robowflex_dart/space.h>
9 #include <robowflex_dart/world.h>
10 
11 #include <utility>
12 
14 using namespace robowflex::darts;
15 
16 ///
17 /// StateSpace::StateSampler
18 ///
19 
21  : ompl::base::RealVectorStateSampler(space), joints_(space->joints_)
22 {
23 }
24 
25 void StateSpace::StateSampler::sampleUniform(ompl::base::State *state)
26 {
27  auto *as = state->as<StateType>();
28 
29  for (const auto &joint : joints_)
30  joint->sample(joint->getSpaceVars(as->data));
31 }
32 
33 void StateSpace::StateSampler::sampleUniformNear(ompl::base::State *state, const ompl::base::State *near,
34  double distance)
35 {
36  auto *as = state->as<StateType>();
37  const auto *an = near->as<StateType>();
38 
39  for (const auto &joint : joints_)
40  joint->sampleNear(joint->getSpaceVars(as->data), joint->getSpaceVarsConst(an->data), distance);
41 }
42 
43 ///
44 /// StateSpace::StateType
45 ///
46 
48 {
49  values = data.data();
50 }
51 
52 ///
53 /// StateSpace::StateType
54 ///
55 
56 StateSpace::StateSpace(WorldPtr world) : ompl::base::RealVectorStateSpace(), world_(std::move(world))
57 {
58 }
59 
61 {
62  return metric_;
63 }
64 
65 void StateSpace::addGroup(const std::string &name, const std::string &group, std::size_t cyclic)
66 {
67  auto robot = world_->getRobot(name);
68  if (not robot)
69  {
70  RBX_ERROR("Robot %1% does not exist in world.", name);
71  throw std::runtime_error("Invalid robot");
72  }
73 
74  auto joints = robot->getGroupJoints(group);
75  addGroupFromJoints(group, joints, cyclic);
76 }
77 
80 {
81  group_joints_.emplace(group_name, std::vector<JointPtr>{});
82  group_dimension_.emplace(group_name, 0);
83 
84  for (auto *joint : joints)
85  {
86  if (jointset_.find(joint) != jointset_.end())
87  {
88  addJointToGroup(group_name, getJoint(joint->getName()));
89  continue;
90  }
91 
92  jointset_.emplace(joint);
93 
94  const auto &type = joint->getType();
95  if (type == "RevoluteJoint")
96  {
97  auto *revolute = static_cast<dart::dynamics::RevoluteJoint *>(joint);
98 
99  if (revolute->isCyclic(0))
100  {
101  if (cyclic)
102  {
103  double low = -constants::pi * cyclic;
104  double high = constants::pi * cyclic;
105  addJoint(group_name, std::make_shared<RnJoint>(this, revolute, low, high));
106  }
107  else
108  addJoint(group_name, std::make_shared<SO2Joint>(this, revolute));
109  }
110  else
111  {
112  auto *dof = joint->getDof(0);
113  auto limits = dof->getPositionLimits();
114  addJoint(group_name, std::make_shared<RnJoint>(this, revolute, limits.first, limits.second));
115  }
116  }
117  else if (type == "PrismaticJoint")
118  {
119  auto *prismatic = static_cast<dart::dynamics::PrismaticJoint *>(joint);
120  auto *dof = joint->getDof(0);
121  auto limits = dof->getPositionLimits();
122  addJoint(group_name, std::make_shared<RnJoint>(this, prismatic, limits.first, limits.second));
123  }
124  else if (type == "PlanarJoint")
125  {
126  // Assume XY plane for now
127  auto *planar = static_cast<dart::dynamics::PlanarJoint *>(joint);
128  if (cyclic)
129  {
130  Eigen::Vector3d low;
131  Eigen::Vector3d high;
132 
133  // XY limits
134  for (std::size_t i = 0; i < 2; ++i)
135  {
136  low[i] = world_->getWorkspaceLowConst()[i];
137  high[i] = world_->getWorkspaceHighConst()[i];
138  }
139 
140  low[2] = -constants::pi * cyclic;
141  high[2] = constants::pi * cyclic;
142 
143  addJoint(group_name, std::make_shared<RnJoint>(this, planar, 3, 0, low, high));
144  }
145  else
146  {
147  Eigen::Vector2d low;
148  Eigen::Vector2d high;
149 
150  for (std::size_t i = 0; i < 2; ++i)
151  {
152  low[i] = world_->getWorkspaceLowConst()[i];
153  high[i] = world_->getWorkspaceHighConst()[i];
154  }
155 
156  addJoint(group_name, std::make_shared<RnJoint>(this, planar, 2, 0, low, high));
157  addJoint(group_name, std::make_shared<SO2Joint>(this, planar, 2));
158  }
159  }
160  else if (type == "FreeJoint")
161  {
162  auto *free = static_cast<dart::dynamics::FreeJoint *>(joint);
163 
164  if (cyclic)
165  {
166  double alow = -constants::pi * cyclic;
167  double ahigh = constants::pi * cyclic;
168 
169  Eigen::Vector6d low;
170  Eigen::Vector6d high;
171 
172  for (std::size_t i = 0; i < 3; ++i)
173  {
174  low[i] = alow;
175  high[i] = ahigh;
176  low[3 + i] =
177  std::max({free->getPositionLowerLimit(3 + i), world_->getWorkspaceLowConst()[i]});
178  high[3 + i] =
179  std::min({free->getPositionUpperLimit(3 + i), world_->getWorkspaceHighConst()[i]});
180  }
181  auto j = std::make_shared<RnJoint>(this, free, 6, 0, low, high);
182  addJoint(group_name, j);
183  }
184  else
185  {
186  Eigen::Vector3d low;
187  Eigen::Vector3d high;
188 
189  for (std::size_t i = 0; i < 3; ++i)
190  {
191  low[i] =
192  std::max({free->getPositionLowerLimit(3 + i), world_->getWorkspaceLowConst()[i]});
193  high[i] =
194  std::min({free->getPositionUpperLimit(3 + i), world_->getWorkspaceHighConst()[i]});
195  }
196 
197  addJoint(group_name, std::make_shared<RnJoint>(this, free, 3, 3, low, high));
198  addJoint(group_name, std::make_shared<SO3Joint>(this, free));
199  }
200  }
201  else
202  RBX_WARN("Unknown joint type %1%, skipping.", type);
203  }
204 
205  registerDefaultProjection(
206  std::make_shared<ompl::base::RealVectorRandomLinearProjectionEvaluator>(this, 2));
207 }
208 
209 void StateSpace::addJoint(const std::string &group_name, const JointPtr &joint)
210 {
211  joints_.emplace_back(joint);
212  addJointToGroup(group_name, joint);
213 
214  if (not std::dynamic_pointer_cast<RnJoint>(joint))
215  metric_ = false;
216 }
217 
218 void StateSpace::addJointToGroup(const std::string &group_name, const JointPtr &joint)
219 {
220  group_joints_[group_name].emplace_back(joint);
221  group_dimension_[group_name] += joint->getDimension();
222 }
223 
224 void StateSpace::setWorldState(WorldPtr world, const ompl::base::State *state) const
225 {
226  const auto &as = state->as<StateType>();
227  setWorldState(std::move(world), as->data);
228 }
229 
230 void StateSpace::setWorldState(WorldPtr world, const Eigen::Ref<const Eigen::VectorXd> &x) const
231 {
232  for (const auto &joint : joints_)
233  {
234  const auto &v = joint->getSpaceVarsConst(x);
235  joint->setJointState(world, v);
236  }
237 
238  world->forceUpdate();
239 }
240 
241 void StateSpace::getWorldState(WorldPtr world, ompl::base::State *state) const
242 {
243  auto *as = state->as<StateType>();
244  getWorldState(std::move(world), as->data);
245 }
246 
247 void StateSpace::getWorldState(WorldPtr world, Eigen::Ref<Eigen::VectorXd> x) const
248 {
249  for (const auto &joint : joints_)
250  {
251  const auto &v = joint->getSpaceVars(x);
252  joint->getJointState(world, v);
253  }
254 }
255 
257  const Eigen::Ref<const Eigen::VectorXd> &x) const
258 {
259  const auto &joints = group_joints_.find(group_name)->second;
260 
261  std::size_t index = 0;
262  for (const auto &joint : joints)
263  {
264  std::size_t n = joint->getDimension();
265  joint->setJointState(world, x.segment(index, n));
266  index += n;
267  }
268 
269  world->forceUpdate();
270 }
271 
273  Eigen::Ref<Eigen::VectorXd> x) const
274 {
275  const auto &joints = group_joints_.find(group_name)->second;
276 
277  std::size_t index = 0;
278  for (const auto &joint : joints)
279  {
280  std::size_t n = joint->getDimension();
281  joint->getJointState(world, x.segment(index, n));
282  index += n;
283  }
284 }
285 
286 void StateSpace::enforceBounds(ompl::base::State *state) const
287 {
288  const auto &as = state->as<StateType>();
289  for (const auto &joint : joints_)
290  {
291  auto v = joint->getSpaceVars(as->data);
292  joint->enforceBounds(v);
293  }
294 }
295 
296 bool StateSpace::satisfiesBounds(const ompl::base::State *state) const
297 {
298  const auto &as = state->as<StateType>();
299  for (const auto &joint : joints_)
300  {
301  const auto &v = joint->getSpaceVarsConst(as->data);
302  if (not joint->satisfiesBounds(v))
303  return false;
304  }
305 
306  return true;
307 }
308 
309 double StateSpace::distance(const ompl::base::State *state1, const ompl::base::State *state2) const
310 {
311  const auto &as1 = state1->as<StateType>();
312  const auto &as2 = state2->as<StateType>();
313 
314  double d = 0;
315  for (const auto &joint : joints_)
316  {
317  const auto &v1 = joint->getSpaceVarsConst(as1->data);
318  const auto &v2 = joint->getSpaceVarsConst(as2->data);
319 
320  d += joint->distance(v1, v2);
321  }
322 
323  return d;
324 }
325 
327 {
328  double d = 0;
329  for (const auto &joint : joints_)
330  d += joint->getMaximumExtent();
331 
332  return d;
333 }
334 
335 bool StateSpace::equalStates(const ompl::base::State *state1, const ompl::base::State *state2) const
336 {
337  return distance(state1, state2) <= 1e-8;
338 }
339 
340 void StateSpace::interpolate(const ompl::base::State *from, const ompl::base::State *to, double t,
341  ompl::base::State *state) const
342 {
343  const auto &af = from->as<StateType>();
344  const auto &at = to->as<StateType>();
345  auto *as = state->as<StateType>();
346 
347  for (const auto &joint : joints_)
348  {
349  const auto &vf = joint->getSpaceVarsConst(af->data);
350  const auto &vt = joint->getSpaceVarsConst(at->data);
351  auto vs = joint->getSpaceVars(as->data);
352 
353  joint->interpolate(vf, vt, t, vs);
354  }
355 }
356 
357 ompl::base::StateSamplerPtr StateSpace::allocDefaultStateSampler() const
358 {
359  return std::make_shared<StateSampler>(this);
360 }
361 
362 ompl::base::State *StateSpace::allocState() const
363 {
364  return new StateType(dimension_);
365 }
366 
367 void StateSpace::freeState(ompl::base::State *state) const
368 {
369  auto *as = state->as<StateType>();
370  delete as;
371 }
372 
374 {
375  return world_;
376 }
377 
379 {
380  return world_;
381 }
382 
384 {
386  for (const auto &joint : joints_)
387  {
388  auto skelx = joint->getSkeletonIndex();
389  auto add = joint->getIndices();
390  for (const auto &index : add)
391  indices.emplace_back(skelx, index);
392  }
393 
394  return indices;
395 }
396 
398 {
399  return joints_[index];
400 }
401 
403 {
404  auto it = std::find_if(joints_.begin(), joints_.end(),
405  [&](const JointPtr &j) { return j->getJoint(world_)->getName() == name; });
406  if (it != joints_.end())
407  return *it;
408  return nullptr;
409 }
410 
412 {
413  return joints_;
414 }
415 
416 void StateSpace::getGroupState(const std::string &group, const ompl::base::State *state,
417  Eigen::Ref<Eigen::VectorXd> v) const
418 {
419  const auto &joints = group_joints_.find(group)->second;
420  const auto &as = state->as<StateType>();
421 
422  std::size_t index = 0;
423  for (const auto &joint : joints)
424  {
425  std::size_t n = joint->getDimension();
426  v.segment(index, n) = joint->getSpaceVarsConst(as->data);
427  index += n;
428  }
429 }
430 
431 void StateSpace::setGroupState(const std::string &group, ompl::base::State *state,
432  const Eigen::Ref<const Eigen::VectorXd> &v) const
433 {
434  const auto &joints = group_joints_.find(group)->second;
435  auto *as = state->as<StateType>();
436 
437  std::size_t index = 0;
438  for (const auto &joint : joints)
439  {
440  std::size_t n = joint->getDimension();
441  joint->getSpaceVars(as->data) = v.segment(index, n);
442  index += n;
443  }
444 }
445 
447 {
448  return group_dimension_.find(group)->second;
449 }
450 
452 {
454  for (const auto &pair : group_joints_)
455  groups.emplace_back(pair.first);
456 
457  return groups;
458 }
459 
461 {
463 
464  const auto &joints = group_joints_.find(group_name)->second;
465  for (const auto &joint : joints)
466  {
467  const auto &jdofs = joint->getDofs();
468  dofs.insert(dofs.end(), jdofs.begin(), jdofs.end());
469  }
470 
471  return dofs;
472 }
473 
474 Eigen::VectorXd StateSpace::getLowerBound() const
475 {
476  const auto &bounds = getBounds();
477  return Eigen::Map<const Eigen::VectorXd>(bounds.low.data(), bounds.low.size());
478 }
479 
480 Eigen::VectorXd StateSpace::getUpperBound() const
481 {
482  const auto &bounds = getBounds();
483  return Eigen::Map<const Eigen::VectorXd>(bounds.high.data(), bounds.high.size());
484 }
485 
486 void StateSpace::setMetricSpace(bool metric)
487 {
488  metric_ = metric;
489 }
A shared pointer wrapper for robowflex::darts::Joint.
void sampleUniform(ompl::base::State *state) override
Definition: space.cpp:25
void sampleUniformNear(ompl::base::State *state, const ompl::base::State *near, double distance) override
Definition: space.cpp:33
StateSampler(const StateSpace *space)
Constructor.
Definition: space.cpp:20
State type for the robowflex::darts::StateSpace.
Definition: space.h:69
Eigen::VectorXd data
Vector for configuration.
Definition: space.h:76
StateType(std::size_t n)
Constructor.
Definition: space.cpp:47
An OMPL state space for robowflex::darts::World. Can do motion planning for any of the robots or stru...
Definition: space.h:31
void addJointToGroup(const std::string &group_name, const JointPtr &joint)
Definition: space.cpp:218
void setWorldState(WorldPtr world, const ompl::base::State *state) const
Set the state of a world from an OMPL state.
Definition: space.cpp:224
bool metric_
Is this space all Rn?
Definition: space.h:262
void interpolate(const ompl::base::State *from, const ompl::base::State *to, double t, ompl::base::State *state) const override
Definition: space.cpp:340
std::vector< std::pair< std::size_t, std::size_t > > getIndices() const
Get the set of indices that is being planned for. Pairs of skeleton index and joint index.
Definition: space.cpp:383
void getGroupState(const std::string &group, const ompl::base::State *state, Eigen::Ref< Eigen::VectorXd > v) const
From a full state, get only the state of a group.
Definition: space.cpp:416
Eigen::VectorXd getLowerBound() const
Get a vector of the lower joint bounds for the space.
Definition: space.cpp:474
const WorldPtr & getWorldConst() const
Get underlying world.
Definition: space.cpp:378
ompl::base::State * allocState() const override
Definition: space.cpp:362
void getWorldState(WorldPtr world, ompl::base::State *state) const
Get the state of a world in an OMPL state.
Definition: space.cpp:241
const std::vector< JointPtr > & getJoints() const
Get a vector of the joints being planned for.
Definition: space.cpp:411
bool isMetricSpace() const override
Definition: space.cpp:60
bool satisfiesBounds(const ompl::base::State *state) const override
Definition: space.cpp:296
StateSpace(WorldPtr world)
Constructor.
Definition: space.cpp:56
Eigen::VectorXd getUpperBound() const
Get a vector of the upper joint bounds for the space.
Definition: space.cpp:480
void enforceBounds(ompl::base::State *state) const override
Definition: space.cpp:286
WorldPtr world_
World to use for planning.
Definition: space.h:257
std::vector< JointPtr > joints_
Vector of all joints used in planning.
Definition: space.h:264
double distance(const ompl::base::State *state1, const ompl::base::State *state2) const override
Definition: space.cpp:309
void setMetricSpace(bool metric)
Definition: space.cpp:486
void addJoint(const std::string &group_name, const JointPtr &joint)
Definition: space.cpp:209
std::set< dart::dynamics::Joint * > jointset_
Set of joints used in planning.
Definition: space.h:259
ompl::base::StateSamplerPtr allocDefaultStateSampler() const override
Definition: space.cpp:357
double getMaximumExtent() const override
Definition: space.cpp:326
std::vector< std::string > getGroupDofNames(const std::string &group_name) const
Get the names of each of the dof controlled by a group.
Definition: space.cpp:460
void freeState(ompl::base::State *state) const override
Definition: space.cpp:367
void addGroupFromJoints(const std::string &group_name, const std::vector< dart::dynamics::Joint * > &joints, std::size_t cyclic=0)
Add a group to be planned for.
Definition: space.cpp:78
void addGroup(const std::string &name, const std::string &group, std::size_t cyclic=0)
Add a group to be planned for.
Definition: space.cpp:65
std::map< std::string, std::vector< JointPtr > > group_joints_
Joints belonging to a group.
Definition: space.h:268
std::map< std::string, std::size_t > group_dimension_
Dimension of the group.
Definition: space.h:269
bool equalStates(const ompl::base::State *state1, const ompl::base::State *state2) const override
Definition: space.cpp:335
WorldPtr getWorld()
Get underlying world.
Definition: space.cpp:373
void getWorldGroupState(WorldPtr world, const std::string &group_name, Eigen::Ref< Eigen::VectorXd > x) const
Get the group state of a world.
Definition: space.cpp:272
void setGroupState(const std::string &group, ompl::base::State *state, const Eigen::Ref< const Eigen::VectorXd > &v) const
Set a (sub)group state in a full state.
Definition: space.cpp:431
std::size_t getGroupDimension(const std::string &group) const
Get the dimension of joint variables for a subgroup.
Definition: space.cpp:446
JointPtr getJoint(std::size_t index) const
Get a joint that is being planned for.
Definition: space.cpp:397
void setWorldGroupState(WorldPtr world, const std::string &group_name, const Eigen::Ref< const Eigen::VectorXd > &x) const
Set the state of a world from a configuration of a group.
Definition: space.cpp:256
std::vector< std::string > getGroups() const
Get the names of all groups managed by this space.
Definition: space.cpp:451
A shared pointer wrapper for robowflex::darts::World.
T emplace_back(T... args)
T emplace(T... args)
T end(T... args)
T find(T... args)
T insert(T... args)
#define RBX_WARN(fmt,...)
Output a warning logging message.
Definition: log.h:110
#define RBX_ERROR(fmt,...)
Output a error logging message.
Definition: log.h:102
T max(T... args)
T min(T... args)
T move(T... args)
Functions for loading and animating robots in Blender.
static const double pi
Definition: constants.h:21
DART-based robot modeling and planning.
Definition: acm.h:16