lcm-cli 0.1.0__tar.gz → 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lcm_cli-0.2.0/.github/workflows/ci.yml +104 -0
- lcm_cli-0.2.0/.gitignore +59 -0
- {lcm_cli-0.1.0 → lcm_cli-0.2.0}/LICENSE +1 -1
- {lcm_cli-0.1.0 → lcm_cli-0.2.0}/PKG-INFO +154 -27
- {lcm_cli-0.1.0 → lcm_cli-0.2.0}/README.md +142 -20
- {lcm_cli-0.1.0 → lcm_cli-0.2.0}/README_zh.md +145 -19
- {lcm_cli-0.1.0 → lcm_cli-0.2.0}/pyproject.toml +14 -9
- lcm_cli-0.2.0/src/lcm_cli/__init__.py +3 -0
- lcm_cli-0.2.0/src/lcm_cli/__main__.py +8 -0
- lcm_cli-0.2.0/src/lcm_cli/cli.py +92 -0
- lcm_cli-0.2.0/src/lcm_cli/commands/node_list.py +133 -0
- lcm_cli-0.2.0/src/lcm_cli/commands/play.py +94 -0
- lcm_cli-0.2.0/src/lcm_cli/commands/record.py +131 -0
- lcm_cli-0.2.0/src/lcm_cli/commands/topic_bw.py +57 -0
- lcm_cli-0.2.0/src/lcm_cli/commands/topic_echo.py +334 -0
- lcm_cli-0.2.0/src/lcm_cli/commands/topic_info.py +142 -0
- lcm_cli-0.2.0/src/lcm_cli/commands/topic_list.py +119 -0
- lcm_cli-0.2.0/src/lcm_cli/commands/topic_stats.py +151 -0
- lcm_cli-0.2.0/src/lcm_cli/commands/type_list.py +40 -0
- lcm_cli-0.2.0/src/lcm_cli/commands/type_show.py +51 -0
- {lcm_cli-0.1.0/src/lcm_tools → lcm_cli-0.2.0/src/lcm_cli}/core/discovery.py +5 -4
- {lcm_cli-0.1.0/src/lcm_tools → lcm_cli-0.2.0/src/lcm_cli}/core/lcm_type_builder.py +11 -9
- {lcm_cli-0.1.0/src/lcm_tools → lcm_cli-0.2.0/src/lcm_cli}/core/lcm_type_parser.py +2 -0
- {lcm_cli-0.1.0/src/lcm_tools → lcm_cli-0.2.0/src/lcm_cli}/core/stats.py +62 -22
- {lcm_cli-0.1.0/src/lcm_tools → lcm_cli-0.2.0/src/lcm_cli}/display/echo_display.py +5 -4
- lcm_cli-0.2.0/src/lcm_cli/display/stats_display.py +211 -0
- lcm_cli-0.2.0/src/lcm_cli/display/type_display.py +100 -0
- lcm_cli-0.2.0/src/lcm_cli/export.py +295 -0
- lcm_cli-0.2.0/src/lcm_cli/lcm_log.py +106 -0
- {lcm_cli-0.1.0/src/lcm_tools → lcm_cli-0.2.0/src/lcm_cli}/listener.py +3 -1
- {lcm_cli-0.1.0/src/lcm_tools → lcm_cli-0.2.0/src/lcm_cli}/protocol.py +2 -0
- lcm_cli-0.2.0/src/lcm_cli/source.py +150 -0
- lcm_cli-0.2.0/tests/__init__.py +1 -0
- lcm_cli-0.2.0/tests/conftest.py +1 -0
- {lcm_cli-0.1.0 → lcm_cli-0.2.0}/tests/helpers.py +2 -2
- {lcm_cli-0.1.0 → lcm_cli-0.2.0}/tests/test_echo_display.py +2 -2
- lcm_cli-0.2.0/tests/test_export.py +173 -0
- lcm_cli-0.2.0/tests/test_lcm_log.py +79 -0
- {lcm_cli-0.1.0 → lcm_cli-0.2.0}/tests/test_lcm_type_builder.py +16 -2
- {lcm_cli-0.1.0 → lcm_cli-0.2.0}/tests/test_lcm_type_parser.py +11 -6
- lcm_cli-0.2.0/tests/test_new_commands.py +314 -0
- lcm_cli-0.2.0/tests/test_play.py +84 -0
- {lcm_cli-0.1.0 → lcm_cli-0.2.0}/tests/test_protocol.py +2 -4
- lcm_cli-0.2.0/tests/test_record.py +93 -0
- lcm_cli-0.2.0/tests/test_source.py +99 -0
- {lcm_cli-0.1.0 → lcm_cli-0.2.0}/tests/test_stats.py +58 -5
- lcm_cli-0.1.0/.gitignore +0 -33
- lcm_cli-0.1.0/src/lcm_tools/__init__.py +0 -3
- lcm_cli-0.1.0/src/lcm_tools/__main__.py +0 -6
- lcm_cli-0.1.0/src/lcm_tools/cli.py +0 -52
- lcm_cli-0.1.0/src/lcm_tools/commands/node_list.py +0 -82
- lcm_cli-0.1.0/src/lcm_tools/commands/topic_echo.py +0 -188
- lcm_cli-0.1.0/src/lcm_tools/commands/topic_list.py +0 -69
- lcm_cli-0.1.0/src/lcm_tools/commands/topic_stats.py +0 -87
- lcm_cli-0.1.0/src/lcm_tools/display/stats_display.py +0 -103
- lcm_cli-0.1.0/tests/__init__.py +0 -1
- lcm_cli-0.1.0/tests/conftest.py +0 -1
- {lcm_cli-0.1.0/src/lcm_tools → lcm_cli-0.2.0/src/lcm_cli}/commands/__init__.py +0 -0
- {lcm_cli-0.1.0/src/lcm_tools → lcm_cli-0.2.0/src/lcm_cli}/core/__init__.py +0 -0
- {lcm_cli-0.1.0/src/lcm_tools → lcm_cli-0.2.0/src/lcm_cli}/display/__init__.py +0 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
tags:
|
|
7
|
+
- 'v*'
|
|
8
|
+
pull_request:
|
|
9
|
+
branches: [main]
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
test:
|
|
13
|
+
name: Test (Python ${{ matrix.python-version }}, ${{ matrix.os }})
|
|
14
|
+
runs-on: ${{ matrix.os }}
|
|
15
|
+
strategy:
|
|
16
|
+
fail-fast: false
|
|
17
|
+
matrix:
|
|
18
|
+
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
|
|
19
|
+
os: [ubuntu-latest, macOS-latest]
|
|
20
|
+
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@v4
|
|
23
|
+
|
|
24
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
25
|
+
uses: actions/setup-python@v5
|
|
26
|
+
with:
|
|
27
|
+
python-version: ${{ matrix.python-version }}
|
|
28
|
+
cache: 'pip'
|
|
29
|
+
|
|
30
|
+
- name: Install dependencies
|
|
31
|
+
run: |
|
|
32
|
+
python -m pip install --upgrade pip
|
|
33
|
+
pip install -e ".[dev]"
|
|
34
|
+
|
|
35
|
+
- name: Lint with Ruff
|
|
36
|
+
run: |
|
|
37
|
+
ruff check src/lcm_cli tests
|
|
38
|
+
|
|
39
|
+
- name: Type check with mypy
|
|
40
|
+
run: |
|
|
41
|
+
mypy src/lcm_cli --ignore-missing-imports
|
|
42
|
+
|
|
43
|
+
- name: Run tests
|
|
44
|
+
run: |
|
|
45
|
+
pytest tests/ -v --cov=lcm_cli --cov-report=xml
|
|
46
|
+
|
|
47
|
+
- name: Upload coverage to Codecov
|
|
48
|
+
if: matrix.python-version == '3.12' && matrix.os == 'ubuntu-latest'
|
|
49
|
+
uses: codecov/codecov-action@v4
|
|
50
|
+
with:
|
|
51
|
+
file: ./coverage.xml
|
|
52
|
+
fail_ci_if_error: false
|
|
53
|
+
|
|
54
|
+
build:
|
|
55
|
+
name: Build distribution
|
|
56
|
+
needs: test
|
|
57
|
+
runs-on: ubuntu-latest
|
|
58
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
59
|
+
|
|
60
|
+
steps:
|
|
61
|
+
- uses: actions/checkout@v4
|
|
62
|
+
|
|
63
|
+
- name: Set up Python
|
|
64
|
+
uses: actions/setup-python@v5
|
|
65
|
+
with:
|
|
66
|
+
python-version: '3.12'
|
|
67
|
+
|
|
68
|
+
- name: Install build tools
|
|
69
|
+
run: |
|
|
70
|
+
pip install build twine
|
|
71
|
+
|
|
72
|
+
- name: Build package
|
|
73
|
+
run: |
|
|
74
|
+
python -m build
|
|
75
|
+
|
|
76
|
+
- name: Check package
|
|
77
|
+
run: |
|
|
78
|
+
twine check dist/*
|
|
79
|
+
|
|
80
|
+
- name: Upload dist
|
|
81
|
+
uses: actions/upload-artifact@v4
|
|
82
|
+
with:
|
|
83
|
+
name: dist
|
|
84
|
+
path: dist/
|
|
85
|
+
|
|
86
|
+
publish:
|
|
87
|
+
name: Publish to PyPI
|
|
88
|
+
needs: build
|
|
89
|
+
runs-on: ubuntu-latest
|
|
90
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
91
|
+
environment:
|
|
92
|
+
name: pypi
|
|
93
|
+
url: https://pypi.org/p/lcm-cli
|
|
94
|
+
permissions:
|
|
95
|
+
id-token: write
|
|
96
|
+
|
|
97
|
+
steps:
|
|
98
|
+
- uses: actions/download-artifact@v4
|
|
99
|
+
with:
|
|
100
|
+
name: dist
|
|
101
|
+
path: dist/
|
|
102
|
+
|
|
103
|
+
- name: Publish to PyPI
|
|
104
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
lcm_cli-0.2.0/.gitignore
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Byte-compiled / cache
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
*.egg
|
|
6
|
+
|
|
7
|
+
# Distribution / packaging
|
|
8
|
+
dist/
|
|
9
|
+
build/
|
|
10
|
+
*.tar.gz
|
|
11
|
+
*.whl
|
|
12
|
+
|
|
13
|
+
# Tests & coverage
|
|
14
|
+
.pytest_cache/
|
|
15
|
+
htmlcov/
|
|
16
|
+
.coverage
|
|
17
|
+
coverage.xml
|
|
18
|
+
|
|
19
|
+
# Type checking
|
|
20
|
+
.mypy_cache/
|
|
21
|
+
|
|
22
|
+
# Linting
|
|
23
|
+
.ruff_cache/
|
|
24
|
+
|
|
25
|
+
# IDE
|
|
26
|
+
.vscode/
|
|
27
|
+
.idea/
|
|
28
|
+
*.swp
|
|
29
|
+
*.swo
|
|
30
|
+
*~
|
|
31
|
+
|
|
32
|
+
# LCM reference repo (not part of this project)
|
|
33
|
+
lcm_ref/
|
|
34
|
+
|
|
35
|
+
# lcm-gen generated Python types
|
|
36
|
+
gen_types/
|
|
37
|
+
|
|
38
|
+
# Test LCM types (sample files)
|
|
39
|
+
test_lcm_types/
|
|
40
|
+
|
|
41
|
+
# Virtual environments
|
|
42
|
+
venv/
|
|
43
|
+
.venv-build/
|
|
44
|
+
.env/
|
|
45
|
+
|
|
46
|
+
# OS files
|
|
47
|
+
.DS_Store
|
|
48
|
+
Thumbs.db
|
|
49
|
+
|
|
50
|
+
# Logs
|
|
51
|
+
*.log
|
|
52
|
+
|
|
53
|
+
# Development scripts and internal docs
|
|
54
|
+
scripts/
|
|
55
|
+
docs/superpowers/
|
|
56
|
+
|
|
57
|
+
# Temporary files
|
|
58
|
+
tmp/
|
|
59
|
+
temp/
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lcm-cli
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary:
|
|
5
|
-
Project-URL: Homepage, https://github.com/
|
|
6
|
-
Project-URL: Repository, https://github.com/
|
|
7
|
-
Project-URL: Issues, https://github.com/
|
|
8
|
-
Author: lcm-
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Command line tools for monitoring and debugging LCM (Lightweight Communications and Marshalling)
|
|
5
|
+
Project-URL: Homepage, https://github.com/Joyserr/lcm-cli
|
|
6
|
+
Project-URL: Repository, https://github.com/Joyserr/lcm-cli
|
|
7
|
+
Project-URL: Issues, https://github.com/Joyserr/lcm-cli/issues
|
|
8
|
+
Author: lcm-cli contributors
|
|
9
9
|
License-Expression: MIT
|
|
10
10
|
License-File: LICENSE
|
|
11
|
-
Keywords: cli,debugging,lcm,middleware,multicast,robotics
|
|
11
|
+
Keywords: cli,debugging,lcm,middleware,multicast,robotics
|
|
12
12
|
Classifier: Development Status :: 4 - Beta
|
|
13
13
|
Classifier: Environment :: Console
|
|
14
14
|
Classifier: Intended Audience :: Developers
|
|
@@ -33,40 +33,56 @@ Requires-Dist: typer>=0.12.0
|
|
|
33
33
|
Provides-Extra: decode
|
|
34
34
|
Requires-Dist: lcm>=1.5.0; extra == 'decode'
|
|
35
35
|
Provides-Extra: dev
|
|
36
|
+
Requires-Dist: build>=0.10; extra == 'dev'
|
|
37
|
+
Requires-Dist: mypy>=1.0; extra == 'dev'
|
|
38
|
+
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
|
|
36
39
|
Requires-Dist: pytest-timeout>=2.1; extra == 'dev'
|
|
37
40
|
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
41
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
42
|
+
Requires-Dist: twine>=4.0; extra == 'dev'
|
|
38
43
|
Description-Content-Type: text/markdown
|
|
39
44
|
|
|
40
45
|
# LCM CLI Tools
|
|
41
46
|
|
|
42
47
|
**[English](README.md)** | [中文](README_zh.md)
|
|
43
48
|
|
|
44
|
-
>
|
|
49
|
+
> Command line tools for monitoring and debugging LCM (Lightweight Communications and Marshalling) networks.
|
|
45
50
|
|
|
46
51
|
## Features
|
|
47
52
|
|
|
48
53
|
```
|
|
49
|
-
lcm topic echo <channel> — View real-time topic data
|
|
50
|
-
lcm topic list — List active topics/channels
|
|
51
|
-
lcm topic stats — Real-time topic stats: rate, bandwidth, msg count
|
|
52
|
-
lcm
|
|
54
|
+
lcm topic echo <channel> — View real-time topic data
|
|
55
|
+
lcm topic list — List active topics/channels
|
|
56
|
+
lcm topic stats — Real-time topic stats: rate, bandwidth, msg count
|
|
57
|
+
lcm topic bw <channel> — Monitor bandwidth for a single channel with sparkline graph
|
|
58
|
+
lcm topic info <channel> — Detailed channel information with type structure
|
|
59
|
+
lcm node list — List discovered publisher nodes
|
|
60
|
+
lcm type list — List all registered LCM types
|
|
61
|
+
lcm type show <type> — Show type field structure
|
|
62
|
+
lcm record — Record live LCM traffic to .log file
|
|
63
|
+
lcm play <file.log> — Replay .log file to multicast
|
|
53
64
|
```
|
|
54
65
|
|
|
55
|
-
**
|
|
66
|
+
**Highlights**:
|
|
67
|
+
- Built-in pure-Python `.lcm` file parser — no `lcm-gen` or `PYTHONPATH` needed
|
|
68
|
+
- **Message Export**: CSV/JSONL export with field extraction (`--csv`, `--jsonl`, `--field`)
|
|
69
|
+
- **Advanced Monitoring**: Sort/filter stats (`--sort`, `--top`, `--freeze`, `--spark`)
|
|
70
|
+
- **Live Watch Mode**: Continuous refresh for topic/node list (`--watch`)
|
|
71
|
+
- **Recording & Playback**: Full log file support compatible with `lcm-logger`
|
|
56
72
|
|
|
57
73
|
## Installation
|
|
58
74
|
|
|
59
75
|
```bash
|
|
60
76
|
# From PyPI
|
|
61
|
-
pip install lcm-
|
|
77
|
+
pip install lcm-cli
|
|
62
78
|
|
|
63
79
|
# From source (development)
|
|
64
|
-
git clone https://github.com/
|
|
65
|
-
cd lcm-
|
|
80
|
+
git clone https://github.com/Joyserr/lcm-cli.git
|
|
81
|
+
cd lcm-cli
|
|
66
82
|
pip install -e .
|
|
67
83
|
|
|
68
84
|
# Optional: traditional lcm-gen Python package decode support
|
|
69
|
-
pip install lcm-
|
|
85
|
+
pip install lcm-cli[decode]
|
|
70
86
|
```
|
|
71
87
|
|
|
72
88
|
**Requirements**: Python >= 3.9, `typer`, `rich` (`lcm` package is optional, only for legacy `--type module.Class` decoding).
|
|
@@ -77,9 +93,15 @@ pip install lcm-tools[decode]
|
|
|
77
93
|
# Show all subcommands
|
|
78
94
|
lcm --help
|
|
79
95
|
|
|
96
|
+
# Show version
|
|
97
|
+
lcm --version
|
|
98
|
+
|
|
80
99
|
# List active channels (listens for 5 seconds)
|
|
81
100
|
lcm topic list
|
|
82
101
|
|
|
102
|
+
# Continuous watch mode (live refresh)
|
|
103
|
+
lcm topic list --watch
|
|
104
|
+
|
|
83
105
|
# View messages on a channel (raw hex format)
|
|
84
106
|
lcm topic echo EXAMPLE
|
|
85
107
|
|
|
@@ -92,15 +114,106 @@ lcm topic echo "CAM.*"
|
|
|
92
114
|
# Monitor real-time statistics for all channels
|
|
93
115
|
lcm topic stats
|
|
94
116
|
|
|
95
|
-
#
|
|
96
|
-
lcm topic stats
|
|
117
|
+
# Sort by bandwidth, show top 5
|
|
118
|
+
lcm topic stats --sort bw --top 5
|
|
119
|
+
|
|
120
|
+
# Freeze mode (single snapshot)
|
|
121
|
+
lcm topic stats --freeze
|
|
122
|
+
|
|
123
|
+
# Monitor bandwidth with sparkline graph
|
|
124
|
+
lcm topic bw CAMERA --spark
|
|
125
|
+
|
|
126
|
+
# Detailed channel information
|
|
127
|
+
lcm topic info CAMERA --lcm-file types/
|
|
97
128
|
|
|
98
129
|
# List discovered publisher nodes
|
|
99
130
|
lcm node list
|
|
100
131
|
```
|
|
101
132
|
|
|
133
|
+
## Recording & Playback
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
# Record all channels to a .log file
|
|
137
|
+
lcm record
|
|
138
|
+
|
|
139
|
+
# Record specific channels with regex
|
|
140
|
+
lcm record --channel "CAM.*" -o camera.log
|
|
141
|
+
|
|
142
|
+
# Record for a fixed duration
|
|
143
|
+
lcm record -d 60 # 60 seconds
|
|
144
|
+
|
|
145
|
+
# Replay a .log file
|
|
146
|
+
lcm play camera.log
|
|
147
|
+
|
|
148
|
+
# Replay at 2x speed
|
|
149
|
+
lcm play camera.log --speed 2.0
|
|
150
|
+
|
|
151
|
+
# Loop playback
|
|
152
|
+
lcm play camera.log --loop
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Message Export
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
# Export to CSV (headers auto-determined from first message)
|
|
159
|
+
lcm topic echo EXAMPLE --csv output.csv
|
|
160
|
+
|
|
161
|
+
# Export to JSON Lines
|
|
162
|
+
lcm topic echo EXAMPLE --jsonl output.jsonl
|
|
163
|
+
|
|
164
|
+
# Extract specific fields
|
|
165
|
+
lcm topic echo EXAMPLE --field position --field velocity --csv data.csv
|
|
166
|
+
|
|
167
|
+
# Extract nested fields
|
|
168
|
+
lcm topic echo EXAMPLE --field imu.accel.x --field imu.gyro.y
|
|
169
|
+
|
|
170
|
+
# Extract array slices
|
|
171
|
+
lcm topic echo EXAMPLE --field "position[0:2]"
|
|
172
|
+
|
|
173
|
+
# Custom timestamp format
|
|
174
|
+
lcm topic echo EXAMPLE --csv data.csv --ts-format iso
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Advanced Statistics
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
# Sort channels by message rate
|
|
181
|
+
lcm topic stats --sort rate
|
|
182
|
+
|
|
183
|
+
# Show top 10 channels by bandwidth
|
|
184
|
+
lcm topic stats --sort bw --top 10
|
|
185
|
+
|
|
186
|
+
# Single snapshot (non-interactive)
|
|
187
|
+
lcm topic stats --freeze
|
|
188
|
+
|
|
189
|
+
# Add sparkline trend visualization
|
|
190
|
+
lcm topic stats --spark
|
|
191
|
+
|
|
192
|
+
# Monitor bandwidth for a single channel
|
|
193
|
+
lcm topic bw CAMERA --window 10 --spark
|
|
194
|
+
|
|
195
|
+
# Read stats from log file
|
|
196
|
+
lcm topic stats --from recording.log
|
|
197
|
+
```
|
|
198
|
+
|
|
102
199
|
## Message Decoding
|
|
103
200
|
|
|
201
|
+
### Type Diagnostics
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
# List all registered types
|
|
205
|
+
lcm type list
|
|
206
|
+
|
|
207
|
+
# Filter by package
|
|
208
|
+
lcm type list --package exlcm
|
|
209
|
+
|
|
210
|
+
# Show type structure
|
|
211
|
+
lcm type show example_t --lcm-file types/
|
|
212
|
+
|
|
213
|
+
# Grep search types
|
|
214
|
+
lcm type list --grep "sensor"
|
|
215
|
+
```
|
|
216
|
+
|
|
104
217
|
### Method 1: Specify `.lcm` files directly (recommended)
|
|
105
218
|
|
|
106
219
|
No `lcm-gen` installation, no `PYTHONPATH` configuration. The tool includes a built-in pure-Python parser:
|
|
@@ -133,7 +246,7 @@ Supports the complete LCM type system:
|
|
|
133
246
|
|
|
134
247
|
```bash
|
|
135
248
|
# Install the lcm Python package
|
|
136
|
-
pip install lcm-
|
|
249
|
+
pip install lcm-cli[decode]
|
|
137
250
|
|
|
138
251
|
# Generate Python files with lcm-gen, then configure PYTHONPATH
|
|
139
252
|
lcm-gen --python -d types/ types/example_t.lcm
|
|
@@ -195,6 +308,8 @@ Reference: [LCM UDP Multicast Protocol](https://lcm-proj.github.io/lcm/content/u
|
|
|
195
308
|
|
|
196
309
|
## LCM vs ROS2 Concepts
|
|
197
310
|
|
|
311
|
+
LCM and ROS2 share similar pub/sub communication patterns. Here's a concept mapping:
|
|
312
|
+
|
|
198
313
|
| LCM Concept | ROS2 Equivalent | Description |
|
|
199
314
|
|-------------|----------------|-------------|
|
|
200
315
|
| Channel | Topic | Message publish/subscribe conduit |
|
|
@@ -204,13 +319,21 @@ Reference: [LCM UDP Multicast Protocol](https://lcm-proj.github.io/lcm/content/u
|
|
|
204
319
|
## Project Structure
|
|
205
320
|
|
|
206
321
|
```
|
|
207
|
-
src/
|
|
322
|
+
src/lcm_cli/
|
|
323
|
+
├── __init__.py # Package definition + version
|
|
324
|
+
├── __main__.py # python -m lcm_cli entry point
|
|
208
325
|
├── cli.py # Typer entry point, registers subcommands
|
|
209
326
|
├── commands/
|
|
210
|
-
│ ├── topic_echo.py # lcm topic echo
|
|
211
|
-
│ ├── topic_list.py # lcm topic list
|
|
212
|
-
│ ├── topic_stats.py # lcm topic stats
|
|
213
|
-
│
|
|
327
|
+
│ ├── topic_echo.py # lcm topic echo (with --csv/--jsonl export)
|
|
328
|
+
│ ├── topic_list.py # lcm topic list (with --watch mode)
|
|
329
|
+
│ ├── topic_stats.py # lcm topic stats (with --sort/--top/--freeze)
|
|
330
|
+
│ ├── topic_bw.py # lcm topic bw (bandwidth monitor)
|
|
331
|
+
│ ├── topic_info.py # lcm topic info (channel details)
|
|
332
|
+
│ ├── node_list.py # lcm node list (with --watch mode)
|
|
333
|
+
│ ├── type_list.py # lcm type list
|
|
334
|
+
│ ├── type_show.py # lcm type show
|
|
335
|
+
│ ├── record.py # lcm record
|
|
336
|
+
│ └── play.py # lcm play
|
|
214
337
|
├── core/
|
|
215
338
|
│ ├── discovery.py # Passive channel/node discovery
|
|
216
339
|
│ ├── stats.py # Real-time statistics (rate, bandwidth)
|
|
@@ -218,9 +341,13 @@ src/lcm_tools/
|
|
|
218
341
|
│ └── lcm_type_builder.py # Runtime decode class generation + TypeRegistry
|
|
219
342
|
├── display/
|
|
220
343
|
│ ├── echo_display.py # Rich panel display (with recursive nesting)
|
|
221
|
-
│
|
|
344
|
+
│ ├── stats_display.py # Statistics table display (with sparkline)
|
|
345
|
+
│ └── type_display.py # Type structure table display
|
|
346
|
+
├── export.py # Field extraction + CSV/JSONL writers
|
|
347
|
+
├── lcm_log.py # LCM log file reader/writer (lcm-logger compatible)
|
|
222
348
|
├── listener.py # UDP multicast listener thread
|
|
223
|
-
|
|
349
|
+
├── protocol.py # LCM Wire Protocol parser
|
|
350
|
+
└── source.py # PacketSource abstraction (live/offline)
|
|
224
351
|
```
|
|
225
352
|
|
|
226
353
|
## Testing
|
|
@@ -2,32 +2,43 @@
|
|
|
2
2
|
|
|
3
3
|
**[English](README.md)** | [中文](README_zh.md)
|
|
4
4
|
|
|
5
|
-
>
|
|
5
|
+
> Command line tools for monitoring and debugging LCM (Lightweight Communications and Marshalling) networks.
|
|
6
6
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
9
9
|
```
|
|
10
|
-
lcm topic echo <channel> — View real-time topic data
|
|
11
|
-
lcm topic list — List active topics/channels
|
|
12
|
-
lcm topic stats — Real-time topic stats: rate, bandwidth, msg count
|
|
13
|
-
lcm
|
|
10
|
+
lcm topic echo <channel> — View real-time topic data
|
|
11
|
+
lcm topic list — List active topics/channels
|
|
12
|
+
lcm topic stats — Real-time topic stats: rate, bandwidth, msg count
|
|
13
|
+
lcm topic bw <channel> — Monitor bandwidth for a single channel with sparkline graph
|
|
14
|
+
lcm topic info <channel> — Detailed channel information with type structure
|
|
15
|
+
lcm node list — List discovered publisher nodes
|
|
16
|
+
lcm type list — List all registered LCM types
|
|
17
|
+
lcm type show <type> — Show type field structure
|
|
18
|
+
lcm record — Record live LCM traffic to .log file
|
|
19
|
+
lcm play <file.log> — Replay .log file to multicast
|
|
14
20
|
```
|
|
15
21
|
|
|
16
|
-
**
|
|
22
|
+
**Highlights**:
|
|
23
|
+
- Built-in pure-Python `.lcm` file parser — no `lcm-gen` or `PYTHONPATH` needed
|
|
24
|
+
- **Message Export**: CSV/JSONL export with field extraction (`--csv`, `--jsonl`, `--field`)
|
|
25
|
+
- **Advanced Monitoring**: Sort/filter stats (`--sort`, `--top`, `--freeze`, `--spark`)
|
|
26
|
+
- **Live Watch Mode**: Continuous refresh for topic/node list (`--watch`)
|
|
27
|
+
- **Recording & Playback**: Full log file support compatible with `lcm-logger`
|
|
17
28
|
|
|
18
29
|
## Installation
|
|
19
30
|
|
|
20
31
|
```bash
|
|
21
32
|
# From PyPI
|
|
22
|
-
pip install lcm-
|
|
33
|
+
pip install lcm-cli
|
|
23
34
|
|
|
24
35
|
# From source (development)
|
|
25
|
-
git clone https://github.com/
|
|
26
|
-
cd lcm-
|
|
36
|
+
git clone https://github.com/Joyserr/lcm-cli.git
|
|
37
|
+
cd lcm-cli
|
|
27
38
|
pip install -e .
|
|
28
39
|
|
|
29
40
|
# Optional: traditional lcm-gen Python package decode support
|
|
30
|
-
pip install lcm-
|
|
41
|
+
pip install lcm-cli[decode]
|
|
31
42
|
```
|
|
32
43
|
|
|
33
44
|
**Requirements**: Python >= 3.9, `typer`, `rich` (`lcm` package is optional, only for legacy `--type module.Class` decoding).
|
|
@@ -38,9 +49,15 @@ pip install lcm-tools[decode]
|
|
|
38
49
|
# Show all subcommands
|
|
39
50
|
lcm --help
|
|
40
51
|
|
|
52
|
+
# Show version
|
|
53
|
+
lcm --version
|
|
54
|
+
|
|
41
55
|
# List active channels (listens for 5 seconds)
|
|
42
56
|
lcm topic list
|
|
43
57
|
|
|
58
|
+
# Continuous watch mode (live refresh)
|
|
59
|
+
lcm topic list --watch
|
|
60
|
+
|
|
44
61
|
# View messages on a channel (raw hex format)
|
|
45
62
|
lcm topic echo EXAMPLE
|
|
46
63
|
|
|
@@ -53,15 +70,106 @@ lcm topic echo "CAM.*"
|
|
|
53
70
|
# Monitor real-time statistics for all channels
|
|
54
71
|
lcm topic stats
|
|
55
72
|
|
|
56
|
-
#
|
|
57
|
-
lcm topic stats
|
|
73
|
+
# Sort by bandwidth, show top 5
|
|
74
|
+
lcm topic stats --sort bw --top 5
|
|
75
|
+
|
|
76
|
+
# Freeze mode (single snapshot)
|
|
77
|
+
lcm topic stats --freeze
|
|
78
|
+
|
|
79
|
+
# Monitor bandwidth with sparkline graph
|
|
80
|
+
lcm topic bw CAMERA --spark
|
|
81
|
+
|
|
82
|
+
# Detailed channel information
|
|
83
|
+
lcm topic info CAMERA --lcm-file types/
|
|
58
84
|
|
|
59
85
|
# List discovered publisher nodes
|
|
60
86
|
lcm node list
|
|
61
87
|
```
|
|
62
88
|
|
|
89
|
+
## Recording & Playback
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
# Record all channels to a .log file
|
|
93
|
+
lcm record
|
|
94
|
+
|
|
95
|
+
# Record specific channels with regex
|
|
96
|
+
lcm record --channel "CAM.*" -o camera.log
|
|
97
|
+
|
|
98
|
+
# Record for a fixed duration
|
|
99
|
+
lcm record -d 60 # 60 seconds
|
|
100
|
+
|
|
101
|
+
# Replay a .log file
|
|
102
|
+
lcm play camera.log
|
|
103
|
+
|
|
104
|
+
# Replay at 2x speed
|
|
105
|
+
lcm play camera.log --speed 2.0
|
|
106
|
+
|
|
107
|
+
# Loop playback
|
|
108
|
+
lcm play camera.log --loop
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Message Export
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
# Export to CSV (headers auto-determined from first message)
|
|
115
|
+
lcm topic echo EXAMPLE --csv output.csv
|
|
116
|
+
|
|
117
|
+
# Export to JSON Lines
|
|
118
|
+
lcm topic echo EXAMPLE --jsonl output.jsonl
|
|
119
|
+
|
|
120
|
+
# Extract specific fields
|
|
121
|
+
lcm topic echo EXAMPLE --field position --field velocity --csv data.csv
|
|
122
|
+
|
|
123
|
+
# Extract nested fields
|
|
124
|
+
lcm topic echo EXAMPLE --field imu.accel.x --field imu.gyro.y
|
|
125
|
+
|
|
126
|
+
# Extract array slices
|
|
127
|
+
lcm topic echo EXAMPLE --field "position[0:2]"
|
|
128
|
+
|
|
129
|
+
# Custom timestamp format
|
|
130
|
+
lcm topic echo EXAMPLE --csv data.csv --ts-format iso
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Advanced Statistics
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
# Sort channels by message rate
|
|
137
|
+
lcm topic stats --sort rate
|
|
138
|
+
|
|
139
|
+
# Show top 10 channels by bandwidth
|
|
140
|
+
lcm topic stats --sort bw --top 10
|
|
141
|
+
|
|
142
|
+
# Single snapshot (non-interactive)
|
|
143
|
+
lcm topic stats --freeze
|
|
144
|
+
|
|
145
|
+
# Add sparkline trend visualization
|
|
146
|
+
lcm topic stats --spark
|
|
147
|
+
|
|
148
|
+
# Monitor bandwidth for a single channel
|
|
149
|
+
lcm topic bw CAMERA --window 10 --spark
|
|
150
|
+
|
|
151
|
+
# Read stats from log file
|
|
152
|
+
lcm topic stats --from recording.log
|
|
153
|
+
```
|
|
154
|
+
|
|
63
155
|
## Message Decoding
|
|
64
156
|
|
|
157
|
+
### Type Diagnostics
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
# List all registered types
|
|
161
|
+
lcm type list
|
|
162
|
+
|
|
163
|
+
# Filter by package
|
|
164
|
+
lcm type list --package exlcm
|
|
165
|
+
|
|
166
|
+
# Show type structure
|
|
167
|
+
lcm type show example_t --lcm-file types/
|
|
168
|
+
|
|
169
|
+
# Grep search types
|
|
170
|
+
lcm type list --grep "sensor"
|
|
171
|
+
```
|
|
172
|
+
|
|
65
173
|
### Method 1: Specify `.lcm` files directly (recommended)
|
|
66
174
|
|
|
67
175
|
No `lcm-gen` installation, no `PYTHONPATH` configuration. The tool includes a built-in pure-Python parser:
|
|
@@ -94,7 +202,7 @@ Supports the complete LCM type system:
|
|
|
94
202
|
|
|
95
203
|
```bash
|
|
96
204
|
# Install the lcm Python package
|
|
97
|
-
pip install lcm-
|
|
205
|
+
pip install lcm-cli[decode]
|
|
98
206
|
|
|
99
207
|
# Generate Python files with lcm-gen, then configure PYTHONPATH
|
|
100
208
|
lcm-gen --python -d types/ types/example_t.lcm
|
|
@@ -156,6 +264,8 @@ Reference: [LCM UDP Multicast Protocol](https://lcm-proj.github.io/lcm/content/u
|
|
|
156
264
|
|
|
157
265
|
## LCM vs ROS2 Concepts
|
|
158
266
|
|
|
267
|
+
LCM and ROS2 share similar pub/sub communication patterns. Here's a concept mapping:
|
|
268
|
+
|
|
159
269
|
| LCM Concept | ROS2 Equivalent | Description |
|
|
160
270
|
|-------------|----------------|-------------|
|
|
161
271
|
| Channel | Topic | Message publish/subscribe conduit |
|
|
@@ -165,13 +275,21 @@ Reference: [LCM UDP Multicast Protocol](https://lcm-proj.github.io/lcm/content/u
|
|
|
165
275
|
## Project Structure
|
|
166
276
|
|
|
167
277
|
```
|
|
168
|
-
src/
|
|
278
|
+
src/lcm_cli/
|
|
279
|
+
├── __init__.py # Package definition + version
|
|
280
|
+
├── __main__.py # python -m lcm_cli entry point
|
|
169
281
|
├── cli.py # Typer entry point, registers subcommands
|
|
170
282
|
├── commands/
|
|
171
|
-
│ ├── topic_echo.py # lcm topic echo
|
|
172
|
-
│ ├── topic_list.py # lcm topic list
|
|
173
|
-
│ ├── topic_stats.py # lcm topic stats
|
|
174
|
-
│
|
|
283
|
+
│ ├── topic_echo.py # lcm topic echo (with --csv/--jsonl export)
|
|
284
|
+
│ ├── topic_list.py # lcm topic list (with --watch mode)
|
|
285
|
+
│ ├── topic_stats.py # lcm topic stats (with --sort/--top/--freeze)
|
|
286
|
+
│ ├── topic_bw.py # lcm topic bw (bandwidth monitor)
|
|
287
|
+
│ ├── topic_info.py # lcm topic info (channel details)
|
|
288
|
+
│ ├── node_list.py # lcm node list (with --watch mode)
|
|
289
|
+
│ ├── type_list.py # lcm type list
|
|
290
|
+
│ ├── type_show.py # lcm type show
|
|
291
|
+
│ ├── record.py # lcm record
|
|
292
|
+
│ └── play.py # lcm play
|
|
175
293
|
├── core/
|
|
176
294
|
│ ├── discovery.py # Passive channel/node discovery
|
|
177
295
|
│ ├── stats.py # Real-time statistics (rate, bandwidth)
|
|
@@ -179,9 +297,13 @@ src/lcm_tools/
|
|
|
179
297
|
│ └── lcm_type_builder.py # Runtime decode class generation + TypeRegistry
|
|
180
298
|
├── display/
|
|
181
299
|
│ ├── echo_display.py # Rich panel display (with recursive nesting)
|
|
182
|
-
│
|
|
300
|
+
│ ├── stats_display.py # Statistics table display (with sparkline)
|
|
301
|
+
│ └── type_display.py # Type structure table display
|
|
302
|
+
├── export.py # Field extraction + CSV/JSONL writers
|
|
303
|
+
├── lcm_log.py # LCM log file reader/writer (lcm-logger compatible)
|
|
183
304
|
├── listener.py # UDP multicast listener thread
|
|
184
|
-
|
|
305
|
+
├── protocol.py # LCM Wire Protocol parser
|
|
306
|
+
└── source.py # PacketSource abstraction (live/offline)
|
|
185
307
|
```
|
|
186
308
|
|
|
187
309
|
## Testing
|