Skip to content

Source-Robotics/source_robotics_msg_gripper_ros2

 
 

MSG Gripper ROS2 Driver

ROS2 Humble License: MIT Python 3.10+

ROS2 driver for the MSG gripper using the Spectral BLDC library and CAN bus.

Developed by UCLA Biomechatronics Lab and Ben Forbes

Overview

The node accepts sensor_msgs/JointState commands with position specified as encoder counts (0–255) and publishes feedback with position in encoder counts and effort in milliamps.

Direction Topic Message Type
Command /gripper/command_joint_states sensor_msgs/JointState
Feedback /gripper/feedback_joint_states sensor_msgs/JointState

A control_msgs/GripperCommand action server is also available at /gripper_command.


Prerequisites

  • Ubuntu 22.04 LTS with ROS2 Humble installed (installation guide)
  • Python 3.10+
  • A USB-to-CAN adapter that supports the slcan protocol (e.g., CANable, PCAN-USB)

macOS / Windows: Not officially tested, but the Python driver code is platform-agnostic. ROS2 and python-can must be available on your platform. The only OS-specific setting is the channel device path — see Hardware & CAN Setup below.


Hardware & CAN Setup

The gripper communicates over CAN bus via a USB-to-CAN adapter using the slcan protocol.

Finding your device path

After plugging in the USB-to-CAN adapter, find the device path:

Linux:

ls /dev/ttyACM* /dev/ttyUSB*
# Typical result: /dev/ttyACM0  or  /dev/ttyUSB0

macOS:

ls /dev/tty.usb*
# Typical result: /dev/tty.usbmodem1101  or  /dev/tty.usbserial-1234

Windows: Open Device Manager → Ports (COM & LPT) → note the COMx number (e.g., COM3).

Platform channel values

The channel parameter in config/default.yaml (or passed at launch) is the only OS-specific setting:

Platform Typical channel value
Linux /dev/ttyACM0 or /dev/ttyUSB0
macOS /dev/tty.usbmodem* or /dev/tty.usbserial*
Windows COM3 (adjust number as needed)

Linux: Grant serial port access

On Linux you may need to add your user to the dialout group to access /dev/ttyACM* without sudo:

sudo usermod -aG dialout $USER
# Log out and back in for the change to take effect

Installation

1. Install pip dependencies

pip install Spectral_BLDC python-can

2. Clone and build

cd ~/ros2_ws/src
git clone https://github.com/BiomechatronicsLab/source_robotics_msg_gripper_ros2.git
cd ~/ros2_ws
colcon build --packages-select msg_gripper_ros2
source install/setup.bash

Usage

ros2 launch msg_gripper_ros2 msg_gripper_launch.py

With custom config or namespace:

ros2 launch msg_gripper_ros2 msg_gripper_launch.py \
  config_file:=/path/to/my_config.yaml \
  node_name:=my_gripper \
  namespace:=robot

Override individual parameters by providing a custom config file:

# Copy and edit the default config
cp src/msg_gripper_ros2/config/default.yaml ~/my_gripper.yaml
# Edit channel, bustype, etc. in ~/my_gripper.yaml, then:
ros2 launch msg_gripper_ros2 msg_gripper_launch.py \
  config_file:=~/my_gripper.yaml

Or run the node directly with --ros-args for one-off overrides:

ros2 run msg_gripper_ros2 msg_gripper_node \
  --ros-args -p channel:=/dev/ttyUSB0

Command Format

Publish a sensor_msgs/JointState to the command topic:

Field Description
position[0] Target position — encoder counts (0–255)
velocity[0] (optional) Speed 0–255, default: 20
effort[0] (optional) Force in mA, default: 500

Commands are filtered by a deadband: if the new position is within position_deadband counts (default: 5) of the last sent position, the command is silently dropped. This prevents redundant CAN traffic.

Feedback Format

The feedback JointState contains:

Field Description
position[0] Current position in encoder counts
effort[0] Motor current in mA

Testing

All tests are run with pytest from the package directory:

cd ~/src/source_robotics_msg_gripper_ros2/
source /opt/ros/humble/setup.bash

Unit tests only (no hardware required)

pytest test/ -v -m "not hardware"

The unit tests mock the Spectral_BLDC library so no CAN adapter or gripper needs to be connected.

All tests (unit + hardware-in-the-loop)

With the gripper connected (the test suite launches the node automatically):

pytest test/ -v

Custom device path:

pytest test/ -v --channel /dev/ttyUSB0

If the node is already running externally:

pytest test/ -v --no-launch

Available pytest options

Option Default Description
--channel /dev/ttyACM0 CAN serial device path
--bustype slcan CAN bus type
--bitrate 1000000 CAN bitrate in bps
--no-launch False Skip launching the node (assumes it is already running)
--startup-timeout 10 Seconds to wait for node startup

Quick Test

# Command gripper to position 128
ros2 topic pub --once /gripper/command_joint_states sensor_msgs/msg/JointState \
  "{position: [128]}"

# Monitor feedback
ros2 topic echo /gripper/feedback_joint_states

Action Server

The node exposes a control_msgs/GripperCommand action at /gripper_command.

position maps to encoder counts (0–255); max_effort maps to force in mA (0 = use default).

Send a goal from the command line:

ros2 action send_goal /gripper_command control_msgs/action/GripperCommand \
  "{command: {position: 200.0, max_effort: 500.0}}"

Send a goal and stream feedback:

ros2 action send_goal --feedback /gripper_command control_msgs/action/GripperCommand \
  "{command: {position: 100.0, max_effort: 0.0}}"

max_effort: 0.0 uses the node's default_force parameter.


Parameters

All parameters are configurable via config/default.yaml or at launch time.

Parameter Default Description
bustype slcan CAN bus type
channel /dev/ttyACM0 CAN interface device (OS-specific — see above)
bitrate 1000000 CAN bitrate
node_id 0 Spectral BLDC node ID
default_speed 20 Default speed (0–255)
default_force 500 Default force in mA
position_deadband 5 Minimum change in counts to send a new command
auto_calibrate true Run calibration on startup
command_topic /gripper/command_joint_states Command subscription topic
feedback_topic /gripper/feedback_joint_states Feedback publisher topic

Troubleshooting

Failed to initialize CAN: ...

  • Check that the USB-to-CAN adapter is plugged in and recognized by the OS.
  • Verify the channel parameter matches the actual device path (e.g., /dev/ttyACM0).
  • Try a lower bitrate if the adapter does not support 1 Mbit/s.

Permission denied on /dev/ttyACM* or /dev/ttyUSB* (Linux)

# Quick fix (requires sudo each session):
sudo chmod a+rw /dev/ttyACM0

# Permanent fix (requires logout):
sudo usermod -aG dialout $USER

Calibration not completing

  • The calibration command is sent once ~1 second after startup (auto_calibrate: true).
  • If the gripper does not move, check CAN communication first (see above).
  • You can disable auto-calibration with auto_calibrate: false and trigger it manually if needed.
  • Ensure the gripper has enough range of motion and is not mechanically obstructed.

No feedback messages on /gripper/feedback_joint_states

  • Confirm the node started without errors (ros2 node list should show msg_gripper_node).
  • The motor only responds after being addressed — check that at least one command has been sent.
  • Use ros2 topic hz /gripper/feedback_joint_states to confirm the publisher is running at ~20 Hz.

Package Structure

msg_gripper_ros2/
├── CMakeLists.txt
├── package.xml
├── setup.py
├── pytest.ini
├── LICENSE
├── README.md
├── CONTRIBUTING.md
├── CODEOWNERS.md
├── msg_gripper_ros2/
│   ├── __init__.py
│   └── msg_gripper_node.py
├── launch/
│   └── msg_gripper_launch.py
├── config/
│   └── default.yaml
├── resource/
│   └── msg_gripper_ros2
└── test/
    ├── conftest.py       # shared fixtures and CLI options
    ├── test_unit.py      # offline unit tests (no hardware)
    └── test_hardware.py  # hardware-in-the-loop tests

Contributing / Issues

Bug reports and pull requests are welcome at: https://github.com/BiomechatronicsLab/source_robotics_msg_gripper_ros2/issues

Please include:

  • ROS2 distribution and OS version
  • USB-to-CAN adapter model
  • Full error output from ros2 launch msg_gripper_ros2 msg_gripper_launch.py

About

An open source ROS2 driver for the Source Robotics MSG adaptive electric gripper

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • Python 97.3%
  • CMake 2.7%