Debugging
Advanced debugging techniques for HID ROS 2.
Debugging Tools
1. inspect_device
The primary tool for debugging USB communication:
# Monitor raw reports
ros2 run hid_tools inspect_device --vid 0xCAFE --pid 0x4000
Shows:
Report IDs
Raw bytes
Decoded values (uint32, float32, etc.)
Update rate statistics
2. ros2 control CLI
Check hardware interface status:
# List all interfaces
ros2 control list_hardware_interfaces
# List controllers
ros2 control list_controllers
# Controller status
ros2 control view_controller_chains
3. ROS 2 Topic Tools
Monitor published data:
# Echo topic
ros2 topic echo /hid_sensor_states
# Topic info
ros2 topic info /hid_sensor_states -v
# Monitor rate
ros2 topic hz /hid_sensor_states
Common Issues
No Data Received
Check 1: Device connected and recognized
lsusb | grep CAFE
ros2 run hid_tools inspect_device --list
Check 2: Correct report ID
# Compare firmware report ID with schema
ros2 run hid_tools inspect_device --vid 0xCAFE --pid 0x4000
Check 3: Hardware interface active
ros2 control list_hardware_interfaces
# Should show [available] [claimed]
Wrong Values
Check 1: Byte order
# View raw bytes
ros2 run hid_tools inspect_device --vid 0xCAFE --pid 0x4000
Verify little-endian format.
Check 2: Type mismatch
Schema says
float32but firmware sendsint16?Check struct in firmware matches schema
Check 3: Struct packing
// Firmware must use packed structs
typedef struct __attribute__((packed)) {
// ...
} Report;
Verify with:
printf("Size: %zu\n", sizeof(Report));
Performance Issues
Check 1: Update rate too high
# Monitor actual rate
ros2 topic hz /hid_sensor_states
Reduce update_rate in schema if dropping data.
Check 2: USB bandwidth
Full-speed USB: ~12 Mbps
Calculate:
report_size * update_rate * 8Should be well below 12 Mbps
Check 3: Processing time Add timing to controller:
auto start = std::chrono::high_resolution_clock::now();
// ... update code ...
auto end = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
RCLCPP_INFO_THROTTLE(get_node()->get_logger(), *get_node()->get_clock(), 1000,
"Update took %ld μs", duration.count());
Debugging Workflow
Verify device basics
lsusb ros2 run hid_tools inspect_device --list
Check raw USB communication
ros2 run hid_tools inspect_device --vid 0xVVVV --pid 0xPPPP
Verify hardware interface
ros2 control list_hardware_interfaces
Check controller status
ros2 control list_controllers
Monitor published data
ros2 topic echo /sensor_states
Advanced Debugging
USB Packet Capture
Use Wireshark with usbmon:
# Load usbmon kernel module
sudo modprobe usbmon
# Capture with Wireshark
wireshark
# Select usbmonX interface, filter: usb.device_address == YOUR_DEVICE
Firmware Debugging
Add debug output in firmware:
void send_report(void) {
HIDInputReport report = { /* ... */ };
// Debug print
printf("Sending report ID=%d, x=%.2f, y=%.2f\n",
report.report_id, report.x, report.y);
usb_hid_send((uint8_t*)&report, sizeof(report));
}
Compare with inspect_device output.
GDB Debugging
Debug the hardware interface:
# Build with debug symbols
colcon build --cmake-args -DCMAKE_BUILD_TYPE=Debug
# Run with GDB
ros2 run --prefix 'gdb --args' hid_hardware hid_hardware
Set breakpoints in read() and write() methods.
Logging
Enable debug logging:
ros2 launch my_package hid.launch.py --log-level debug
Or in code:
RCLCPP_DEBUG(get_logger(), "Read value: %f", value);
Validation Tools
Schema Validation
ros2 run hid_tools validate_schema --strict schema/hid_device.yaml
Report Size Calculation
# Calculate expected report size
from schema_parser import parse_schema
schema = parse_schema("schema/hid_device.yaml")
input_size = calculate_report_size(schema['fields'])
print(f"Expected input report size: {input_size + 1} bytes (including report ID)")
Compare with actual size from inspect_device.
Getting Help
If stuck:
Check Troubleshooting
Search GitHub Issues
Ask in GitHub Discussions
When reporting issues, include:
ROS 2 distribution and version
Schema YAML
Output from
inspect_deviceOutput from
list_hardware_interfacesRelevant logs