-
Notifications
You must be signed in to change notification settings - Fork 545
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] Improve support for switching planning group #2333
Conversation
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'm not sure about this. Lot of complexity added and I don't see anything to prevent a switch when the robot is in motion.
Perhaps it would make more sense to launch 2 Servo instances, one for each move_group
? That will be needed, anyway, for something like a dual-arm system.
I don't think this adds much complexity. Other than that the changes are:
The user would have to manage that when using the C++ API like with most of the functionality , but for the ROS API which I assume most users will be using, the service call automatically pauses the servo loop before updating the move group and then resumes it after update. I think this functionality would be useful in the long run since it lets us use different groups without having to start a new node. Would be good to have some feedback from the MoveIt Studio team. |
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.
Blocking until the comments above get resolved
dd0262b
to
405ccf3
Compare
Codecov ReportPatch coverage:
Additional details and impacted files@@ Coverage Diff @@
## main #2333 +/- ##
==========================================
+ Coverage 50.73% 50.84% +0.12%
==========================================
Files 386 386
Lines 31970 31974 +4
==========================================
+ Hits 16216 16255 +39
+ Misses 15754 15719 -35
☔ View full report in Codecov by Sentry. |
This update allows the user to change the planning group and smoothing plugin without restarting the servo node. Another important change is that the choice of updating the parameters when using C++ API has been delegated to the user.
|
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 kind of agree with @AndyZe about the extra complexity, but at the same time don't think we should require multiple servo nodes to switch planning groups.
To reduce complexity, I'd like to clarify: Why do we need to explicitly call updateParameters()
with these changes? If this continues to be called automatically when you get the next servo command, this should be fine and you'll still get the warnings if you change planning groups/smoothing plugin while servo is running. Then, the changes in this PR also become much less disruptive.
As a much smaller comment: Seems with these changes we got rid of the RCLCPP_INFO_STREAM()
printouts that mentioned what parameters were changed to. Can we get those back as well?
If the One reason for making it manual is that users who do not need to update params during runtime don't need to pay the cost for load of checks that happen when calling I don't find this this change disruptive, but we can go back to putting the
Yeah, only EDIT : This de-coupling will most likely be useful for future changes as well. |
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.
Looking at this again, I'm OK with the non-node examples explicitly calling updateParams()
.
There is a test failure here based on inability to load the smoothing plugin, so take a look at that and this should be good.
|
||
// Update the parameters | ||
updateParams(); | ||
setStatus(StatusCode::NO_WARNING); |
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 this should be done outside of this function, for readability. It's kind of hidden away here in an unrelated function.
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 is the only place we can set it automatically.
Otherwise user would have to manually call 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.
If you have the function either return the status or accept it as a mutable input arg, this could be done!
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.
Reading through the code again, I realize that additionally to everything already said, using the setStatus()
function the way we use it now is why you had to make all those other member functions non-const
. So another data point for figuring this out in a more functional way.
405ccf3
to
3bf17df
Compare
Have implemented this, and kept the call to |
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.
Read through and I think this looks good.
My biggest thing remaining is ensuring we don't have to un-const
a lot of our functions. If anything, we need more of them to be const
. To that point:
- I'll +1 @AndyZe's comment on using
setStatus()
outside the bodies of existing functions so it's more readable and gives us moreconst
member functions - The
getCurrentRobotState()
is now being used both as a getter and to mutate internal state, so I think those 2 things should use 2 separate functions.
<< params.move_group_name); | ||
if (servo_status_ == StatusCode::PAUSED) | ||
{ | ||
invalid_parameter_update_ = false; |
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.
invalid_parameter_update_
is synonymous with servo_status != StatusCode::PAUSED
now, so no need for this member variable, right?
|
||
// Update the parameters | ||
updateParams(); | ||
setStatus(StatusCode::NO_WARNING); |
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.
Reading through the code again, I realize that additionally to everything already said, using the setStatus()
function the way we use it now is why you had to make all those other member functions non-const
. So another data point for figuring this out in a more functional way.
@@ -122,14 +128,19 @@ class Servo | |||
* \brief Get the current state of the robot as given by planning scene monitor. | |||
* @return The current state of the robot. | |||
*/ | |||
KinematicState getCurrentRobotState() const; | |||
KinematicState getCurrentRobotState(); |
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 is this not const
if it just gets the robot state variable?
This is impacting the constness of a bunch of other functions as well
KinematicState Servo::getCurrentRobotState() | ||
{ | ||
moveit::core::RobotStatePtr robot_state = planning_scene_monitor_->getStateMonitor()->getCurrentState(); | ||
const moveit::core::JointModelGroup* joint_model_group = | ||
robot_state->getJointModelGroup(servo_params_.move_group_name); | ||
const auto joint_names = joint_model_group->getActiveJointModelNames(); | ||
robot_state_ = planning_scene_monitor_->getStateMonitor()->getCurrentState(); | ||
|
||
KinematicState current_state(joint_names.size()); | ||
current_state.joint_names = joint_names; | ||
robot_state->copyJointGroupPositions(joint_model_group, current_state.positions); | ||
robot_state->copyJointGroupVelocities(joint_model_group, current_state.velocities); | ||
robot_state->copyJointGroupAccelerations(joint_model_group, current_state.accelerations); | ||
KinematicState current_state(joint_names_.size()); | ||
current_state.joint_names = joint_names_; | ||
robot_state_->copyJointGroupPositions(joint_model_group_, current_state.positions); | ||
robot_state_->copyJointGroupVelocities(joint_model_group_, current_state.velocities); | ||
robot_state_->copyJointGroupAccelerations(joint_model_group_, current_state.accelerations); | ||
|
||
return current_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.
Yeah, so this function seems to have 2 uses right now, which is why it's not const
. I think what we need is:
- An
updateCurrentRobotState()
that does everything done here but doesn't returncurrent_state
, it simply updatesrobot_state_
, to be used in functions that calculate commands. - A
getCurrentRobotState()
function that isconst
and simply returnsrobot_state_
, to be used in other tools.
{ | ||
bool stopped = false; | ||
auto target_state = halt_state; | ||
const auto current_state = getCurrentRobotState(); | ||
|
||
const size_t num_joints = current_state.joint_names.size(); | ||
for (size_t i = 0; i < num_joints; i++) | ||
for (size_t i = 0; i < joint_names_.size(); i++) |
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.
for (size_t i = 0; i < joint_names_.size(); i++) | |
for (size_t i = 0; i < joint_names_.size(); ++i) |
const moveit::core::JointModelGroup* joint_model_group_; | ||
std::vector<std::string> joint_names_; | ||
|
||
bool invalid_parameter_update_; |
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 don't think we need this if it's used as synonymous with servo being paused.
I also can't find that line in the PR review, but I think your changes make you able to remove the servo_paused_
member variable as well?
I had one more random thought... if we switch planning groups, things like the planning frame, controller command topic, etc. possibly will need to change too. If this is getting a bit convoluted, we can take it on at PickNik. Offer still stands! |
Yeah, I had mentioned the need for additional parameter changes in one of the earlier comments on this PR.
Yeah that might be a better choice here since you guys will have more grasp on the requirements internally. And I can work on the optimisation PR instead. |
👍 to this, and coming back full circle now |
Thanks! I'll go ahead and close this PR. Based on this, I think we can stick with the multiple node solution until/unless we can put some engineering resources on something else. |
Description
Fixes #2332
This PR adds improved support for changing the planning group used by Servo by following approach 3 mentioned in the issue.