-
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
Add ParabolicTiming for linear spline #302
Add ParabolicTiming for linear spline #302
Conversation
Codecov Report
@@ Coverage Diff @@
## master #302 +/- ##
=========================================
- Coverage 81.14% 81.1% -0.04%
=========================================
Files 204 204
Lines 5891 5913 +22
=========================================
+ Hits 4780 4796 +16
- Misses 1111 1117 +6
|
CHANGELOG.md
Outdated
@@ -30,6 +30,7 @@ | |||
|
|||
* Added World class: [#243](https://github.com/personalrobotics/aikido/pull/243), [#252](https://github.com/personalrobotics/aikido/pull/252), [#265](https://github.com/personalrobotics/aikido/pull/265) | |||
* Added vector field planner [#246](https://github.com/personalrobotics/aikido/pull/246), [#262](https://github.com/personalrobotics/aikido/pull/262), [#268](https://github.com/personalrobotics/aikido/pull/268) | |||
* Added parabolic timing for linear spline [#302](https://github.com/personalrobotics/aikido/pull/302) |
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.
Please move this to 0.3.0.
_inputTrajectory, _maxVelocity, _maxAcceleration, true); | ||
|
||
auto outputTrajectory | ||
= detail::convertToSpline(*dynamicPath, startTime, stateSpace); |
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.
Is dynamicPath
always not nullptr
? If so, please throw an exception if dynamicPath
is nullptr
.
Otherwise, return nullptr
as output trajectory if dynamicPath
is 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.
The current implementation of convertToDynamicPath
guarantees that dynamicPath
will never be nullptr
.
Do you think we shall add the check in case any potential change will happen in the future?
throw std::invalid_argument("Velocity limits must be finite."); | ||
|
||
if (_maxAcceleration[i] <= 0.) | ||
throw std::invalid_argument("Acceleration limits must be positive."); |
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.
Shouldn't be fine to allow zero velocity/acceleration limits? Could you explain for me why nonnegative limits aren't enough? 😅
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 following the code of computeParabolicTiming
for an Interpolated
.
I think the reason is that if the velocity/acceleration limit of one dimension is zero, it should not be considered in timing a trajectory.
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 a lot of duplicated code in convertToDynamicPath
and computeParabolicTiming
:
computeParabolicTiming
is identical except for passing a flag toconvertToDynamicPath
to decide whether velocities should be preserved (which is currently supported only forSpline
, notInterpolated
, and is always set to ignore the velocities)convertToDynamicPath
is identical except for (1) how waypoints are extracted from each trajectory type, (2) evaluatingSpline
derivatives to (potentially) preserve them in theDynamicPath
, and (3) the flag mentioned above
It seems to me that this redundancy is mostly because we don't have a unified interface for getting waypoints from a trajectory (e.g. getNumWaypoints()
, getWaypoint(i)
, getWaypointTime(i)
) for convertToDynamicPath
. I'm not sure whether the best way to add this is to add a WaypointTrajectory
in the class hierarchy between Trajectory
and Interpolated
/Spline
, or to add those methods directly to the Trajectory
class. Either way, the resulting code for both types of trajectories could look something like this:
std::unique_ptr<ParabolicRamp::DynamicPath> convertToDynamicPath(
const aikido::trajectory::WaypointTrajectory& _inputTrajectory,
const Eigen::VectorXd& _maxVelocity,
const Eigen::VectorXd& _maxAcceleration,
bool preserveWaypointVelocities)
{
const auto stateSpace = _inputTrajectory.getStateSpace();
const auto numWaypoints = _inputTrajectory.getNumWaypoints();
std::vector<ParabolicRamp::Vector> milestones;
std::vector<ParabolicRamp::Vector> velocities;
Eigen::VectorXd tangentVector, currVec;
for (std::size_t iwaypoint = 0; iwaypoint < numWaypoints; ++iwaypoint)
{
auto currentState = stateSpace->createState();
double t = _inputTrajectory.getWaypointTime(iwaypoint);
_inputTrajectory.evaluate(t, currentState);
stateSpace->logMap(currentState, currVec);
milestones.emplace_back(toVector(currVec));
if (preserveWaypointVelocities)
{
_inputTrajectory.evaluateDerivative(t, 1, tangentVector);
velocities.emplace_back(toVector(tangentVector));
}
}
auto outputPath = make_unique<ParabolicRamp::DynamicPath>();
outputPath->Init(toVector(_maxVelocity), toVector(_maxAcceleration));
if (preserveWaypointVelocities)
outputPath->SetMilestones(milestones, velocities)
else
outputPath->SetMilestones(milestones)
if (!outputPath->IsValid())
throw std::runtime_error("Converted DynamicPath is not valid");
return outputPath;
}
Does this change sound valuable, and would it make sense to add this interface to Trajectory
or a different class?
@@ -60,7 +60,8 @@ std::unique_ptr<aikido::trajectory::Spline> convertToSpline( | |||
std::unique_ptr<ParabolicRamp::DynamicPath> | |||
convertToDynamicPath(const aikido::trajectory::Spline& _inputTrajectory, | |||
const Eigen::VectorXd& _maxVelocity, | |||
const Eigen::VectorXd& _maxAcceleration); | |||
const Eigen::VectorXd& _maxAcceleration, | |||
bool untimed = false); |
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.
Can we rename untimed
to timed
and flip the default values? Or maybe a more informative name, like preserveWaypointVelocity
, would be better?
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 general, I am a fan of boolean flags to indicate input properties including an is
or has
prefix to help indicate their intent e.g. isTimed
. But that's neither here nor there.
@brianhou I agree with your suggestion on introducing a There is an alternative approach in conversion. |
Magi requires that we have post processors support both Interpolated and Spline trajectories. This is a small PR that makes the parabolic post processor classes support the new methods added in #302.
* add timing for spline trajectories * fix code style * add test case * add docstring * update change log * fix CHANGELOG * address Brian's comments * fix bug
Magi requires that we have post processors support both Interpolated and Spline trajectories. This is a small PR that makes the parabolic post processor classes support the new methods added in #302.
This pull request adds
computeParabolicTime
for linear spline trajectory.Document new methods and classes
Format code with
make format
Set version target by selecting a milestone on the right side
Summarize this change in
CHANGELOG.md
Add unit test(s) for this change