ROS2-like command line tools for LCM (Lightweight Communications and Marshalling)
Project description
LCM CLI Tools
ROS2-style command line tools for monitoring and debugging LCM (Lightweight Communications and Marshalling) networks.
Features
lcm topic echo <channel> — View real-time topic data (like ros2 topic echo)
lcm topic list — List active topics/channels (like ros2 topic list)
lcm topic stats — Real-time topic stats: rate, bandwidth, msg count (like ros2 topic hz)
lcm node list — List discovered publisher nodes (like ros2 node list)
Highlight: Built-in pure-Python .lcm file parser — no lcm-gen or PYTHONPATH needed. Just point to your .lcm files and messages are decoded automatically.
Installation
# From PyPI
pip install lcm-tools
# From source (development)
git clone https://github.com/your-username/lcm-tools.git
cd lcm-tools
pip install -e .
# Optional: traditional lcm-gen Python package decode support
pip install lcm-tools[decode]
Requirements: Python >= 3.9, typer, rich (lcm package is optional, only for legacy --type module.Class decoding).
Quick Start
# Show all subcommands
lcm --help
# List active channels (listens for 5 seconds)
lcm topic list
# View messages on a channel (raw hex format)
lcm topic echo EXAMPLE
# Receive only 10 messages
lcm topic echo EXAMPLE -n 10
# Match multiple channels with regex
lcm topic echo "CAM.*"
# Monitor real-time statistics for all channels
lcm topic stats
# Monitor a specific channel only
lcm topic stats CAMERA
# List discovered publisher nodes
lcm node list
Message Decoding
Method 1: Specify .lcm files directly (recommended)
No lcm-gen installation, no PYTHONPATH configuration. The tool includes a built-in pure-Python parser:
# Specify a single .lcm file — auto-matches message type by fingerprint
lcm topic echo EXAMPLE --lcm-file types/example_t.lcm
# Specify a directory (recursively scans all .lcm files)
lcm topic echo EXAMPLE -f types/
# Specify multiple paths
lcm topic echo EXAMPLE -f types/ -f extra_types/
# Specify a concrete type name (when .lcm files contain multiple structs)
lcm topic echo EXAMPLE -f types/ --type example_t
Supports the complete LCM type system:
- All primitive types (
int8_t~int64_t,float,double,string,boolean,byte) - Fixed-length and variable-length arrays (
double position[3],int16_t ranges[num_ranges]) - Multi-dimensional arrays (
int32_t data[size_a][size_b][size_c]) - Nested structs and cross-file type references
- Recursive types (e.g.,
node_t children[n]in a linked-listnode_t) - Constant declarations (
const int32_t MAX_SIZE = 100)
How it works: Parses .lcm files → builds decode classes in memory (type() dynamic creation) → auto-matches by the first 8-byte fingerprint of the payload → decodes and recursively expands nested structs. No files are generated at any point.
Method 2: Traditional lcm-gen generated files
# Install the lcm Python package
pip install lcm-tools[decode]
# Generate Python files with lcm-gen, then configure PYTHONPATH
lcm-gen --python -d types/ types/example_t.lcm
export PYTHONPATH=types:$PYTHONPATH
# Use --type to specify the decode class (module.Class format)
lcm topic echo EXAMPLE --type exlcm.example_t
Custom Multicast Address
lcm topic list --lcm-url 239.255.76.68 --lcm-port 7668
Statistics
| Metric | Description |
|---|---|
| Rate (Hz) | Message frequency within a sliding window (last 2000 messages) |
| BW (KB/s) | Bandwidth within the sliding window |
| Avg Size (B) | Average bytes per message |
| Total (KB) | Cumulative total transferred |
Architecture
┌───────────────────────────────────────────────────┐
│ CLI Layer (Typer) │
│ topic echo │ topic list │ topic stats │ node │
├───────────────────────────────────────────────────┤
│ Display Layer (Rich Panel) │
│ recursive nesting │ hex dump │ stats table │
├───────────────────────────────────────────────────┤
│ Type Parsing Layer (Pure Python) │
│ .lcm parse → AST → fingerprint → dynamic class │
├───────────────────────────────────────────────────┤
│ Protocol Layer (Raw UDP Socket) │
│ LCM Wire Protocol parsing (zero deps) │
├───────────────────────────────────────────────────┤
│ UDP Multicast (239.255.76.67) │
└───────────────────────────────────────────────────┘
- Zero external LCM dependency: Core functionality directly parses the LCM wire protocol from UDP multicast packets
- Built-in type parsing: Pure-Python
.lcmfile parser + runtime decode class generator - Node discovery: Infers different publishers from UDP packet source IP:port
- Legacy decode compatible: Optional
lcmPython package for--type module.Classdecoding
LCM Protocol
LCM uses UDP multicast for communication (default 239.255.76.67:7667).
Short messages (< 64KB): 8-byte header (magic=0x4c433032 + seqno) + channel name (null-terminated) + payload
Fragmented messages: 20-byte header (magic=0x4c433033 + seqno + payload_size + fragment_offset + fragment_no + n_fragments)
Reference: LCM UDP Multicast Protocol
LCM vs ROS2 Concepts
| LCM Concept | ROS2 Equivalent | Description |
|---|---|---|
| Channel | Topic | Message publish/subscribe conduit |
| UDP (IP:port) | Node | LCM has no native node concept; inferred from publisher address |
| Fingerprint | Message Type Hash | Unique identifier for a message type |
Project Structure
src/lcm_tools/
├── cli.py # Typer entry point, registers subcommands
├── commands/
│ ├── topic_echo.py # lcm topic echo
│ ├── topic_list.py # lcm topic list
│ ├── topic_stats.py # lcm topic stats
│ └── node_list.py # lcm node list
├── core/
│ ├── discovery.py # Passive channel/node discovery
│ ├── stats.py # Real-time statistics (rate, bandwidth)
│ ├── lcm_type_parser.py # .lcm file parser + fingerprint algorithm
│ └── lcm_type_builder.py # Runtime decode class generation + TypeRegistry
├── display/
│ ├── echo_display.py # Rich panel display (with recursive nesting)
│ └── stats_display.py # Statistics table display
├── listener.py # UDP multicast listener thread
└── protocol.py # LCM Wire Protocol parser
Testing
pip install -e ".[dev]"
pytest tests/ -v
Network Configuration
If you can't receive messages, check your multicast routing:
macOS:
# View multicast routes
netstat -rn | grep 239
# Add route if needed
sudo route add -net 239.255.76.0/24 -interface en0
Linux:
# Add route
sudo ip route add 239.255.76.0/24 dev eth0
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file lcm_cli-0.1.0.tar.gz.
File metadata
- Download URL: lcm_cli-0.1.0.tar.gz
- Upload date:
- Size: 37.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
31e20f2470ba462218a28edb6be52f89a5e152949e7e4db8e97dc59f97dde83a
|
|
| MD5 |
a143eb1d186b3997778c5f853b8aab1e
|
|
| BLAKE2b-256 |
a6d6ca27ffc67545c64bff6ba39d6a09e3917e0bd64747b3e0082e1c3e8ed939
|
File details
Details for the file lcm_cli-0.1.0-py3-none-any.whl.
File metadata
- Download URL: lcm_cli-0.1.0-py3-none-any.whl
- Upload date:
- Size: 33.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
268ab2ae37f77f0e8ca781b7a85ef6413fed92eb033ae2526bd5d422d0feea58
|
|
| MD5 |
145949a942d9c9334e99c634717b7494
|
|
| BLAKE2b-256 |
6745c438307fe113424db2ce2c249210fb2ad064cf80262eefd904bce0192a96
|