ROS 2 tactile sensing: from synthetic messages to replay

Build the RoboSkin ROS 2 starter kit, inspect normalized tactile arrays and use rosbag2 to record and replay. Includes verified source references and explicit runtime limits.

Publish a deterministic synthetic array, inspect its contract, record one topic and replay it with the publisher stopped. No robot, hardware driver or actuator command is involved.

Verification scope

Source checked at 7bf81d2 on 2026-09-16. Four contract tests and Python compilation passed locally. Upstream Lyrical CI built the packages and inspected the interface. Launch, live messages, recording and replay were not executed in this Windows environment, which has no ROS 2 installation or Linux runtime.

1. Use one ROS and operating-system combination

This walkthrough targets Ubuntu 26.04 (Resolute), Bash and ROS 2 Lyrical. The starter-kit CI uses osrf/ros:lyrical-desktop; the upstream image is based on Ubuntu Resolute. Do not mix these commands with a Humble, Jazzy or Kilted workspace.

Follow the official Lyrical Ubuntu installation guide to configure UTF-8, the Ubuntu repositories and the ROS apt source, then install the desktop packages and development tools below. This requires administrator access on that Linux environment. Run rosdep init only on a fresh installation; skip it if rosdep is already initialized.

These installation and runtime commands are source-checked instructions, not a local ROS execution transcript. The upstream CI result covers building and interface inspection only.

Ubuntu 26.04 / Bash — after configuring the official ROS apt repository
sudo apt update
sudo apt install ros-lyrical-desktop ros-dev-tools git
source /opt/ros/lyrical/setup.bash
sudo rosdep init  # once per fresh rosdep installation
rosdep update
printenv ROS_DISTRO

2. Get the inspected code and build the workspace

Use a new workspace. Pin the inspected commit so the interface and commands below remain reviewable. rosdep reads the actual package manifests; colcon builds the message package and the Python demo. Source the resulting overlay in every terminal that uses these packages.

Clone, pin, resolve dependencies and build
mkdir -p ~/roboskin_ws/src
cd ~/roboskin_ws/src
git clone https://github.com/roboskin-ai/ros2-tactile-starter-kit.git
cd ros2-tactile-starter-kit
git checkout 7bf81d2575e3ef4b62034f4771daf948033b4d76
cd ~/roboskin_ws
source /opt/ros/lyrical/setup.bash
rosdep install --from-paths src --ignore-src -r -y
colcon build --symlink-install
source install/setup.bash
ros2 interface show roboskin_tactile_msgs/msg/TactileArray

3. Publish a synthetic tactile field

The launch file starts synthetic_publisher and contract_monitor from roboskin_tactile_demo. Its exposed launch arguments are rows, columns and publish_rate_hz. The default is a 4 × 4 grid with a requested timer rate of 10 Hz.

The values come from sine and cosine functions in the source. They are deterministic normalized signals for integration exercises, not sensor measurements or physics simulation. A requested timer rate is not a measured sampling-rate guarantee.

Terminal A — leave the publisher and monitor running
cd ~/roboskin_ws
source /opt/ros/lyrical/setup.bash
source install/setup.bash
ros2 launch roboskin_tactile_demo demo.launch.py rows:=4 columns:=4 publish_rate_hz:=10.0
Terminal B — inspect one message with compatible QoS
cd ~/roboskin_ws
source /opt/ros/lyrical/setup.bash
source install/setup.bash
ros2 topic info /tactile/array --verbose
ros2 topic echo /tactile/array --once --qos-reliability best_effort --qos-durability volatile

4. Read shape, units, validity and time correctly

The type is roboskin_tactile_msgs/msg/TactileArray, an experimental reference implementation rather than an official ROS standard. It is not a completed hardware driver or evidence of compatibility with a commercial sensor.

The monitor checks dimensions, array lengths and validity bytes, then reports pressure-channel statistics every tenth accepted frame. It does not check all semantic errors: channel units, nonfinite numbers, clock synchronization, calibration and geometry still need separate inspection. The channel name pressure does not make its normalized values physical pressure.

Field or conceptMeaning in this demo
rows / columns4 / 4 by default; 16 logical taxels.
channels / unitspressure, shear_x, shear_y; all three units are normalized. No newtons or pascals.
values / valid48 channel-major values and 16 validity bytes by default. 1 = usable; 0 = masked/invalid.
Flattening((channel * rows) + row) * columns + column. Read channel order from each message.
header.frame_id / sensor_iddemo_tactile_surface / demo_surface. A name alone does not provide TF geometry.
Sampling timeFor real acquisition, the measurement time. Here header.stamp is the ROS clock read after synthetic values are computed; there is no physical sample.
Receive timeA subscriber-side timestamp on arrival. The included monitor does not record it. A bag timestamp must be interpreted with its recording and middleware semantics.
End-to-end latencyRequires a defined start and end, compatible clocks and measured timestamps. Neither the publisher rate nor this monitor measures sensor-to-action latency.

5. Record the topic with rosbag2

Keep Terminal A running. In Terminal B, record the topic using the repository’s best-effort, volatile QoS override. This path follows the actual cloned directory name, ros2-tactile-starter-kit.

Let messages arrive, then press Ctrl+C in Terminal B so rosbag2 closes the recording. Inspect the bag information and verify the topic, type and a nonzero message count. Counts and storage metadata depend on your run; no example count is asserted here. Choose a new output directory if tactile_demo already exists.

Terminal B — record, stop with Ctrl+C, then inspect
cd ~/roboskin_ws
ros2 bag record --topics /tactile/array \
  --qos-profile-overrides-path src/ros2-tactile-starter-kit/src/roboskin_tactile_demo/config/rosbag2_qos_overrides.yaml \
  -o tactile_demo
# Press Ctrl+C before running the next command.
ros2 bag info tactile_demo

6. Stop live publishing, then replay

Press Ctrl+C in Terminal A to stop both launched nodes. Start only the monitor there. Play the recording in Terminal B after the monitor has started. This prevents live and recorded messages from mixing on the same topic.

The replay preserves the recorded header stamps while publication happens later. A wall-clock subtraction against an old stamp measures age plus other effects, not the original live transport latency. This monitor does not use simulation time or compute latency, so the exercise does not require --clock.

Terminal A — monitor only, after stopping the launch
cd ~/roboskin_ws
source /opt/ros/lyrical/setup.bash
source install/setup.bash
ros2 run roboskin_tactile_demo contract_monitor
Terminal B — replay
cd ~/roboskin_ws
ros2 bag play tactile_demo \
  --qos-profile-overrides-path src/ros2-tactile-starter-kit/src/roboskin_tactile_demo/config/rosbag2_qos_overrides.yaml

7. What was actually verified

On 2026-09-16, we cloned commit 7bf81d2, read the message, package entry points, launch file, publisher, monitor and QoS configuration, and ran the four dependency-free contract tests with CPython 3.13.3 on Windows. Python compilation also passed. The output below is from that local contract-test run; it is not ROS terminal output.

GitHub Actions run 32648006098 reports successful dependency installation, colcon build and generated-interface inspection in osrf/ros:lyrical-desktop for this exact commit. We inspected the workflow and run/job results. That workflow does not launch the demo or record and replay a bag.

This local environment has no ROS 2 installation, Docker runtime or installed WSL distribution. The launch, inspection, recording and playback commands above remain unexecuted here. There is no claimed live message output, timing measurement, hardware test or calibration result.

Actual local dependency-free test output (duration omitted)
test_demo_is_explicitly_synthetic_and_normalized ... ok
test_message_fields_and_layout_rule_are_published ... ok
test_qos_matches_ros_sensor_data_profile_shape ... ok
test_sample_frame_is_a_complete_two_by_two_grid ... ok
Ran 4 tests
OK

Troubleshooting by symptom

Work through these checks before changing the interface or treating an empty stream as a sensor fault.

SymptomCheck and next step
ros2 or a package cannot be foundSource /opt/ros/lyrical/setup.bash and ~/roboskin_ws/install/setup.bash in that terminal. Check the first colcon error if the overlay was not built.
rosdep reports an existing default sources fileSkip rosdep init on that installation; run rosdep update. Do not repeatedly initialize it.
Echo or recording receives no dataCheck that Terminal A is alive, both terminals use the same ROS_DOMAIN_ID and middleware environment, and the subscriber uses best-effort / volatile QoS. Inspect ros2 topic info --verbose.
QoS file does not existRun from ~/roboskin_ws and use src/ros2-tactile-starter-kit/…; a differently named clone needs a correspondingly different path.
Bag output directory already existsChoose a new -o directory. Preserve recordings you still need.
Monitor prints nothing during a short replayIt reports every tenth accepted frame. Inspect the bag count and use topic echo to inspect a shorter stream. Start the monitor before playback.
Unexpected shape, units or invalid valuesCompare lengths with rows × columns × channels; inspect units and validity. Do not turn invalid taxels into zero or interpret normalized data as force.
Replay appears to contain extra framesStop the live publisher before playback and check for other publishers on the same topic.

Common questions

Is this a hardware driver or standard message?

No. It is an Apache-2.0 experimental message and synthetic publisher. Hardware acquisition, calibration, compatibility and actuator control have not been implemented or verified by this tutorial.

Can I use the CSV from the repository as a captured run?

No. sample_data/tactile_frame.csv is a separate 2 × 2, four-row synthetic fixture, not a recording of the default 4 × 4 publisher.

How do I inspect data before learning ROS 2?

Use the Python tactile data exercise. It has independent synthetic time-series data, explicit validity checks and actual generated results, without a ROS dependency.

Next steps

Source references