-
Notifications
You must be signed in to change notification settings - Fork 46
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
base: master
Are you sure you want to change the base?
Conversation
…nning. Streaming also planned footsteps and CoM
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.
Also in this case, I would ask to move as much logic as possible from Module.cpp
to dedicated classes
* 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); |
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.
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
/** | ||
* 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); |
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 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); |
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 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.
//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; | ||
|
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.
# Loop rate for the thread computing the navigation trigger | ||
navigationTriggerLoopRate 100 | ||
|
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 mentioned in #144, this would fit well in a separate file named navigation
src/WalkingModule/src/Module.cpp
Outdated
// 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"; | ||
} |
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 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.
I have updated the code to satisfy the requests. |
I will wait for #144 to be merged first as they share a lot of code |
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.