-
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 methods for caching and retrieving trajectories #541
Conversation
* Status: Working; Tested with simple_trajectories
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.
Thanks for the great start! I have a few thoughts and questions:
- I think the trajectory loading should be in
aikido::io
rather thanaikido::trajectory
. Would there be some weird dependencies, or does that make sense? - Rather than manually writing out the information in YAML format, can we take advantage of the YAML emitter for these sequences? In particular, I think
aikido/io/detail/yaml_extension.hpp
has some stuff for Eigen vectors that might be nice to use, so we don't have to specify anEigen::IOFormat
here.
Thoughts about the format:
- I think
dofs
should refer to a list of DOF names (and doesn't need to just be a sequence). This might allow us to animate other objects in the future by specifying those joints. - I think some of this information might be redundant, e.g.
num_segments
might be obvious from the number of segments. - I'm not sure whether we need specific names for each segment; maybe we can just put them in a sequence and handle that implicitly?
- Maybe it makes sense to organize the YAML information into two maps, similar to OpenRave.
So all together, maybe it could look something like this:
configuration:
start_time: 0
dofs: ["/right/j1", "/right/j2", ...]
type: spline
spline:
order: 3
data:
- coefficients: [1, 2, ...]
duration: 0.1875
start_state: [3, 4, ...]
- coefficients: [5, 6, ...]
duration: 0.1875
start_state: [7, 8, ...]
src/trajectory/util.cpp
Outdated
{ | ||
auto segment_id = "seg_" + std::to_string(i); | ||
Eigen::MatrixXd coeffVec | ||
= trajFile[segment_id]["coefficients"].as<Eigen::MatrixXd>(); |
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 MatrixXd
rather than VectorXd
? It seems to just be a vector in the yaml file?
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.
No particular reason, while implementing I may have associated MatrixXd
with all coefficient related variables I used. But yes, having this as VectorXd
definitely makes more sense.
The format that you've suggested actually looks great and is more clearer. Would the entries under |
It seems that So, I think I'm still inclined to put this with other deserialization code (for raw YAML, kinbody, URDF formats) in I think after yaml-cpp parses the sequence for you, you should be able to then query for the size of that sequence just like any other C++ container :) |
include/aikido/io/trajectory.hpp
Outdated
/// \param[in] skelSpace Metaskeleton of the object | ||
/// \param[in] savePath save path for the trajectory yaml file | ||
void saveTrajectory(const aikido::trajectory::Spline& trajectory, | ||
const aikido::statespace::dart::MetaSkeletonStateSpacePtr& skelSpace, |
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 this parameter necessary? I think it should be read from the trajectory.
include/aikido/io/trajectory.hpp
Outdated
namespace aikido { | ||
namespace io { | ||
|
||
/// Saves a timed 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.
I don't think we need this full summary. I'd just rephrase as "Serializes a spline trajectory to YAML." before listing the parameters.
include/aikido/io/trajectory.hpp
Outdated
const aikido::statespace::dart::MetaSkeletonStateSpacePtr& skelSpace, | ||
const std::string& savePath); | ||
|
||
/// Load spline trajectory from yaml file |
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.
Similarly, I'd just say that this "Deserializes a spline trajectory from YAML.".
src/io/trajectory.cpp
Outdated
namespace io { | ||
|
||
void saveTrajectory(const aikido::trajectory::Spline& trajectory, | ||
const MetaSkeletonStateSpacePtr& skelSpace, const std::string& savePath) |
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.
As above, I think you should be able to just pull the statespace from the trajectory. I would just try to cast it to a MetaSkeletonStateSpace
to get the properties you need.
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.
If you do the above, I suggest using MetaSkeletonStateSpace
specific functions to make the log/exp conversions.
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 Is there any particular reason for that? Because I think using MetaSkeletonStateSpace specific function would first require type-casting the state that we pass to these functions.
src/io/trajectory.cpp
Outdated
= ::aikido::common::make_unique<Spline>(stateSpace, startTime); | ||
|
||
const YAML::Node& segments = trajFile["data"]; | ||
for (std::size_t i = 0; i < segments.size(); 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.
The open brace should be on the next line.
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 iterate directly over segments
rather than by index?
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 I guess we can use an iterator (with for
loop) over the YAML node. Would that 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.
Yep!
src/io/trajectory.cpp
Outdated
Eigen::VectorXd position = segment["start_state"].as<Eigen::VectorXd>(); | ||
|
||
// Convert position Eigen vector to StateSpace::State* | ||
aikido::statespace::StateSpace::State* startState |
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 is this correct usage? Do we need to free the 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.
Definitely. Needs a freeState()
at the end of the function.
src/io/trajectory.cpp
Outdated
|
||
statespace::ConstStateSpacePtr trajSpace = trajectory.getStateSpace(); | ||
emitter << YAML::BeginMap; | ||
emitter << YAML::Key << "configuration" << YAML::BeginMap; |
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.
Put the YAML::BeginMap
on a new line?
src/io/trajectory.cpp
Outdated
emitter << YAML::BeginMap; | ||
emitter << YAML::Key << "order" << YAML::Value << trajectory.getNumDerivatives(); | ||
emitter << YAML::EndMap; | ||
emitter << YAML::EndMap << YAML::Key << "data" << YAML::BeginSeq; |
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.
Put the YAML::Key << "data" << YAML::BeginSeq
on two more lines? I'd also move this right before the for loop.
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.
Looks good! Requested some changes.
include/aikido/io/trajectory.hpp
Outdated
/// Given trajectory file and trajectory state space, this method parses | ||
/// the trajectory file and loads a timed trajectory for direct execution. | ||
/// \param[in] trajPath Spline trajectory | ||
/// \param[in] stateSpace Metaskeleton for the 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.
If we expect the stateSpace to be associated with a MetaSkeleton, I would rename it to metaSkeletonStateSpace
. Additionally, MetaSkeleton
-> MetaSkeletonStateSpace
.
include/aikido/io/trajectory.hpp
Outdated
} // namespace io | ||
} // namespace aikido | ||
|
||
#endif // AIKIDO_IO_TRAJECTORY_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.
Add EOF line.
src/io/trajectory.cpp
Outdated
namespace io { | ||
|
||
void saveTrajectory(const aikido::trajectory::Spline& trajectory, | ||
const MetaSkeletonStateSpacePtr& skelSpace, const std::string& savePath) |
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.
If you do the above, I suggest using MetaSkeletonStateSpace
specific functions to make the log/exp conversions.
src/io/trajectory.cpp
Outdated
Eigen::VectorXd position = segment["start_state"].as<Eigen::VectorXd>(); | ||
|
||
// Convert position Eigen vector to StateSpace::State* | ||
aikido::statespace::StateSpace::State* startState |
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.
Definitely. Needs a freeState()
at the end of the function.
Use iterators over YAML segment sequences Compare dof names and spline type for deserialized trajectory
d741c4c
to
372ad2a
Compare
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.
Looks really close! Just a few minor nits to go.
aefbc97
to
36b6f86
Compare
I think this is ready for the final review! I haven't run |
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.
One last minor nit, then I think we're good to merge!
This PR addresses #534 and adds methods to save and load a spline trajectory using YAML file. The methods are implemented as utility functions under
src/trajectory
.This is an example of how a saved trajectory file looks like:
I have added a unit test to check trajectory loaded from a saved YAML file has the same member variables as that of the original trajectory. Additionally, as a sanity check, also tested the methods with herb3_demos/simple_trajectories by loading saved trajectories for execution and visualization it in RViz.
Before creating a pull request
make format
Before merging a pull request
CHANGELOG.md