-
Notifications
You must be signed in to change notification settings - Fork 568
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
[Servo] Change planning frame to base frame of active joint subgroup #2515
Conversation
const auto ik_solver = active_joint_model_group->getSolverInstance(); | ||
if (ik_solver) | ||
{ | ||
const auto planning_frame = ik_solver->getBaseFrame(); |
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 there a better way to get the base link of a joint model group without having to grab the IK solver like 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.
Can't you do this?
const JointModel* root_joint_model = group->getJointModels().front();
const LinkModel* root_link_model = root_joint_model->getParentLinkModel();
But now I wonder if you rather need the IK solver base frame (i.e. your code as is), since the underlying IK solver could be working on a different frame, not necessarily the group root?
If that's the case, maybe create a getIKSolverBaseFrame()
function that can be called here and below?
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!
This raises a follow up question that, if these changes are the right thing for changing subgroups, can we actually get rid of the planning frame parameter and have servo always do its own internal conversions to active group's IK base frame?
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.
Hmm.. looking deeper into Servo I got more confused about what the 'planning frame' is, but also how this fix works, since the IK base frame for the manipulator group is the one tilted 45 deg. right? so I would expect this to still move the wrong way.
Another q: the command has a frame_id
. Shouldn't that be all that is needed to move in the same frame (e.g. world
), independently of the active group? Sorry I have more questions than answers!
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 should have more questions than answers, I think there's a lot here that needs to be disentangled for clarity.
Basically, Servo has this rule that enforces that all commands passed into it are expressed w.r.t. a common frame -- this is the "planning frame" we speak of.
All we're trying to do, perhaps in an overly complex way, is the following:
- Receive a Cartesian command w.r.t. some arbitrary frame ID
- Convert it to a reference frame that agrees with the IK solver (this is our planning frame)
- ???
- Profit
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.
Hmm... I just saw some other piece of code that reminded me of the fact that a planning group can have multiple tip frames. So can we really get rid of moveit_params.ee_frame
after all?
The other alternative, which is way more destructive, would be to modify the command message definitions for twist and pose tracking to contain both base and tip frames... which would basically require making custom messages for both instead of relying on existing geometry_msgs
definitions.
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 think we can, at least the way it is now, because ee_frame
doesn't seem to be used anywhere. The IK computation is done for ik_solver->getTipFrame()
, so it will always use the first tip.
Longer term what about having Servo expose a /configure
service, where the user could set the planning group and tip frame?
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.
Given all the struggles we've had trying to make sure that parameters stay consistent w.r.t. each other, I quite like the idea of dedicated services that touch these interrelated parameters like planning group + ee frame.
Also, having this configure
service / method means that configuring can implicitly do the task of pausing servo, changing values, and then unpausing it.
Also, I guess to be fair this code was calling getTipFrame()
already, and also there is an error logged when you call getTipFrame()
on a planning group with multiple tips.
So maybe this is just a known limitation for now and we proceed as is?
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.
A service to update the parameters might be a good idea b/c it would fix this issue: #2412
i.e. do the parameter validation in a callback in a different thread
Hate to change the API so drastically, so soon, though. Have to think carefully about 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.
I think servo has changed enough with the refactor since we kept running into limitations trying to keep the API as stable as possible with the old version. It might be beneficial to do all the big changes as soon as possible in hopes that we get to a somewhat more stable API before people actually start using this new version.
That said, we should try do all this in a way that minimizes our need to keep twiddling the interfaces going forward.
Codecov ReportAttention:
Additional details and impacted files@@ Coverage Diff @@
## main #2515 +/- ##
==========================================
+ Coverage 50.77% 50.82% +0.05%
==========================================
Files 392 392
Lines 32170 32194 +24
==========================================
+ Hits 16332 16358 +26
+ Misses 15838 15836 -2
☔ View full report in Codecov by Sentry. |
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.
This looks good to me. A couple of minor comments that can be done in follow-up changes too, since they are not really related to this PR changes.
* @param group_name The currently active joint group name. | ||
* @return The IK solver base frame, if one exists, otherwise std::nullopt. | ||
*/ | ||
std::optional<std::string> getIKSolverBaseFrame(const moveit::core::RobotStatePtr& robot_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.
Can we avoid the pointer here and below and just do const moveit::core::RobotState &robot_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.
I think the robot state which is extracted from
moveit::core::RobotStatePtr CurrentStateMonitor::getCurrentState() const
already returns in pointer form, so is it fine to keep as is? I don't particularly want to dereference what's already there.
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.
That's fine if this is only used in this context. If we ever put it somewhere more general I think we should just take the const&.
shared_ptr
is viral, it easily spreads everywhere. If this takes a shared_ptr
, it can't really can't be used unless you have a shared_ptr
already. Whereas if this takes a const&
, you can call it directly with a RobotState
object, but also with a shared_ptr
or unique_ptr
by derefencing, so it's more usable.
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.
Nice work! Most of my comments are around more error messages and documentations. Besides that I think it is good to go 👍
@AndyZe we're cutting a release tomorrow so I'm going to merge this in now. If you have any follow-on comments related to this PR, let's do a new issue/PR and take it from there? |
Description
This PR seeks to solve an issue in which changing the
active_subgroup
parameter still enforces using theservo_params.planning_frame
planning frame... which is not necessarily the correct frame for all subgroups.So instead, we're grabbing the planning frame (for twist/pose commands) to always be the base frame of the IK solver and doing the frame conversions from there. This fixes the immediate issue, but the implementation leaves much to be desired.