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

Enable using a subgroup of the move group in servo #2396

Merged
merged 14 commits into from
Oct 9, 2023

Conversation

sjahr
Copy link
Contributor

@sjahr sjahr commented Sep 29, 2023

Description

This PR enables using a subgroup of the move_group at runtime without the need to stop servo or switch controllers.

  • Make subgroup -> move group joint index mapping more efficient
  • Disable joint jogging for joints that aren't part of active subgroup

Checklist

  • Required by CI: Code is auto formatted using clang-format
  • Extend the tutorials / documentation reference
  • Document API changes relevant to the user in the MIGRATION.md notes
  • Create tests, which fail without this PR reference
  • Include a screenshot if changing a GUI
  • While waiting for someone to review your request, please help review another open pull request to support the maintainers

@sjahr sjahr requested review from sea-bass and AndyZe September 29, 2023 12:14
Copy link
Contributor

@sea-bass sea-bass left a comment

Choose a reason for hiding this comment

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

Thanks for getting on this! I think your idea of having a fixed move group and only allowing the changing of subgroups has reduced scope enough to be useful and also not overly complicated.

I have one meaningful inline comment about searching for indices (see below).

My other main comment is, I know @AndyZe, @ibrahiminfinite, and I were discussing the risks of immediately switching planning groups and having joints added/removed be commanded with sudden velocity changes. I think because of the subgroup assumption, this may be OK, but it's worth thinking about it: if, e.g., a joint was moving with a nonzero velocity and we suddenly change to a subgroup without the joint, will this cause any issue or will it slow down the joint using the scalings provided?

EDIT: Adding to the above, our "scoped down and not complicated" idea here was to enforce that servo was paused before allowing switching groups. So that's always a fallback.

moveit_ros/moveit_servo/config/servo_parameters.yaml Outdated Show resolved Hide resolved
moveit_ros/moveit_servo/src/utils/command.cpp Outdated Show resolved Hide resolved
moveit_ros/moveit_servo/src/utils/command.cpp Outdated Show resolved Hide resolved
@codecov
Copy link

codecov bot commented Sep 29, 2023

Codecov Report

Attention: 20 lines in your changes are missing coverage. Please review.

Comparison is base (f949aa0) 50.84% compared to head (67b7fb1) 50.87%.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2396      +/-   ##
==========================================
+ Coverage   50.84%   50.87%   +0.03%     
==========================================
  Files         386      386              
  Lines       31938    31983      +45     
==========================================
+ Hits        16237    16269      +32     
- Misses      15701    15714      +13     
Files Coverage Δ
...eit_servo/include/moveit_servo/utils/datatypes.hpp 100.00% <ø> (ø)
moveit_ros/moveit_servo/src/servo.cpp 66.67% <84.85%> (+3.10%) ⬆️
moveit_ros/moveit_servo/src/utils/command.cpp 70.28% <50.00%> (-5.72%) ⬇️

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@tylerjw tylerjw force-pushed the pr-enable_using_subgroup_in_servo branch from a899bed to 3690cb7 Compare September 29, 2023 15:27
Copy link
Member

@AndyZe AndyZe left a comment

Choose a reason for hiding this comment

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

blocking til i have time to review

Copy link
Member

@AndyZe AndyZe left a comment

Choose a reason for hiding this comment

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

Is there an urgent need for this feature? Seems like a bit of a stretch.

What happens to the other joints when you start actuating the subgroup only? Are they still filtered?

moveit_ros/moveit_servo/src/servo.cpp Outdated Show resolved Hide resolved
}

return params_valid;
return true;
}

bool Servo::updateParams()
Copy link
Member

Choose a reason for hiding this comment

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

Need to make sure Servo is paused before doing this for a couple reasons:

  • Don't want to have these operations in the control loop
  • I think it's good from a safety perspective to stop the other joints beside this subgroup. Pausing should do that

@AndyZe
Copy link
Member

AndyZe commented Sep 30, 2023

Does this change the dimension of the final command to ros2_control? That would be another issue when the controller topic type is std_msgs/Float64MultiArray (It's just a dumb array without joint names.)

@ibrahiminfinite
Copy link
Contributor

Does this change the dimension of the final command to ros2_control? That would be another issue when the controller topic type is std_msgs/Float64MultiArray (It's just a dumb array without joint names.)

From what I understand, the new logic does not change the dimension of the final command, it just sets the delta_theta for joints not in the desired sub_group to zero.

@sjahr sjahr self-assigned this Oct 3, 2023
@sjahr
Copy link
Contributor Author

sjahr commented Oct 4, 2023

@AndyZe my changes are meant to enable servoing only a subgroup at runtime without the need to pause servo and/or switch controllers. If a subgroup is enabled I only use this subgroup to calculate the delta_thetas and command a 0 delta theta to the other joints of the move_group. From a robot perspective nothing should change except that some joints (the ones that aren't part of the subgroup) get commands to hold their current position.

@sjahr
Copy link
Contributor Author

sjahr commented Oct 5, 2023

@ibrahiminfinite Any clue why the tests are failing?

    [ros2_control_node-1] terminate called after throwing an instance of 'std::runtime_error'
    [ros2_control_node-1]   what():  can't compare times with different time sources
    [ros2_control_node-1] Stack trace (most recent call last) in thread 23189:
    [ros2_control_node-1] #13   Object "", at 0xffffffffffffffff, in 
    [ros2_control_node-1] #12   Object "/usr/lib/x86_64-linux-gnu/libc.so.6", at 0x7fde71106bf3, in __clone
    [ros2_control_node-1] #11   Object "/usr/lib/x86_64-linux-gnu/libc.so.6", at 0x7fde71075ac2, in 
    [ros2_control_node-1] #10   Object "/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.30", at 0x7fde71307252, in 
    [spawner-2] [INFO] [1696511567.840236022] [spawner_joint_state_broadcaster]: [NON-XML-CHAR-0x1B][92mConfigured and activated [NON-XML-CHAR-0x1B][1mjoint_state_broadcaster[NON-XML-CHAR-0x1B][0m
    [ros2_control_node-1] #9    Object "/opt/ros/rolling/lib/controller_manager/ros2_control_node", at 0x5614c0025a33, in 
    [ros2_control_node-1] #8    Object "/opt/ros/rolling/lib/libcontroller_manager.so", at 0x7fde7176af3c, in controller_manager::ControllerManager::update(rclcpp::Time const&, rclcpp::Duration const&)
    [ros2_control_node-1] #7    Object "/opt/ros/rolling/lib/librclcpp.so", at 0x7fde7155bb09, in 
    [ros2_control_node-1] #6    Object "/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.30", at 0x7fde712d94d7, in __cxa_throw
    [ros2_control_node-1] #5    Object "/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.30", at 0x7fde712d9276, in std::terminate()
    [ros2_control_node-1] #4    Object "/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.30", at 0x7fde712d920b, in 
    [ros2_control_node-1] #3    Object "/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.30", at 0x7fde712cdb9d, in 
    [ros2_control_node-1] #2    Object "/usr/lib/x86_64-linux-gnu/libc.so.6", at 0x7fde710097f2, in abort
    [ros2_control_node-1] #1    Object "/usr/lib/x86_64-linux-gnu/libc.so.6", at 0x7fde71023475, in raise
    [ros2_control_node-1] #0    Object "/usr/lib/x86_64-linux-gnu/libc.so.6", at 0x7fde710779fc, in pthread_kill
    [ros2_control_node-1] Aborted (Signal sent by tkill() 23157 0)
Error: ROR] [ros2_control_node-1]: process has died [pid 23157, exit code -6, cmd '/opt/ros/rolling/lib/controller_manager/ros2_control_node --ros-args --params-file /tmp/launch_params_uphjjf6h --params-file /home/runner/work/moveit2/moveit2/.work/upstream_ws/install/moveit_resources_panda_moveit_config/share/moveit_resources_panda_moveit_config/config/ros2_controllers.yaml'].

Copy link
Contributor

@sea-bass sea-bass left a comment

Choose a reason for hiding this comment

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

I tested this on our robot on linear actuator example and it works beautifully!

Once you address @AndyZe's comment that servo should be paused for this parameter switch to kick in, should be good to go from my end.

moveit_ros/moveit_servo/src/servo.cpp Outdated Show resolved Hide resolved
moveit_ros/moveit_servo/src/servo.cpp Outdated Show resolved Hide resolved
moveit_ros/moveit_servo/src/servo.cpp Outdated Show resolved Hide resolved
moveit_ros/moveit_servo/src/utils/command.cpp Outdated Show resolved Hide resolved
@sjahr
Copy link
Contributor Author

sjahr commented Oct 6, 2023

@ibrahiminfinite Any clue why the tests are failing?

    [ros2_control_node-1] terminate called after throwing an instance of 'std::runtime_error'
    [ros2_control_node-1]   what():  can't compare times with different time sources
    [ros2_control_node-1] Stack trace (most recent call last) in thread 23189:
    [ros2_control_node-1] #13   Object "", at 0xffffffffffffffff, in 
    [ros2_control_node-1] #12   Object "/usr/lib/x86_64-linux-gnu/libc.so.6", at 0x7fde71106bf3, in __clone
    [ros2_control_node-1] #11   Object "/usr/lib/x86_64-linux-gnu/libc.so.6", at 0x7fde71075ac2, in 
    [ros2_control_node-1] #10   Object "/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.30", at 0x7fde71307252, in 
    [spawner-2] [INFO] [1696511567.840236022] [spawner_joint_state_broadcaster]: [NON-XML-CHAR-0x1B][92mConfigured and activated [NON-XML-CHAR-0x1B][1mjoint_state_broadcaster[NON-XML-CHAR-0x1B][0m
    [ros2_control_node-1] #9    Object "/opt/ros/rolling/lib/controller_manager/ros2_control_node", at 0x5614c0025a33, in 
    [ros2_control_node-1] #8    Object "/opt/ros/rolling/lib/libcontroller_manager.so", at 0x7fde7176af3c, in controller_manager::ControllerManager::update(rclcpp::Time const&, rclcpp::Duration const&)
    [ros2_control_node-1] #7    Object "/opt/ros/rolling/lib/librclcpp.so", at 0x7fde7155bb09, in 
    [ros2_control_node-1] #6    Object "/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.30", at 0x7fde712d94d7, in __cxa_throw
    [ros2_control_node-1] #5    Object "/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.30", at 0x7fde712d9276, in std::terminate()
    [ros2_control_node-1] #4    Object "/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.30", at 0x7fde712d920b, in 
    [ros2_control_node-1] #3    Object "/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.30", at 0x7fde712cdb9d, in 
    [ros2_control_node-1] #2    Object "/usr/lib/x86_64-linux-gnu/libc.so.6", at 0x7fde710097f2, in abort
    [ros2_control_node-1] #1    Object "/usr/lib/x86_64-linux-gnu/libc.so.6", at 0x7fde71023475, in raise
    [ros2_control_node-1] #0    Object "/usr/lib/x86_64-linux-gnu/libc.so.6", at 0x7fde710779fc, in pthread_kill
    [ros2_control_node-1] Aborted (Signal sent by tkill() 23157 0)
Error: ROR] [ros2_control_node-1]: process has died [pid 23157, exit code -6, cmd '/opt/ros/rolling/lib/controller_manager/ros2_control_node --ros-args --params-file /tmp/launch_params_uphjjf6h --params-file /home/runner/work/moveit2/moveit2/.work/upstream_ws/install/moveit_resources_panda_moveit_config/share/moveit_resources_panda_moveit_config/config/ros2_controllers.yaml'].

@ibrahiminfinite FYI: The CI failure was caused by a bug in an upstream dependency (ros-controls/ros2_control#1127) and it already got fixed on their end with a new minor release ros-controls/ros2_control@3.19.0...3.19.1, so our CI will be working again once the docker images got updated (Sebastian C just triggered that 🙏)

Co-authored-by: Sebastian Castro <[email protected]>
@sea-bass
Copy link
Contributor

sea-bass commented Oct 6, 2023

It does seem there is another failure now, though... 😔

@sjahr
Copy link
Contributor Author

sjahr commented Oct 7, 2023

Now this unittest is failing which is not related to these changes (it fails in #2288 and main too).

    [moveit_servo_utils_test-5] [INFO] [1696613355.885158439] [moveit_robot_model.robot_model]: Loading robot model 'panda'...
    [moveit_servo_utils_test-5] /home/runner/work/moveit2/moveit2/.work/target_ws/src/moveit2/moveit_ros/moveit_servo/tests/test_utils.cpp:162: Failure
    [moveit_servo_utils_test-5] Expected equality of these values:
    [moveit_servo_utils_test-5]   scaling_result.second
    [moveit_servo_utils_test-5]     Which is: 1-byte object <02>
    [moveit_servo_utils_test-5]   moveit_servo::StatusCode::NO_WARNING
    [moveit_servo_utils_test-5]     Which is: 1-byte object <00>

@ibrahiminfinite Do you have any idea why this is happening? I don't see any immediate reason for the flakiness but I am probably missing something

@ibrahiminfinite
Copy link
Contributor

ibrahiminfinite commented Oct 7, 2023

Now this unittest is failing which is not related to these changes (it fails in #2288 and main too).

    [moveit_servo_utils_test-5] [INFO] [1696613355.885158439] [moveit_robot_model.robot_model]: Loading robot model 'panda'...
    [moveit_servo_utils_test-5] /home/runner/work/moveit2/moveit2/.work/target_ws/src/moveit2/moveit_ros/moveit_servo/tests/test_utils.cpp:162: Failure
    [moveit_servo_utils_test-5] Expected equality of these values:
    [moveit_servo_utils_test-5]   scaling_result.second
    [moveit_servo_utils_test-5]     Which is: 1-byte object <02>
    [moveit_servo_utils_test-5]   moveit_servo::StatusCode::NO_WARNING
    [moveit_servo_utils_test-5]     Which is: 1-byte object <00>

@ibrahiminfinite Do you have any idea why this is happening? I don't see any immediate reason for the flakiness but I am probably missing something

That is weird!
I see no reason for it to fail, the test is also very straightforward.
Also the 2 other related tests (Halting and leaving singularity) are passing.

@sjahr
Copy link
Contributor Author

sjahr commented Oct 7, 2023

That was my impression too, thanks for your quick answer! Also when I run the test locally, it succeeds 🤔

@sea-bass
Copy link
Contributor

sea-bass commented Oct 7, 2023

That was my impression too, thanks for your quick answer! Also when I run the test locally, it succeeds 🤔

Maybe the change in condition number is right at the threshold of the servo parameters?

I would print the values in the condition numbers to see how small their differences are.

You could consider maybe picking a bigger cartesian delta and/or thresholds in the servo params, or choosing an initial state with higher manipulability. It's OK to use bigger than default numbers here!

@sea-bass
Copy link
Contributor

sea-bass commented Oct 8, 2023

I think I know what's wrong with the unit tests. (@ibrahiminfinite)

I ran these locally, printing output, and have been noticing their values are not consistent between runs. Turns out, when you do

robot_state->setJointGroupActivePositions();

This only sets the joint values but not the link transforms used in getJacobian() ... so you need to also call

robot_state->updateLinkTransforms();

When I made this change, my results are consistent, but also leads to new test failures because for many of the tests the condition number actually evaluates to inf -- so something in the calculation is not exactly going correctly.

Up to you guys if you want to look at this for this PR, or in a follow on.

@sea-bass
Copy link
Contributor

sea-bass commented Oct 9, 2023

I think I may have fixed it in #2414?

@sjahr sjahr enabled auto-merge (squash) October 9, 2023 12:54
@sjahr sjahr merged commit 01bae77 into moveit:main Oct 9, 2023
7 of 8 checks passed
m-elwin pushed a commit to m-elwin/moveit2 that referenced this pull request Dec 4, 2023
* Enable using a subgroup of the move group in servo

* Remove unnecessary validations since the param is const

* Apply suggestions from code review

Co-authored-by: Sebastian Castro <[email protected]>

* Don't copy joints if subgroup == move group

* Re-add params_valid in validateParams

* Generalize active subgroup delta calculation

* Add more efficient move group joint position lookup

* Create subgroup map in the constructor

* Apply suggestions from code review

Co-authored-by: Sebastian Castro <[email protected]>

* Update moveit_ros/moveit_servo/src/servo.cpp

---------

Co-authored-by: Sebastian Castro <[email protected]>
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.

4 participants