Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor DART StateSpaces #278

Merged
merged 20 commits into from
Jan 11, 2018
Merged

Conversation

brianhou
Copy link
Contributor

@brianhou brianhou commented Dec 8, 2017

This PR refactors AIKIDO's DART state spaces to decouple the state space from the underlying DART Joint or MetaSkeleton, as suggested by @mkoval and @psigen in #249.

This will be a hugely backwards-incompatible API change. Any code that uses MetaSkeletonStateSpace::getMetaSkeleton, JointStateSpace::getJoint, or MetaSkeletonStateSpaceSaver will need to be fixed.

Quick summary of changes:

  • JointStateSpace::getJoint has been removed and JointStateSpace::getProperties has been added.
  • MetaSkeletonStateSpace::getMetaSkeleton has been removed and MetaSkeletonStateSpace::getProperties has been added. MetaSkeletonStateSpace::Properties also holds information about how to map (joint index, joint dof index) to metaskeleton dof index, rather than re-computing each time we need to convert between states and positions.
  • MetaSkeletonStateSpaceSaver has been renamed to MetaSkeletonStateSaver. I think this makes more sense, since it was most importantly used to save the current MetaSkeleton position (which would no longer be in a MetaSkeletonStateSpace).
  • Many constraints (e.g. constraint::CollisionFree, constraint::InverseKinematicsSampleable) now take in an additional MetaSkeleton argument. This is necessary so they have a concrete skeleton that they can test with.
  • Conversions between SplineTrajectory and ROS JointTrajectory are somewhat different. The joint names in the JointTrajectory now come from the DOF names, rather than the Joint names. I thought this was simpler, but could be convinced to figure out how to use Joint names instead if this is the wrong thing to do. (It seems that each joint in a ROS JointTrajectory can only take on one value, so maybe it's closer to what we mean by DOF?)

Note: one of the VectorFieldPlanner tests is currently failing, but I figured it's not really worth debugging since the improved VectorFieldPlanner will be ready soon and will need to be ported to the new MetaSkeletonStateSpace anyway.


Before creating a pull request

  • Document new methods and classes
  • Format code with make format

Before merging a pull request

  • Set version target by selecting a milestone on the right side
  • Summarize this change in CHANGELOG.md
  • Add unit test(s) for this change

This decouples the state space from the underlying DART Joint that was
used to generate the state space. Joint properties (e.g. position
limits) are maintained in a separate JointStateSpace::Properties field,
which is not tied to the original DART Joint.

This also changes the interfaces for the JointStateSpace::getState and
JointStateSpace::setState methods to take in a DART Joint.
Since MetaSkeletonStateSpaces won't have an internal MetaSkeleton,
having a MetaSkeletonStateSpaceSaver doesn't make sense.
This decouples the state space from the underlying DART MetaSkeleton
that was used to generate the state space. Properties are maintained in
a separate MetaSkeletonStateSpace::Properties field.

This changes the interfaces for the MetaSkeletonStateSpace::getState and
MetaSkeletonStateSpace::setState methods to take in a DART MetaSkeleton.

This also changes the interfaces for many of the constraints and
executors to take in an additional DART MetaSkeleton argument.

The VectorFieldPlanner code is in a separate commit so it can be easily
reverted when the improved VectorFieldPlanner is implemented.
One of the VectorFieldPlanner tests is currently failing, but I figured
it's not worth debugging since the improved VectorFieldPlanner will be
ready soon. This is in a separate commit so it can be easily reverted
when the improved implementation is ready.
@codecov
Copy link

codecov bot commented Dec 8, 2017

Codecov Report

Merging #278 into master will decrease coverage by 0.32%.
The diff coverage is 73.5%.

@@            Coverage Diff             @@
##           master     #278      +/-   ##
==========================================
- Coverage   79.75%   79.42%   -0.33%     
==========================================
  Files         201      202       +1     
  Lines        5768     5841      +73     
==========================================
+ Hits         4600     4639      +39     
- Misses       1168     1202      +34
Impacted Files Coverage Δ
...lude/aikido/constraint/FramePairDifferentiable.hpp 100% <ø> (ø) ⬆️
include/aikido/statespace/dart/SO3Joint.hpp 100% <ø> (ø) ⬆️
include/aikido/statespace/dart/SO2Joint.hpp 100% <ø> (ø) ⬆️
include/aikido/statespace/StateSpace.hpp 100% <ø> (ø) ⬆️
...do/planner/vectorfield/BodyNodePoseVectorField.hpp 100% <ø> (ø) ⬆️
...ner/vectorfield/MoveEndEffectorPoseVectorField.hpp 100% <ø> (ø) ⬆️
include/aikido/constraint/FrameDifferentiable.hpp 100% <ø> (ø) ⬆️
include/aikido/statespace/dart/WeldJoint.hpp 100% <ø> (ø) ⬆️
...r/vectorfield/MoveEndEffectorOffsetVectorField.hpp 100% <ø> (ø) ⬆️
include/aikido/constraint/CollisionFree.hpp 100% <ø> (ø) ⬆️
... and 41 more

Copy link
Member

@mkoval mkoval left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great. Nice work @brianhou! I generally think this is ready-to-merge once you address the merge conflicts with devel, which seem to be caused by the recent merge of #286.

Two random musings:

  1. It's annoying that we often pass around a MetaSkeletonStateSpace and a concrete MetaSkeleton as a pair, e.g. to implement constraints. If this continues to be an issue, it may be worthwhile to wrap this in a helper class that is effectively an std::pair that has an API similar to the old implementation of MetaSkeletonStateSpace.
  2. At some point we'll likely want to parallelize constraint evaluations. That will require cloning a constraint onto a different MetaSkeleton, e.g. creating two PoseConstraints that refer to the different MetaSkeletons that both instantiate the same MetaSkeletonStateSpace. This will be tricky to implement for constraints that wrap other constraints - but I have some ideas here.

/// \return Degree of freedom
const dart::dynamics::DegreeOfFreedom* dof() const;
/// \return Degree of freedom name
const std::string dof() const;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const is not meaningful here. Also, I suggest naming this "DOF name" - since it is now a string rather than a DegreeOfFreedom object itself.

const Eigen::VectorXd getVelocityLowerLimits() const;

/// Return the vector of velocity upper limits.
const Eigen::VectorXd getVelocityUpperLimits() const;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of these const return values are not meaningful. Consider returning by const & instead.

std::size_t getNumDofs() const;

/// Return the names of DOFs in the joint.
std::vector<std::string> getDofNames() const;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Return by const &?

const std::string getName() const;

/// Return the type of the joint.
const std::string getType() const;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Return by const &?

explicit Properties(::dart::dynamics::Joint* _joint);

/// Return the name of the joint.
const std::string getName() const;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Return by const &?

/// Mapping from Joint index and Joint DOF index to MetaSkeleton DOF index
std::unordered_map<std::size_t,
std::unordered_map<std::size_t, std::size_t>>
mIndexMap;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a suggestion: If the docstring is correct, maybe this should be a:

std::unordered_map<std::pair<std::size_t, std::size_t>, std::size_t>

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was because pairs don't come with a hash function and I was being sloppy... I'll fix it.

for (std::size_t idof = 0; idof < joint->getNumDofs(); ++idof)
{
const auto dof = joint->getDof(idof);
const auto dofName = dof->getName();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: const auto&?

std::size_t MetaSkeletonStateSpace::Properties::getDofIndex(
const std::string& dofName) const
{
std::vector<std::size_t> indices;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Call indices.reserve(mDofNames.size()) here.

using CartesianProduct::State;
using CartesianProduct::ScopedState;

/// Constructs a state space for a DART \c MetaSkeleton.
///
/// \param _metaskeleton target \c MetaSkeleton
MetaSkeletonStateSpace(::dart::dynamics::MetaSkeletonPtr _metaskeleton);
MetaSkeletonStateSpace(::dart::dynamics::MetaSkeleton* _metaskeleton);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mark this as explicit. It should have been before, too! 😱

/// \return \c MetaSkeleton associated with this state space
::dart::dynamics::MetaSkeletonPtr getMetaSkeleton() const;
/// \return MetaSkeleton properties associated with this state space
const Properties getProperties() const;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: const is not meaningful.

@jslee02 jslee02 added this to the Aikido 0.3.0 milestone Dec 15, 2017
@brianhou
Copy link
Contributor Author

brianhou commented Jan 7, 2018

I've updated this PR with the new VectorFieldPlanner implementation, so there are no longer any conflicts with master. Can someone (@gilwoolee or @jslee02) take one last pass over this before I merge?

@jslee02 jslee02 self-requested a review January 8, 2018 18:58
jslee02 added a commit that referenced this pull request Jan 9, 2018
Copy link
Member

@jslee02 jslee02 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per this change, all the DART state spaces take DART objects (meta-skeleton and joints) only to retrieve data from the DART objects but not to change them. So it would be good to take DART objects as const variable. I've made this change in this branch so feel free to merge if it looks good to you.

Also, DART state space assumes the passing-in DART object pointer is not nullptr. I think we should either throw an exception for nullptr or take it as a const reference.

Copy link
Contributor

@gilwoolee gilwoolee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made a few small comments but other than that it looks good. :)

@@ -31,8 +31,8 @@ namespace vectorfield {
bool computeJointVelocityFromTwist(
Eigen::VectorXd& jointVelocity,
const Eigen::Vector6d& desiredTwist,
aikido::statespace::dart::MetaSkeletonStateSpacePtr stateSpace,
dart::dynamics::BodyNodePtr bodyNode,
const dart::dynamics::MetaSkeletonPtr stateSpace,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to change the name to metaSkeleton.


protected:
::dart::dynamics::Joint* mJoint;
Properties mProperties;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make it const?

, mCollisionDetector(std::move(_collisionDetector))
, mCollisionOptions(std::move(_collisionOptions))
{
if (!mStatespace)
throw std::invalid_argument("_statespace is nullptr.");
if (!mMetaSkeletonStateSpace)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: check whether _metaSkeletonStateSpace and _metaskeleton are compatible.

{
if (!mMetaSkeletonStateSpace)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: check compatibility between _metaSkeletonStateSpace and _metaskeleton.

{
if (!mMetaSkeletonStateSpace)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check compatibility between statespace and metaskeleton.

@@ -13,6 +13,7 @@ namespace vectorfield {
//==============================================================================
MoveEndEffectorOffsetVectorField::MoveEndEffectorOffsetVectorField(
aikido::statespace::dart::MetaSkeletonStateSpacePtr stateSpace,
dart::dynamics::MetaSkeletonPtr metaskeleton,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check for compatibility between statespace and metaskeleton.

@@ -192,6 +195,7 @@ std::unique_ptr<aikido::trajectory::Spline> planToEndEffectorOffset(
//==============================================================================
std::unique_ptr<aikido::trajectory::Spline> planToEndEffectorPose(
const aikido::statespace::dart::MetaSkeletonStateSpacePtr& stateSpace,
dart::dynamics::MetaSkeletonPtr metaskeleton,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check for compatibility.

jslee02 and others added 2 commits January 10, 2018 09:19
* Update changelog; Move #278 to 0.3.0

* Pass DART joint as const variable to state spaces

* Use BallJoint::convertToPositions()
@brianhou
Copy link
Contributor Author

@jslee02 Merging master (with the TrajectoryMarker introduced in #288) causes the build to fail. Can you investigate? Part of the issue is because MetaSkeletonStateSpaceSaver was changed to MetaSkeletonStateSaver. Also, it seems that the MetaSkeleton within TrajectoryMarker shouldn't be const since we change it in TrajectoryMarker::updatePoints.

@brianhou brianhou merged commit 99f6866 into master Jan 11, 2018
@brianhou brianhou deleted the enhancement/brianhou/dart-statespaces branch January 11, 2018 23:09
gilwoolee pushed a commit that referenced this pull request Jan 21, 2019
* Refactor JointStateSpace to remove Joint.

This decouples the state space from the underlying DART Joint that was
used to generate the state space. Joint properties (e.g. position
limits) are maintained in a separate JointStateSpace::Properties field,
which is not tied to the original DART Joint.

This also changes the interfaces for the JointStateSpace::getState and
JointStateSpace::setState methods to take in a DART Joint.

* Rename MetaSkeletonStateSpaceSaver to MetaSkeletonStateSaver.

Since MetaSkeletonStateSpaces won't have an internal MetaSkeleton,
having a MetaSkeletonStateSpaceSaver doesn't make sense.

* Refactor MetaSkeletonStateSpace.

This decouples the state space from the underlying DART MetaSkeleton
that was used to generate the state space. Properties are maintained in
a separate MetaSkeletonStateSpace::Properties field.

This changes the interfaces for the MetaSkeletonStateSpace::getState and
MetaSkeletonStateSpace::setState methods to take in a DART MetaSkeleton.

This also changes the interfaces for many of the constraints and
executors to take in an additional DART MetaSkeleton argument.

The VectorFieldPlanner code is in a separate commit so it can be easily
reverted when the improved VectorFieldPlanner is implemented.

* Refactor VectorFieldPlanner to work with new MetaSkeletonStateSpaces.

One of the VectorFieldPlanner tests is currently failing, but I figured
it's not worth debugging since the improved VectorFieldPlanner will be
ready soon. This is in a separate commit so it can be easily reverted
when the improved implementation is ready.

* Minor formatting fixes.

* Add hash function for std::pair.

* Address Mike's review comments.

Return const & rather than const.

* Address more of Mike's review comments.

* Revert "Refactor VectorFieldPlanner to work with new MetaSkeletonStateSpaces."

This reverts commit 934ee62.

* Refactor new VectorFieldPlanner to work with new MetaSkeletonStateSpaces.

* Update CHANGELOG.md

* Pass DART objects as const to state spaces (#297)

* Update changelog; Move #278 to 0.3.0

* Pass DART joint as const variable to state spaces

* Use BallJoint::convertToPositions()

* Address Gilwoo's review comments.

* Update TrajectoryMarker per DART state space refactor

* Fix code style
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants