Skip to content
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

Merged
merged 9 commits into from
Jan 23, 2019

Conversation

S-Dafarra
Copy link
Collaborator

This PR merges the branch dcmTrajectoryGenerator even tough not in its current form. Indeed, a general refactory was necessary in order to allow merging in devel. 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.

The code has been copied from the dcmTrajectoryGenerator branch and refactored to comply with the new structure of the planner.
@S-Dafarra S-Dafarra self-assigned this Dec 17, 2018
std::lock_guard<std::mutex> guard(m_pimpl->mutex);

if (m_pimpl->feetMinimumJerkGenerator == nullptr) {
m_pimpl->feetMinimumJerkGenerator.reset(new FeetMinimumJerkGenerator());
Copy link
Member

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.

Copy link
Collaborator Author

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
@S-Dafarra
Copy link
Collaborator Author

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.

Copy link
Member

@GiulioRomualdi GiulioRomualdi left a 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)
Copy link
Member

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?

Copy link
Collaborator Author

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?

Copy link
Collaborator Author

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.

include/DCMTrajectoryGenerator.h Show resolved Hide resolved
@@ -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)));
Copy link
Member

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?

Copy link
Collaborator Author

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);
Copy link
Member

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.

Copy link
Collaborator Author

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 馃槈

Copy link
Member

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.

Copy link
Member

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) {
Copy link
Member

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.

Copy link
Collaborator Author

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/FeetMinimumJerkGenerator.cpp Show resolved Hide resolved
src/FeetMinimumJerkGenerator.cpp Outdated Show resolved Hide resolved
}
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>());
Copy link
Member

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:

  1. lFootPhases is an attribute of the class. Why is it not like m_lFootPhases? This is general for all the attribute of UnicycleGenerator::UnicycleGeneratorImplementation class. Is this related to the fact that all these attributes are public?
  2. probabily here you can use std::make_shared<>() instead of .reset(new )

Copy link
Collaborator Author

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.

Copy link
Collaborator Author

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()
Copy link
Member

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?

Copy link
Collaborator Author

@S-Dafarra S-Dafarra Jan 21, 2019

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.

@S-Dafarra
Copy link
Collaborator Author

@GiulioRomualdi when you are happy with the comments we can merge 馃槈

@GiulioRomualdi
Copy link
Member

LGTM. You can merge the PR

@S-Dafarra S-Dafarra merged commit ef71c9a into devel Jan 23, 2019
@S-Dafarra S-Dafarra deleted the dcm-refactoring branch October 27, 2020 14:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants