-
Notifications
You must be signed in to change notification settings - Fork 30
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
Ranking IK Solutions #423
Conversation
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" |
There was a problem hiding this comment.
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( |
There was a problem hiding this comment.
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" |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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.
src/distance/ConfigurationRanker.cpp
Outdated
throw std::invalid_argument("MetaSkeleton is nullptr."); | ||
|
||
mDistanceMetric = createDistanceMetricFor( | ||
std::dynamic_pointer_cast<statespace::CartesianProduct>( |
There was a problem hiding this comment.
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
?
There was a problem hiding this comment.
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.
src/distance/ConfigurationRanker.cpp
Outdated
} | ||
|
||
//============================================================================== | ||
std::vector<statespace::CartesianProduct::State*> |
There was a problem hiding this comment.
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::State
s, rather than CartesianProduct::ScopedState
s. What would happen if the input configurations are destructed before the ranking results are accessed?
JointAvoidanceConfigurationRanker::JointAvoidanceConfigurationRanker( | ||
ConstMetaSkeletonStateSpacePtr metaSkeletonStateSpace, | ||
ConstMetaSkeletonPtr metaSkeleton) | ||
: ConfigurationRanker(metaSkeletonStateSpace, metaSkeleton) |
There was a problem hiding this comment.
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
?
This looks pretty good overall! Thanks for the changes. @jslee02 would you mind looking over the |
Addressed the comments except for the |
I think it's reasonable to do something like |
I'm not sure if I can review this PR soon (hopefully late this week?). Please go ahead if this is blocked by me. 😅 |
There was a problem hiding this 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) |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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(); |
There was a problem hiding this comment.
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(); |
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 { | ||
|
There was a problem hiding this comment.
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 { | ||
|
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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 inf
s, 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);
}
There was a problem hiding this comment.
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.
Hm, for some reason, |
* 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.
This PR introduces ranker for IK solutions.
Looking for discussion on:
I prefer having them separate to make it simple and free of potential errors.
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 underplanner
.distance
WIP: Tests. I started a test for FIFO (which is more or less a random IK ranker like inprpy
).Before creating a pull request
make format
Before merging a pull request
CHANGELOG.md