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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Streaming odometry info, CoM and footsteps #145

Open
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

SimoneMic
Copy link

On this PR a parallel thread periodically check the status of the feet and computes the virtual unicycle, i.e. it is streaming odometry information of the robot.
In the method updateModule is also streamed the planned CoM and the relative planned footsteps (only once per double support).

This is part of the changes required for the integration with the navigation stack #142 and the PR #143
Splitting into multiple PRs to improve readability.

Copy link
Collaborator

@S-Dafarra S-Dafarra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also in this case, I would ask to move as much logic as possible from Module.cpp to dedicated classes

Comment on lines 269 to 274
* Get the footprints planned by the unicycle generator
* @param leftFootprints vector containing the desired poses of the left foot on the xy plane
* @param rightFootprints vector containing the desired poses of the right foot on the xy plane
* @return true/false in case of success/failure.
*/
bool getFootprints(std::vector<iDynTree::Vector3>& leftFootprints, std::vector<iDynTree::Vector3>& rightFootprints);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From here it is not clear that the first two elements are the position and the third element is the angle. I would suggest using a dedicated struct

Comment on lines 276 to 283
/**
* Get the unicycle state from the feet of the robot in the odom frame (aka world frame)
* @param virtualUnicyclePose pose of the virtual unicycle in the odom frame
* @param referenceUnicyclePose pose of the reference virtual unicycle in the odom frame
* @param stanceFoot returns a string with the stance foot used for the computation
* @return true/false in case of success/failure.
*/
bool getUnicycleState(iDynTree::Vector3& virtualUnicyclePose, iDynTree::Vector3& referenceUnicyclePose, const std::string& stanceFoot);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is stanceFoot an input or an output of the method? If it is an input, could you move it as a first input?

pose(0) = leftDequeue.at(i).position(0);
pose(1) = leftDequeue.at(i).position(1);
pose(2) = leftDequeue.at(i).angle;
leftFootprints.push_back(pose);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would expect this method to fill the input vectors rather than appending new elements. I would suggest to resize them to the correct dimension at the beginning, and then edit the elements by index. In this way, you can avoid to allocate new memory if the number of footprints remains constant over time.

Comment on lines +936 to +954
//Odom (expressed in odom frame)
double s_theta = std::sin(unicycleAngleOdom);
double c_theta = std::cos(unicycleAngleOdom);
unicycleRotation(0,0) = c_theta;
unicycleRotation(0,1) = -s_theta;
unicycleRotation(1,0) = s_theta;
unicycleRotation(1,1) = c_theta;
unicyclePosition = unicycleRotation * unicyclePositionFromStanceFoot; // position in respect to the support foot
unicycleOdom = unicyclePosition + footPosition; //postion in odom frame
virtualUnicyclePose(0) = unicycleOdom(0);
virtualUnicyclePose(1) = unicycleOdom(1);
virtualUnicyclePose(2) = unicycleAngleOdom;

iDynTree::Vector2 referencePointInAbsoluteFrame;
iDynTree::toEigen(referencePointInAbsoluteFrame) = unicycleRotation * (iDynTree::toEigen(m_referencePointDistance)) + unicycleOdom;
referenceUnicyclePose(0) = referencePointInAbsoluteFrame(0);
referenceUnicyclePose(1) = referencePointInAbsoluteFrame(1);
referenceUnicyclePose(2) = unicycleAngleOdom;

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines 57 to 59
# Loop rate for the thread computing the navigation trigger
navigationTriggerLoopRate 100

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned in #144, this would fit well in a separate file named navigation

Comment on lines 1904 to 1999
// This thread publishes the internal informations of the virtual unicycle extracted from the feet and the CoM speed
// It's the internal odometry
void WalkingModule::computeVirtualUnicycleThread()
{
yInfo() << "[WalkingModule::computeVirtualUnicycleThread] Starting Thread";
bool inContact = false;
while (m_runThreads)
{
if (m_robotState != WalkingFSM::Walking)
{
std::this_thread::sleep_for(std::chrono::milliseconds(1000/m_navigationTriggerLoopRate));
continue;
}

iDynTree::Vector3 virtualUnicyclePose, virtualUnicycleReference;
std::string stanceFoot;
iDynTree::Transform footTransformToWorld, root_linkTransform;
//Stance foot check
if (m_leftInContact.size() > 0)
{
if (m_leftInContact.at(0))
{
stanceFoot = "left";
footTransformToWorld = m_FKSolver->getLeftFootToWorldTransform();
}
else
{
stanceFoot = "right";
footTransformToWorld = m_FKSolver->getRightFootToWorldTransform();
}
inContact = true;
}
else if (m_rightInContact.size() > 0)
{
if (m_rightInContact.at(0))
{
stanceFoot = "right";
footTransformToWorld = m_FKSolver->getRightFootToWorldTransform();
}
else
{
stanceFoot = "left";
footTransformToWorld = m_FKSolver->getLeftFootToWorldTransform();
}
inContact = true;
}
else
{
inContact = false;
}
root_linkTransform = m_FKSolver->getRootLinkToWorldTransform(); //world -> rootLink transform
//Data conversion and port writing
if (inContact)
{
if (m_trajectoryGenerator->getUnicycleState(virtualUnicyclePose, virtualUnicycleReference, stanceFoot))
{
//send data
yarp::os::Stamp stamp (0, yarp::os::Time::now()); //move to private member of the class
m_unicyclePort.setEnvelope(stamp);
auto& data = m_unicyclePort.prepare();
data.clear();
auto& unicyclePose = data.addList();
unicyclePose.addFloat64(virtualUnicyclePose(0));
unicyclePose.addFloat64(virtualUnicyclePose(1));
unicyclePose.addFloat64(virtualUnicyclePose(2));
auto& referencePose = data.addList();
referencePose.addFloat64(virtualUnicycleReference(0));
referencePose.addFloat64(virtualUnicycleReference(1));
referencePose.addFloat64(virtualUnicycleReference(2));
data.addString(stanceFoot);

//add root link stransform: X, Y, Z, r, p, yaw,
auto& transform = data.addList();
transform.addFloat64(root_linkTransform.getPosition()(0));
transform.addFloat64(root_linkTransform.getPosition()(1));
transform.addFloat64(root_linkTransform.getPosition()(2));
transform.addFloat64(root_linkTransform.getRotation().asRPY()(0));
transform.addFloat64(root_linkTransform.getRotation().asRPY()(1));
transform.addFloat64(root_linkTransform.getRotation().asRPY()(2));

//planned velocity of the CoM
auto comVel = m_stableDCMModel->getCoMVelocity();
auto& velData = data.addList();
velData.addFloat64(comVel(0));
velData.addFloat64(comVel(1));
m_unicyclePort.write();
}
else
{
yError() << "[WalkingModule::computeVirtualUnicycleThread] Could not getUnicycleState from m_trajectoryGenerator (no data sent).";
}
}
std::this_thread::sleep_for(std::chrono::milliseconds(1000/m_navigationTriggerLoopRate));
}
yInfo() << "[WalkingModule::computeVirtualUnicycleThread] Terminated thread";
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned in #144 it would be best if the modifications to Module.cpp were minimal. This file is meant to connect all the different bits and pieces. It is more of a coordinator, so it should have limited logic.

@SimoneMic
Copy link
Author

I have updated the code to satisfy the requests.
Now there's a separate file NavigationHelper that holds all the code needed by the Nav2 stack.

@S-Dafarra
Copy link
Collaborator

I will wait for #144 to be merged first as they share a lot of code

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.

2 participants