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

Ranking IK Solutions #423

Merged
merged 100 commits into from
Jul 17, 2018
Merged

Ranking IK Solutions #423

merged 100 commits into from
Jul 17, 2018

Conversation

aditya-vk
Copy link
Contributor

@aditya-vk aditya-vk commented May 15, 2018

This PR introduces ranker for IK solutions.

Looking for discussion on:

  1. Should we make it more general to also be able to rank TSRs with the same (templated) classes?
    I prefer having them separate to make it simple and free of potential errors.
  • Decided to keep them separate
  1. Where do we have the files? It seemed constraint/dart/ might be a good place since it's still a constraint over the IKs which by itself is a constraint. Can also be under planner.
  • Decided to have them under distance
  1. Naming convention for the classes.
  2. Efficiency and implementation details.

WIP: Tests. I started a test for FIFO (which is more or less a random IK ranker like in prpy).


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

@aditya-vk aditya-vk removed the pr: work-in-progress Calls for preliminary review of the PR. Remove when PR is ready for complete review. label Jul 8, 2018
@aditya-vk
Copy link
Contributor Author

Cleaned up! Should be good to go (I think). Will follow up with updates to planToTSR methods once this gets merged :)

The tests are failing for reasons that don't have to do with the code itself.

#ifndef AIKIDO_DISTANCE_CONFIGURATIONRANKER_HPP_
#define AIKIDO_DISTANCE_CONFIGURATIONRANKER_HPP_

#include "aikido/distance/CartesianProductWeighted.hpp"
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: is this include necessary?


/// Returns a vector of configurations ranked in increasing order of costs.
/// \param[in] configurations Vector of configurations to rank.
std::vector<statespace::CartesianProduct::State*> rankConfigurations(
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's change this from CartesianProduct::State to MetaSkeletonStateSpace::State, etc.

#include "aikido/distance/CartesianProductWeighted.hpp"
#include "aikido/distance/DistanceMetric.hpp"
#include "aikido/distance/defaults.hpp"
#include "aikido/statespace/CartesianProduct.hpp"
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this is also unnecessary.

virtual ~ConfigurationRanker() = default;

/// Returns the statespace.
statespace::ConstStateSpacePtr getStateSpace() const;
Copy link
Contributor

Choose a reason for hiding this comment

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

This method doesn't seem to be used. I'd prefer to remove it if we don't see a use for it, but I think this should return a ConstMetaSkeletonStateSpacePtr if we decide to keep it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll remove it for now.

///
/// \param[in] metaSkeletonStateSpace Statespace of the skeleton.
/// \param[in] metaskeleton Metaskeleton of the robot.
/// \param[in] nominalConfiguration Nominal Configuration. The current
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: Nominal Configuration -> Nominal configuration.

Can we also provide a nullptr default?

/// specified DART \c MetaSkeleton positions.
///
/// \param[in] positions DART \c MetaSkeleton positions
ScopedState getStateFromPositions(Eigen::VectorXd& positions) const;
Copy link
Contributor

Choose a reason for hiding this comment

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

In that case, let's add it as a separate/future PR instead so this one is just about the IK rankers.

throw std::invalid_argument("MetaSkeleton is nullptr.");

mDistanceMetric = createDistanceMetricFor(
std::dynamic_pointer_cast<statespace::CartesianProduct>(
Copy link
Contributor

Choose a reason for hiding this comment

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

Are both of these casts necessary? Does createDistanceMetricFor not work for const statespace::CartesianProduct?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The const-cast should not be necessary.

}

//==============================================================================
std::vector<statespace::CartesianProduct::State*>
Copy link
Contributor

Choose a reason for hiding this comment

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

It seems that we're returning raw pointers to the CartesianProduct::States, rather than CartesianProduct::ScopedStates. What would happen if the input configurations are destructed before the ranking results are accessed?

JointAvoidanceConfigurationRanker::JointAvoidanceConfigurationRanker(
ConstMetaSkeletonStateSpacePtr metaSkeletonStateSpace,
ConstMetaSkeletonPtr metaSkeleton)
: ConfigurationRanker(metaSkeletonStateSpace, metaSkeleton)
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this std::move the MetaSkeletonStateSpace and MetaSkeleton?

@brianhou
Copy link
Contributor

This looks pretty good overall! Thanks for the changes.

@jslee02 would you mind looking over the State stuff to make sure we're using them correctly? Thanks!

@aditya-vk
Copy link
Contributor Author

Addressed the comments except for the State-handling. I'll wait for @jslee02 before modifications. I assumed that the way we'd be using the ranker we wouldn't be destroying the input states but that's a possibility in any case that needs taken care of.

@brianhou
Copy link
Contributor

I think it's reasonable to do something like return ranker.rankConfigurations(states);, which I think would lose the states.

@jslee02
Copy link
Member

jslee02 commented Jul 11, 2018

I'm not sure if I can review this PR soon (hopefully late this week?). Please go ahead if this is blocked by me. 😅

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.

The build failures on macOS is fixed by Homebrew/homebrew-core#29620.

If I don't forget the AIKIDO's state spate mechanism by the last three weeks, classes should hold states as scoped states unless the lifetime is guaranteed to be longer than the lifetime of the state holder, which I don't think that's the case in this PR.

Caveat: I reviewed this PR quickly so it could include incorrect comments.


static constexpr double EPS = 1e-6;

static BodyNode::Properties create_BodyNodeProperties(const std::string& _name)
Copy link
Member

Choose a reason for hiding this comment

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

Nit: No more leading underscore in parameter name!


//==============================================================================
double NominalConfigurationRanker::evaluateConfiguration(
statespace::dart::MetaSkeletonStateSpace::State* solution) const
Copy link
Member

Choose a reason for hiding this comment

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

Why solution is not const?

namespace distance {

using statespace::dart::ConstMetaSkeletonStateSpacePtr;
using statespace::CartesianProduct;
Copy link
Member

Choose a reason for hiding this comment

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

Nit: This type alias isn't used


//==============================================================================
double JointAvoidanceConfigurationRanker::evaluateConfiguration(
statespace::dart::MetaSkeletonStateSpace::State* solution) const
Copy link
Member

Choose a reason for hiding this comment

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

Maybe const?

std::move(metaSkeletonStateSpace), std::move(metaSkeleton))
{
auto lowerLimits = mMetaSkeleton->getPositionLowerLimits();
auto upperLimits = mMetaSkeleton->getPositionUpperLimits();
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& since getPosition(Lower/Upper)Limits() returns const reference.

}

mLowerLimitsState = mMetaSkeletonStateSpace->createState();
mUpperLimitsState = mMetaSkeletonStateSpace->createState();
Copy link
Member

Choose a reason for hiding this comment

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

mUpperLimitsState should be scoped state. Otherwise it will be destructed out of this function, and mUpperLimitsState will become dangling pointer.

/// Destructor
virtual ~ConfigurationRanker() = default;

/// Ranks/Sorts the vector of configurations in increasing order of costs.
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: I think sorts is redundant here?

virtual ~ConfigurationRanker() = default;

/// Ranks/Sorts the vector of configurations in increasing order of costs.
/// \param[in] configurations Vector of configurations to rank.
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: I believe the Doxygen convention for this is \param[in,out].

std::vector<std::size_t> mUnboundedUpperLimitsIndices;

/// (Modified) State corresponding to the lower position limits.
/// The positions at the indices in mUnboundedLowerLimitsIndices are modified
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we can change the descriptions for both lower/upper to clarify that the states are modified by evaluateConfiguration to match the input state before computing the distance from the lower limits.


namespace aikido {
namespace distance {

Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: document ConfigurationRanker.


namespace aikido {
namespace distance {

Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: document JointAvoidanceConfigurationRanker.

I think we should mention here that only joints with limits contribute to the distance to the lower/upper limits.

/// \param[in] metaSkeletonStateSpace Statespace of the skeleton.
/// \param[in] metaskeleton Metaskeleton of the robot.
/// \param[in] nominalConfiguration Nominal configuration. The current
/// configuration is considered if set to nullptr.
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: clarify that it's the current configuration of the metaSkeleton.

/// Constructor
///
/// \param[in] metaSkeletonStateSpace Statespace of the skeleton.
/// \param[in] metaskeleton Metaskeleton of the robot.
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: metaskeleton -> metaSkeleton.

/// Constructor
///
/// \param[in] metaSkeletonStateSpace Statespace of the skeleton.
/// \param[in] metaskeleton Metaskeleton of the robot.
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: metaskeleton -> metaSkeleton.

/// Constructor
///
/// \param[in] metaSkeletonStateSpace Statespace of the skeleton.
/// \param[in] metaskeleton Metaskeleton of the robot.
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: metaskeleton -> metaSkeleton.

auto lowerLimits = mMetaSkeleton->getPositionLowerLimits();
auto upperLimits = mMetaSkeleton->getPositionUpperLimits();

for (std::size_t i = 0; i < mMetaSkeletonStateSpace->getDimension(); ++i)
Copy link
Contributor

Choose a reason for hiding this comment

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

Quick question: is there ever a case where there are lower limits but not upper limits (or vice versa)? If not, then rather than checking against infs, maybe we can use DegreeOfFreedom::hasPositionLimit. I think it'd look something like this:

auto properties = mMetaSkeletonStateSpace->getProperties();
for (std::size_t i = 0; i < properties.getNumDofs(); ++i)
{
  if (mMetaSkeleton->getDof(i)->hasPositionLimit())
    mUnboundedIndices.emplace_back(i);
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I wanted to have it to be general just in case. Looks like dart is checking both upper and lower limits separately when performing that check implying no such assumption is being made if I understand correctly.

brianhou
brianhou previously approved these changes Jul 17, 2018
@jslee02
Copy link
Member

jslee02 commented Jul 17, 2018

Hm, for some reason, test_NominalConfigurationRanker fails on macOS.

@brianhou brianhou merged commit cfba2f6 into master Jul 17, 2018
@brianhou brianhou deleted the ranker branch July 17, 2018 14:34
gilwoolee pushed a commit that referenced this pull request Jan 21, 2019
* init

* Fixing const-correctness in state space

* update structure

* make format

* source for base ranking class

* make format

* add general sorting

* make format

* preallocate size of ranking vector

* nit todo removed

* remove unnecessary headers + new strategies

* make format

* remove redundant virtual keyword

* add FIFO to ranking strategy

* add source scripts for ranking strategies

* assign the base class members first

* make format

* add sources to read later

* correct macro for header-guard

* tests for FIFO + cleanup

* Fixing const-correctness of StateHandle

* Fix implicit conversion of StateHandle to State*

* Undo unnecessary changes

* Remove incorrect comment

* Add clone to StateSpace

* Format code

* test for the bug

* bug fix in adding IK solutions

* comment out unused variables

* nit comments

* Update changelog

* Update CHANGELOG.md

* WIP: Random restructuring to test stuff

* change API

* make format

* nominal configuration strategy

* test for nominal configuration strategy

* restructure the code into distance

* enable base class and nominal configuration ranker

* bring back test for nominal config ranker + check distances

* simplify the test script

* bring bakc joint avoidance ranker

* simplify the code

* make format

* clean up test scripts

* joint avoidance strategy

* consider cyclic joints

* make format

* make tests uniform

* update log

* simplify and address PR comments

* modify joint avoidance. TODO: change to indices of unbounded limits?

* modify constructor to take nominal configuration as parameter

* make format

* add docstring

* work with indices

* make format

* convenience function to get state without creating it explicitly

* simplify code

* make format

* update log

* edit docstrings

* use cartesianproduct state space

* add docstrings

* create limits states in ctr; use cartesian sspace.

* make format

* move helper function to anonymous namespace

* rename variables and functions for increased clarity

* make format

* simplify tests scripts

* remove unnecessary clone

* make format

* take in scoped states as expected during planning

* make format

* remove function outside scope of the PR

* remove getter for statespace; use MetaSkeletonStateSpace

* remove const-cast

* make format

* address concerns over state; cleanup

* remove unnecessary header

* remove unnecesary header

* make ranking efficient; address nit comments

* make format

* Refactor and fix weird bug.
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.

3 participants