-
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
SO2 to R1 conversion for postprocessing #496
Conversation
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.
Great start! I have a few questions about the implementation, mainly about whether the restriction to 1-DOF joints is necessary.
Codecov Report
@@ Coverage Diff @@
## master #496 +/- ##
==========================================
- Coverage 77.87% 77.83% -0.04%
==========================================
Files 262 262
Lines 6712 6768 +56
==========================================
+ Hits 5227 5268 +41
- Misses 1485 1500 +15
|
Co-Authored-By: aditya-vk <adityavk711@gmail.com>
Co-Authored-By: aditya-vk <adityavk711@gmail.com>
@brianhou I do not think dealing with multiple DOF joint spaces needs to be a part of this PR given that the rest of the stack, especially trajectory execution does not support it. Other comments have been addressed. |
include/aikido/trajectory/util.hpp
Outdated
/// Converts an interpolated trajectory in the cartesian product space of SO(2) | ||
/// and R1 joints | ||
/// to a trajectory in cartesian product space of strictly only R1 joints. | ||
/// \param[in] space Statespace the input trajectory is in. |
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.
Delete this line.
include/aikido/trajectory/util.hpp
Outdated
@@ -89,6 +89,26 @@ double findTimeOfClosestStateOnTrajectory( | |||
UniqueSplinePtr createPartialTrajectory( | |||
const Spline& traj, double partialStartTime); | |||
|
|||
/// Converts an interpolated trajectory in the cartesian product space of SO(2) | |||
/// and R1 joints |
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 is wrapped weirdly, and things aren't capitalized correctly.
include/aikido/trajectory/util.hpp
Outdated
/// \param[in] trajectory Trajectory to be converted. | ||
/// \return Converted trajectory. | ||
aikido::trajectory::ConstInterpolatedPtr toR1JointTrajectory( | ||
// aikido::statespace::ConstStateSpacePtr& space, |
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.
Delete this line.
include/aikido/trajectory/util.hpp
Outdated
/// Converts a spline trajectory in the cartesian product space of SO(2) and R1 | ||
/// joints | ||
/// to a trajectory in cartesian product space of strictly only R1 joints. | ||
/// \param[in] space Statespace the input trajectory is in. |
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.
Delete this line.
include/aikido/trajectory/util.hpp
Outdated
/// \param[in] trajectory Trajectory to be converted. | ||
/// \return Converted trajectory. | ||
aikido::trajectory::ConstSplinePtr toR1JointTrajectory( | ||
// aikido::statespace::ConstStateSpacePtr& space, |
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.
Delete this line.
src/control/ros/Conversions.cpp
Outdated
space->logMap(state, tangentVector); | ||
space->convertStateToPositions(state, tangentVector); | ||
|
||
auto geodesicInterpolator = std::dynamic_pointer_cast<aikido::statespace::GeodesicInterpolator>(interpolator); |
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 don't we take in a GeodesicInterpolator
, rather than always dynamic casting it here?
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.
- Consistency: Seems to be the norm to pass in the base class and then cast it to the appropriate one.
- Flexibility: In case we introduce new interpolator classes and want to use the one that's tied to the trajectory.
I don't have a strong preference, but I'd be inclined to go this route.
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, can we replace this with methods that are defined in the Interpolator
class?
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.
See below.
Co-Authored-By: aditya-vk <adityavk711@gmail.com>
src/trajectory/util.cpp
Outdated
NonSingularDOF | ||
}; | ||
|
||
bool checkStateSpace(const statespace::StateSpace* _stateSpace, AllowJointType type) |
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.
There are a couple of tests written (planner / trajectory namespaces for example) that instantiate an R2 statespace and use this function during the process. I agree that we should not have two functions doing the same here. This seems to be a reasonable solution for now, especially given we currently have support for multi-DOF joints some places and not others. I would like to have this solution in place with an issue raised to
- Change the tests to be cartesian product spaces with multiple R1 joints.
or - Extend support for multi-DOF joint spaces uniformly and remove this enum usage.
Since this method is internal, I am okay with using an enum at this point but would liek to get rid of it soon. What do you guys think?
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 would prefer to remove the enum and just use a Cartesian product space of multiple R1 joints in these tests, as part of this PR. Then, we can revisit the multi-DOF joint space if/when it becomes useful in the future.
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 agree with Brian. Can we have an issue to track this in case it becomes necessary?
src/control/ros/Conversions.cpp
Outdated
"The interpolator of trajectory should be a GeodesicInterpolator"); | ||
} | ||
|
||
auto diff = geodesicInterpolator->getTangentVector(prevState, 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.
I'm not entirely sure I understand why this change is necessary. So far, my understanding of this PR is:
- We plan with SO(2) joints
- We convert SO(2) joints to R1, postprocess (because postprocessors only deal with Rn joints), then convert back to SO(2)
What are we trying to do in this function? Is it what I thought was happening in #496 (comment), i.e. basically converting this into an Rn-joint trajectory to send out via ROS?
My main qualm is that it feels wrong to be requiring a specific type of interpolator here. I'm wondering whether we can rewrite this without using GeodesicInterpolator
-specific methods, perhaps by actually converting it to an Rn trajectory and then just using logMap
?
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.
To my understanding, we are committing to executing the shortest paths i.e. interpolating via the Geodesic anytime we execute a trajectory.
What are we trying to do in this function?
We want to extract waypoints along the trajectory "ensuring that the interpolation happens along the geodesic so that SO2 joint space is handled appropriately".
What is the PR doing?
- We plan with SO2 joints
- We convert SO2 joints to R1 and time it -> this generates a spline that has been timed appropriately.
- When converting to ROS trajectory, each waypoint from this spline is extracted using the trajectory's statespace which is SO2 and hence requiring us to use the previous point to be able to interpolate appropriately, and then use the converted extracted waypoint to construct the ROS trajectory.
Conversion into Rn-joint trajectory and then using logMap would also involve the geodesic interpolator so I am not sure how that would help.
- The issue is that the base Interpolator class does not have a
getTangentVector()
and I don't see why it shouldn't since every derived class would need to support that. So I can alternatively add a virtual function there and if we take the interpolator by reference or obtain it from the trajectory, it should point to the right implementation? - But the problem is we need to be able to support both Interpolated trajectories and Splines. Spline trajectories do not have an interpolator attached to them so we need to use something.
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.
@aditya-vk I didn't fully get the 3rd bullet point. trajectory
is already in MetaSkeletonStateSpace
so it's a Cartesian product of SO2. In SO2 spline trajectory, why do we need the previous point to interpolate appropriately?
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.
Yes exactly. It is in the Cartesian Product of SO2, call it space
. So when we evaluate the trajectory, space
is used to retrieve the state (=space->createState())
. Although the spline polynomial is correct, when we retrieve it using space
, the representation for SO2 joints is converted back to between -pi
and pi
.
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 leaves two options: Either have your trajectory be tied with CartesianProduct
space of all R1
joints which can again get messy since we check for MetaSkeletonStateSpace
during execution or use the interpolation from the previous point.
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 was wondering if we could return evaluatePolynomial()
instead of evaluate()
since that returns the value of the polynomial which is what we desire. However, again, since the spline segments are solved from 0, we need to know the start state of the segment which is stores in mSegments.startState
and that is represented as R + SO2. So this route is pretty much useless as well.
After discussing with @aditya-vk, it seems that somewhere lower down in the stack would be a better place to convert to R1 trajectories (when necessary). I think this would make for a cleaner abstraction, since we'd be able to reason with the SO(2) joints all the way from planning until we send it off to the controller. I've created personalrobotics/rewd_controllers#30 to track this, let's clean up this PR to remove the conversion here. |
The timers assume that the path representation is in R1. When the joints in the skeleton are SO2, we would like them to move along the geodesic and not the other way around. To ensure this happens, we need to appropriately convert the path representation to R1 along the geodesic. THis PR handles this conversion.
Before creating a pull request
make format
Before merging a pull request
CHANGELOG.md