-
Notifications
You must be signed in to change notification settings - Fork 11
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鈥檒l occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added DCMTrajectory generator and FeetMinimumJerkGenerator #17
Conversation
The code has been copied from the dcmTrajectoryGenerator branch and refactored to comply with the new structure of the planner.
std::lock_guard<std::mutex> guard(m_pimpl->mutex); | ||
|
||
if (m_pimpl->feetMinimumJerkGenerator == nullptr) { | ||
m_pimpl->feetMinimumJerkGenerator.reset(new FeetMinimumJerkGenerator()); |
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.
Instead of using
m_pimpl->feetMinimumJerkGenerator.reset(new FeetMinimumJerkGenerator());
You may use
m_pimpl->feetMinimumJerkGenerator = std::make_shared<FeetMinimumJerkGenerator>();
Here and here you can find some reasons why this is in general better. In simple terms it just a matter of heap-allocation. Using std::make_shared
only one heap-allocation is performed while, on the other hand, new FeetMinimumJerkGenerator()
invokes a heap-allocation for the managed data and the .reset( )
method performs another one.
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.
Unfortunately it is not possible. The constructors are private
and can be allocated only because UnicyleGenerator
is a friend
. As a consequence std::make_shared
fails is allocating those objects, while with new
we circumvent this issue.
Feet twists are also an output of the cubic spline generator. Some bugfix: - the linear velocity in the minimum jerk generator was not set - ignoring other QTCreator files
Together with robotology/walking-controllers#23, I tested this PR in simulation and on the real robot. It seems to be working fine. @GiulioRomualdi if you could please take a look at the code if it is reasonable and/or perform other tests. Then we could merge. |
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.
Only some minor comments
CMakeLists.txt
Outdated
@@ -28,7 +28,7 @@ include(CMakePackageConfigHelpers) | |||
|
|||
project(UnicyclePlanner | |||
LANGUAGES CXX | |||
VERSION 0.1.100) | |||
VERSION 0.1.200) |
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.
Just a curiosity, how are we handing the versioning of the code?
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 what are you interested in? The numbering system or how this is used inside CMake?
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.
Actually it is better 102
for the patch version.
@@ -157,10 +170,10 @@ class UnicycleGenerator::UnicycleGeneratorImplementation { | |||
//bool pause = m_pauseActive && (switchTime > m_maxSwitchTime); //if true, it will pause in the middle | |||
size_t mergePoint; | |||
if (pause){ | |||
mergePoint = phaseShift.back() - static_cast<size_t>(std::round(nominalSwitchTime/(2*dT))); | |||
mergePoint = phaseShift.back() - static_cast<size_t>(std::round(nominalSwitchTime * (1 - mergePointRatio)/(dT))); |
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 did you change the way to evaluate the new mergePoint
during the pause condition?
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.
} | ||
output[instant] = newTransform; | ||
iDynTree::toEigen(rightTrivializedAngVelocity) = iDynTree::toEigen(iDynTree::Rotation::RPYRightTrivializedDerivative(0.0, pitchAngle, yawAngle)) * | ||
iDynTree::toEigen(rpyDerivative); |
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've found an elegant way to evaluate the minimum jerk trajectory in SE(3). Here (page 162) you can find further details. Using this approach we can avoid to evaluate the minimum jerk trajectory for RPY and then compose the rotation matrix. Also because I'm not sure that the two approaches (minJerk(RPY) -> rotationMatrix
and directly (minJerk(rotationMatrix)
) return the same results. @DanielePucci
By the way, for the time being the approach that we are using is fine.
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.
Feel free to open a PR for this 馃槈
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.
Here (page 162) you can find further details.
I met that guy at a conference. By far the best walking I ever saw on a small humanoid (in his case it was the Nao), really impressive.
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.
You can find his code at https://github.com/mrsp/serow .
|
||
|
||
bool interpolateFoot(double dT, const std::vector<size_t>& phaseShift, const std::vector<StepPhase> &stepPhase, | ||
const FootPrint &foot, std::vector<iDynTree::Transform> &output, std::vector<iDynTree::Twist> &outputTwistsInMixedRepresentation) { |
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 would be nice to have also the acceleration of the feet, indeed it may be useful for the torque control. I know that it's not easy to retrieve but we should discuss some possible solutions.
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.
What is missing is the relation between the RPY double derivative and the angular acceleration. From the outside it is not clear that inside the RPY parametrization is used, thus I would avoid to output the RPY double derivative instead of the actual acceleration. We may address this in a separate PR.
src/UnicycleGenerator.cpp
Outdated
} | ||
return true; | ||
} | ||
|
||
bool createPhasesTimings(const FootPrint &leftFootPrint, const FootPrint &rightFootPrint) { | ||
bool createPhasesTimings(const FootPrint &lFootPrint, const FootPrint &rFootPrint) { | ||
//NOTE this method must be called after orderSteps to work properly | ||
|
||
lFootPhases.reset(new std::vector<StepPhase>()); |
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 know that this part was already here, however, I want to ask you two things:
lFootPhases
is an attribute of the class. Why is it not likem_lFootPhases
? This is general for all the attribute ofUnicycleGenerator::UnicycleGeneratorImplementation
class. Is this related to the fact that all these attributes are public?- probabily here you can use
std::make_shared<>()
instead of.reset(new )
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.
Regarding 1. I usually use the m_*
convention only for private members. Since it is an implementation class, all the parameters are public, so that they can be accessed as m_pimpl->parameter
instead of m_pimpl->m_parameter
. A grey area is when you have methods in the implementation class which use the public parameters. I agree that readability degrades a bit, but I prefer to stick to the initial decision.
Regarding 2., you are right I am going to change 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.
Done 2. in 5332a08.
@@ -641,4 +694,15 @@ std::shared_ptr<CoMHeightTrajectoryGenerator> UnicycleGenerator::addCoMHeightTra | |||
return m_pimpl->comHeightGenerator; | |||
} | |||
|
|||
std::shared_ptr<DCMTrajectoryGenerator> UnicycleGenerator::addDCMTrajectoryGenerator() |
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 far as I know one returns a shared_ptr
if one wants to have the ownership attached to the pointer, but I think that here the ownership should belong only to the UnicycleGenerator
object. So I suggest to make m_pimpl->dcmTrajectoryGenerator
an unique_ptr
and return the raw pointer m_pimpl->dcmTrajectoryGenerator.get()
What do you 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 prefer not to return the raw pointer, otherwise the user class will have to check the existence of that generator every time it tries to access it. In the way you propose, all the generators would be deleted as soon as the UnicycleGenerator
will go out of scope. Instead, by using a shared pointer, the generators will still be accessible (thus you can still access the computed trajectories if needed) without the need to check the pointer, but it will not be possible to generate new trajectories.
@GiulioRomualdi when you are happy with the comments we can merge 馃槈 |
LGTM. You can merge the PR |
This PR merges the branch
dcmTrajectoryGenerator
even tough not in its current form. Indeed, a general refactory was necessary in order to allow merging indevel
. Thus new bugs may arose 馃槄For the time being I just run the tests that were added to that branch, but I would kindly ask @GiulioRomualdi to perform more thorough tests.