Hardware interface for sending motion primitives to the robot via the Instruction Executor instead of trajectories
This PR extends the ur_robot_driver package with a hardware interface for sending motion primitives to the robot via the Instruction Executor instead of traditional trajectory execution.
To reuse the state interface functionalities of the original hardware interface in the new motion_primitive_ur_driver, these functionalities have been refactored into a shared helper file: stateinterface_helper.hpp.
The implementation uses the motion_primitives_forward_controller, which is planned to be integrated into the ros2_controllers repository. (ros-controls/ros2_controllers#1636)
Motion primitives are received by the controller using the MotionPrimitive.msg from the industrial_robot_motion_interfaces package. A modified version of this message is used here, which includes additional helper types:
-
STOP_MOTION: Interrupts current robot motion and clears the motion queue. -
MOTION_SEQUENCE_STARTandMOTION_SEQUENCE_END: Define a sequence block—primitives between these markers are grouped and executed as a single, blended motion sequence. This enables smooth transitions between individual primitives, unlike executing them one by one.
This implementation also depends on a pending Pull Request in the Universal_Robots_Client_Library. This PR extends the Instruction Executor with support for movec commands, which is required for executing circular Cartesian motions within this driver.
I'd appreciate any feedback or suggestions – thanks in advance!
Thank you for your contribution! I'll have a look at this hopefully soon.
Just a high-level question while I go through this implementation: Why did you decide to add that functionality to another hardware interface rather than integrating it into the existing one?
Integrating it would allow to switch between modes during runtime, which is especially useful e.g. when users want to use freedrive mode in between.
We already have multiple modes in our current hardware interface calling different methods from the write() function depending on the operation mode.
There's no specific reason for that, it's simply how I started implementing it. But you're probably right that it would be more elegant to integrate it into the existing hardware interface.
@urfeex I've now integrated the motion_primitives_ur_driver into the hardware_interface, which allows switching modes during operation. I'm happy to receive any feedback on this!
During the integration, I encountered the following issue:
Both the hardware_interface implementation and the InstructionExecutor (used to execute motion primitives) depend on a callback that is triggered when a trajectory is completed. In the current setup, the UR driver's callback function is overwritten, which means only one of these callbacks can be active at any given time.
To solve this, I register the InstructionExecutor's callback when motion primitives mode is activated, and restore the hardware_interface's callback when the mode is deactivated. To enable this mechanism, I added a method registerTrajDoneCallback() to the InstructionExecutor in the ur_client_library:
void urcl::InstructionExecutor::registerTrajDoneCallback()
{
driver_->registerTrajectoryDoneCallback(
std::bind(&InstructionExecutor::trajDoneCallback, this, std::placeholders::_1));
}
Let me know if you have any suggestions for a cleaner solution.
And one more question: I’ve documented everything a bit in README_MotionPrimitive.md. Should I integrate that into README.md? Or put it somewhere else? Or should I just leave it as it is?
@mathias31415 regarding b4f4dec, please let's keep that back for a follow-up PR.
@mathias31415 could you please fix the merge conflicts for this?
Codecov Report
:x: Patch coverage is 0% with 289 lines in your changes missing coverage. Please review.
:white_check_mark: Project coverage is 15.31%. Comparing base (1b121b7) to head (20d0bfe).
:warning: Report is 507 commits behind head on main.
| Files with missing lines | Patch % | Lines |
|---|---|---|
| ur_robot_driver/src/hardware_interface.cpp | 0.00% | 289 Missing :warning: |
Additional details and impacted files
@@ Coverage Diff @@
## main #1341 +/- ##
==========================================
+ Coverage 3.59% 15.31% +11.72%
==========================================
Files 13 34 +21
Lines 947 3873 +2926
Branches 152 482 +330
==========================================
+ Hits 34 593 +559
- Misses 843 3263 +2420
+ Partials 70 17 -53
| Flag | Coverage Δ | |
|---|---|---|
| unittests | 15.31% <0.00%> (+11.72%) |
:arrow_up: |
Flags with carried forward coverage won't be shown. Click here to find out more.
:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.
:rocket: New features to boost your workflow:
- :snowflake: Test Analytics: Detect flaky tests, report on failures, and find test suite problems.