Skip to content

Commit 21efc2f

Browse files
janapavlaseksxy-sunShaw Sun
authored
Merge stable version for F24 (#4)
* Feature/lcm spy cli (#1) 1. updated install script, `mbot-lcm-spy` is now avaibale system-wise 2. added new README for `mbot-lcm-spy` 3. modified `mbot_lcm_spy.py`, now if any array-like values have length > 10, the rest will be cut off 4. now nested lcm data structure can be printed as well, such as mbot_apriltag * print format fix the mbot_apriltag_array_t is too long, the print format needed to be updated * BUG FIX/lidar message too long --------- Co-authored-by: Shaw Sun <sunxync98@gmail.xom> * bugfix: couldn't handle no tag detection for apriltag msg (#2) * Feature/mbot cli (#3) --------- Co-authored-by: Shaw Sun <49962634+sxy-sun@users.noreply.github.com> Co-authored-by: Shaw Sun <sunxync98@gmail.xom>
1 parent 64e12f7 commit 21efc2f

File tree

11 files changed

+606
-0
lines changed

11 files changed

+606
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
This repo contains some essential subpackages needed by all other MBot applications running off LCM:
44
* [mbot_lcm_serial](mbot_lcm_serial): LCM-to-serial communication with the MBot control board.
55
* [mbot_msgs](mbot_msgs): Message type definitions for LCM.
6+
* [mbot_lcm_spy](mbot_lcm_spy): Command line tool to monitor lcm messages similar to lcm-spy.
67

78
## Fast Install
89

mbot_sys_cli/README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# MBot System CLI
2+
3+
## Description
4+
This folder contains command line tools for the MBot system:
5+
6+
- mbot-lcm-spy: A command line tool similar to lcm-spy, akin to `ros topic`.
7+
- mbot-service: Similar to `ros node`, it uses systemctl and journalctl to manage and monitor MBot system services.
8+
- mbot-lcm-msg: Functions like `ros msg`, used to inspect the data structure of MBot LCM messages.
9+
10+
## Installation
11+
> If you have run the install.sh under the mbot_lcm_base folder, then you don't need to run this.
12+
```bash
13+
chmod +x install.sh
14+
./install.sh
15+
```
16+
17+
## Usage and Features
18+
Usage instructions can be found in the README.md file within each tool's folder.
19+
20+
## Authors and maintainers
21+
The current maintainer of this project is Shaw Sun. Please direct all questions regarding support, contributions, and issues to the maintainer.

mbot_sys_cli/install.sh

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#!/bin/bash
2+
set -e # Quit on error.
3+
4+
# Install mbot-lcm-spy
5+
echo "Installing mbot-lcm-spy..."
6+
chmod +x mbot_lcm_spy/mbot_lcm_spy.py
7+
sudo cp mbot_lcm_spy/mbot_lcm_spy.py /usr/local/bin/mbot-lcm-spy
8+
9+
# Install system tool mbot-service
10+
echo "Installing mbot-service..."
11+
chmod +x mbot_service/mbot-service.sh
12+
sudo cp mbot_service/mbot-service.sh /usr/local/bin/mbot-service
13+
14+
# Install mbot-lcm-msg
15+
echo "Installing mbot-lcm-msg..."
16+
chmod +x mbot_lcm_msg/mbot_lcm_msg.py
17+
sudo cp mbot_lcm_msg/mbot_lcm_msg.py /usr/local/bin/mbot-lcm-msg
18+
19+
# Install dispatcher script mbot
20+
echo "Installing mbot cli tools..."
21+
chmod +x mbot.sh
22+
sudo cp mbot.sh /usr/local/bin/mbot
23+
24+
# Auto-completion script
25+
cat << 'EOF' | sudo tee /etc/bash_completion.d/mbot > /dev/null
26+
# mbot completion
27+
_mbot()
28+
{
29+
local cur prev commands servicespy msg
30+
COMPREPLY=()
31+
cur="${COMP_WORDS[COMP_CWORD]}"
32+
prev="${COMP_WORDS[COMP_CWORD-1]}"
33+
commands="service lcm-spy lcm-msg"
34+
35+
if [[ ${COMP_CWORD} -eq 1 ]] ; then
36+
COMPREPLY=( $(compgen -W "${commands}" -- ${cur}) )
37+
return 0
38+
fi
39+
40+
case "${prev}" in
41+
service)
42+
servicespy="list status log start stop restart enable disable"
43+
COMPREPLY=( $(compgen -W "${servicespy}" -- ${cur}) )
44+
return 0
45+
;;
46+
lcm-spy)
47+
servicespy="--channels --rate --module"
48+
COMPREPLY=( $(compgen -W "${servicespy}" -- ${cur}) )
49+
return 0
50+
;;
51+
lcm-msg)
52+
msg="list show"
53+
COMPREPLY=( $(compgen -W "${msg}" -- ${cur}) )
54+
return 0
55+
;;
56+
esac
57+
}
58+
59+
complete -F _mbot mbot
60+
EOF
61+
62+
# Reload bash configuration
63+
source ~/.bashrc
64+
65+
echo "MBot System CLI Installation completed successfully."

mbot_sys_cli/mbot.sh

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#!/bin/bash
2+
set -e
3+
4+
# Dispatcher script for mbot commands
5+
6+
# Check if the user provided at least one argument
7+
if [ $# -lt 1 ]; then
8+
echo "Usage: mbot {service|lcm-spy|lcm-msg} [args]"
9+
exit 1
10+
fi
11+
12+
# The first argument determines the command
13+
command=$1
14+
shift # Remove the first argument
15+
16+
case $command in
17+
service)
18+
/usr/local/bin/mbot-service "$@"
19+
;;
20+
lcm-spy)
21+
/usr/local/bin/mbot-lcm-spy "$@"
22+
;;
23+
lcm-msg)
24+
/usr/local/bin/mbot-lcm-msg "$@"
25+
;;
26+
*)
27+
echo "Unknown command: $command"
28+
echo "Usage: mbot {service|lcm-spy|lcm-msg} [args]"
29+
exit 1
30+
;;
31+
esac
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
> This tool is similar to rosmsg, used to inspect the data structure of MBot LCM messages. Though rosmsg is deprecated in ROS 2 now.
2+
3+
## Usage
4+
```
5+
mbot lcm-msg [-h] [--module MODULE] {show,list} ...
6+
7+
positional arguments:
8+
{show,list} sub-command help
9+
show Output the message definition
10+
list List all available LCM messages
11+
12+
options:
13+
-h, --help show this help message and exit
14+
--module MODULE Module to use for decoding messages
15+
```
16+
17+
Example:
18+
```bash
19+
# this will print all the mbot lcm message's type
20+
mbot lcm-msg list
21+
22+
# this will print pose3D_t data structure
23+
mbot lcm-msg show pose3D_t
24+
25+
# this will print pose3D_t and pose2D_t data structure
26+
mbot lcm-msg show pose3D_t,pose2D_t
27+
```
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
#!/usr/bin/env python3
2+
3+
import argparse
4+
import importlib
5+
6+
# Command-line argument parsing
7+
parser = argparse.ArgumentParser(description="Displays LCM message's data structure")
8+
parser.add_argument("--module", type=str, default="mbot_lcm_msgs", help="Module to use for decoding messages")
9+
10+
subparsers = parser.add_subparsers(dest='command', help='sub-command help')
11+
12+
# Sub-parser for the "show" command
13+
parser_show = subparsers.add_parser('show', help='Output the message definition')
14+
parser_show.add_argument('msgs', type=str, help='Comma-separated list of message names you want to check')
15+
16+
# Sub-parser for the "list" command
17+
parser_list = subparsers.add_parser('list', help='List all available LCM messages')
18+
19+
args = parser.parse_args()
20+
21+
# Load the module for decoding messages if provided
22+
decode_module = None
23+
if args.module:
24+
try:
25+
decode_module = importlib.import_module(args.module)
26+
except ImportError:
27+
print(f"Error: Could not import module {args.module}")
28+
decode_module = None
29+
30+
def read_all_lcm_type():
31+
lcm_type_dict = dict()
32+
if decode_module:
33+
try:
34+
# Attempt to decode the message to find its type
35+
for attr in dir(decode_module):
36+
lcm_type_class = getattr(decode_module, attr)
37+
if isinstance(lcm_type_class, type) and hasattr(lcm_type_class, 'decode'):
38+
try:
39+
# lcm_type is the name of the message type
40+
lcm_type = lcm_type_class.__name__
41+
# lcm_type_dict[lcm_type] is a list of tuple (data type, variable name)
42+
lcm_type_dict[lcm_type] = list(zip(lcm_type_class.__typenames__, lcm_type_class.__slots__))
43+
except Exception:
44+
continue
45+
except Exception as e:
46+
lcm_type_dict['Error'] = str(e)
47+
48+
return lcm_type_dict
49+
50+
def inspect_class_attributes(cls):
51+
attributes = dir(cls)
52+
for attr in attributes:
53+
try:
54+
value = getattr(cls, attr)
55+
print(f"{attr}: {value}")
56+
except AttributeError:
57+
print(f"{attr}: <unavailable>")
58+
59+
def show_msg_struct(msgs):
60+
msgs_to_print = msgs.split(',')
61+
lcm_type_dict = read_all_lcm_type()
62+
for msg in msgs_to_print:
63+
if msg not in lcm_type_dict.keys():
64+
print(f"Error: {msg} is not a valid lcm message type!")
65+
continue
66+
print(f"{msg}\n")
67+
for dtype, vname in lcm_type_dict[msg]:
68+
print(f"{' ' * 4}{dtype:<10} {vname:<10}")
69+
print()
70+
71+
72+
def main():
73+
if args.command == 'list':
74+
lcm_type_dict = read_all_lcm_type()
75+
for key in lcm_type_dict.keys():
76+
print(f"{key}")
77+
elif args.command == 'show':
78+
show_msg_struct(args.msgs)
79+
80+
if __name__ == "__main__":
81+
try:
82+
main()
83+
except KeyboardInterrupt:
84+
print("\nExiting gracefully...")
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
> This tool is a command-line version of lcm-spy
2+
3+
## Usage
4+
```shell
5+
mbot lcm-spy [-h] [--channels CHANNELS] [--rate RATE] [--module MODULE]
6+
```
7+
8+
### Options
9+
- `-h, --help`: Show this help message and exit
10+
- `--channels CHANNELS`: Comma-separated list of channel names to print decoded messages
11+
- `--rate RATE`: Rate at which data is printed in Hz (default: 1 Hz)
12+
- `--module MODULE`: Module to use for decoding messages (default: "mbot_lcm_msgs")
13+
14+
For example, if you run:
15+
16+
```shell
17+
mbot-lcm-spy --channels MBOT_ENCODERS,MBOT_IMU --rate 5
18+
```
19+
- Note that **DO NOT** put space between 2 channel names like this: `MBOT_ENCODERS, MBOT_IMU`
20+
21+
You will get the output:
22+
23+
24+
#### Channel Information
25+
26+
| Channel | Type | Rate | Msgs Rcvd |
27+
| ---------------- | ------------------- | ----- | --------- |
28+
| MBOT\_ODOMETRY | pose2D\_t | 25.00 | 318 |
29+
| MBOT\_IMU | mbot\_imu\_t | 25.00 | 318 |
30+
| MBOT\_VEL | twist2D\_t | 25.00 | 318 |
31+
| MBOT\_MOTOR\_VEL | mbot\_motor\_vel\_t | 25.00 | 318 |
32+
| MBOT\_MOTOR\_PWM | mbot\_motor\_pwm\_t | 25.00 | 318 |
33+
| MBOT\_ENCODERS | mbot\_encoders\_t | 25.00 | 317 |
34+
| MBOT\_TIMESYNC | timestamp\_t | 1.00 | 13 |
35+
36+
#### Decoded message on channel MBOT\_ENCODERS:
37+
38+
| Field | Value |
39+
| ------------ | ---------------- |
40+
| utime | 1718035974387383 |
41+
| ticks | (-1, 276, 0) |
42+
| delta\_ticks | (0, 0, 0) |
43+
| delta\_time | 40453 |
44+
45+
#### Decoded message on channel MBOT\_IMU:
46+
47+
| Field | Value |
48+
| ------------ | ------------------------------------- |
49+
| utime | 1718035974387383 |
50+
| gyro | (0.002396918134763837, -0.0005326484679244459, 0.0017311074770987034) |
51+
| accel | (-0.7628380656242371, 0.6754170656204224, -10.061798095703125) |
52+
| mag | (0.25, 0.25, 0.375) |
53+
| angles\_rpy | (-0.06807039678096771, -0.07631554454565048, -0.12962138652801514) |
54+
| angles\_quat | (0.99658203125, -0.03643798828125, -0.03594970703125, -0.064697265625) |
55+
| temp | 0.0 |

0 commit comments

Comments
 (0)