187 lines
5.1 KiB
Markdown
187 lines
5.1 KiB
Markdown
# Saqr — Auto-start on boot
|
|
|
|
How to make `saqr_g1_bridge.py` run automatically on every boot of the
|
|
Unitree G1 (Jetson), via `systemd` + `start_saqr.sh`.
|
|
|
|
---
|
|
|
|
## Files involved
|
|
|
|
| File | Role |
|
|
|------|------|
|
|
| `~/Saqr/saqr_g1_bridge.py` | The bridge process (DDS + TTS + R2+X/R2+Y trigger loop). |
|
|
| `~/Saqr/start_saqr.sh` | Bash launcher: sources conda, activates `marcus`, `cd ~/Saqr`, exec the bridge with the right flags. |
|
|
| `~/Saqr/saqr-bridge.service` | systemd unit that runs `start_saqr.sh` as user `unitree` on every boot, restarts on failure, logs to journalctl. |
|
|
|
|
---
|
|
|
|
## One-time install
|
|
|
|
Run these on the robot:
|
|
|
|
```bash
|
|
# 1. Make sure the launcher is executable.
|
|
chmod +x ~/Saqr/start_saqr.sh
|
|
|
|
# 2. Install the systemd unit system-wide so it starts at BOOT
|
|
# (not just at login).
|
|
sudo cp ~/Saqr/saqr-bridge.service /etc/systemd/system/
|
|
sudo systemctl daemon-reload
|
|
|
|
# 3. Enable + start it now.
|
|
sudo systemctl enable --now saqr-bridge
|
|
|
|
# 4. Verify it came up.
|
|
sudo systemctl status saqr-bridge
|
|
```
|
|
|
|
You should hear **"Saqr is running. Press R2 plus X to start."** on the
|
|
robot speaker within ~10 seconds. From then on, every reboot auto-starts
|
|
the bridge — no terminal needed.
|
|
|
|
---
|
|
|
|
## Daily commands
|
|
|
|
```bash
|
|
# Follow the live bridge log (replaces the terminal you used to ssh into).
|
|
journalctl -u saqr-bridge -f
|
|
|
|
# Stop / start / restart on demand.
|
|
sudo systemctl restart saqr-bridge
|
|
sudo systemctl stop saqr-bridge
|
|
sudo systemctl start saqr-bridge
|
|
|
|
# Disable auto-start at boot (the service stays installed).
|
|
sudo systemctl disable saqr-bridge
|
|
|
|
# Re-enable auto-start at boot.
|
|
sudo systemctl enable saqr-bridge
|
|
|
|
# Show the most recent 100 log lines (e.g. after a reboot).
|
|
journalctl -u saqr-bridge -n 100 --no-pager
|
|
|
|
# Show only this boot's logs.
|
|
journalctl -u saqr-bridge -b
|
|
```
|
|
|
|
---
|
|
|
|
## ⚠️ Don't run two bridges at once
|
|
|
|
Once the systemd service is enabled, the bridge is **already running** in
|
|
the background. If you also run `./start_saqr.sh` in a terminal you'll have
|
|
two bridges fighting over the same DDS clients (you'll see lines like
|
|
`R2+X pressed -> start saqr` immediately followed by
|
|
`start ignored — saqr already running`, because both bridges react to the
|
|
same wireless-remote events).
|
|
|
|
Pick one mode:
|
|
|
|
```bash
|
|
# Production: let systemd own the bridge.
|
|
sudo systemctl start saqr-bridge
|
|
journalctl -u saqr-bridge -f
|
|
|
|
# Dev / debugging: stop the systemd one first, then run by hand.
|
|
sudo systemctl stop saqr-bridge
|
|
~/Saqr/start_saqr.sh
|
|
```
|
|
|
|
---
|
|
|
|
## Quick reboot test
|
|
|
|
```bash
|
|
sudo reboot
|
|
|
|
# After the robot is back up:
|
|
ssh unitree@192.168.123.164
|
|
sudo systemctl status saqr-bridge # should be "active (running)"
|
|
journalctl -u saqr-bridge -n 50 # boot log including the
|
|
# "Saqr is running" TTS line
|
|
```
|
|
|
|
---
|
|
|
|
## Updating the bridge / launcher / unit
|
|
|
|
After editing any of the three files:
|
|
|
|
```bash
|
|
# If you changed start_saqr.sh or saqr_g1_bridge.py:
|
|
sudo systemctl restart saqr-bridge
|
|
|
|
# If you changed saqr-bridge.service itself:
|
|
sudo cp ~/Saqr/saqr-bridge.service /etc/systemd/system/
|
|
sudo systemctl daemon-reload
|
|
sudo systemctl restart saqr-bridge
|
|
```
|
|
|
|
---
|
|
|
|
## Configuration overrides
|
|
|
|
`start_saqr.sh` reads its config from environment variables, so you can
|
|
override any of them without editing the script. Defaults:
|
|
|
|
| Variable | Default | Meaning |
|
|
|---------------|------------------|---------|
|
|
| `SAQR_DIR` | `$HOME/Saqr` | Where `saqr_g1_bridge.py` lives. |
|
|
| `CONDA_ROOT` | `$HOME/miniconda3` | Miniconda install path. |
|
|
| `CONDA_ENV` | `marcus` | Conda env that has `unitree_sdk2py`, `ultralytics`, `pyrealsense2`. |
|
|
| `DDS_IFACE` | `eth0` | DDS network interface for the G1. |
|
|
| `SAQR_SOURCE` | `realsense` | `--source` passed to saqr (`realsense` / `/dev/video2` / `0`). |
|
|
| `STREAM_PORT` | `8080` | MJPEG stream port (`-- --stream $STREAM_PORT`). |
|
|
|
|
To override permanently in the systemd service, add `Environment=` lines
|
|
to `/etc/systemd/system/saqr-bridge.service` and run
|
|
`sudo systemctl daemon-reload && sudo systemctl restart saqr-bridge`.
|
|
Example:
|
|
|
|
```ini
|
|
Environment=SAQR_SOURCE=/dev/video2
|
|
Environment=STREAM_PORT=9090
|
|
```
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
### Service won't start
|
|
|
|
```bash
|
|
sudo systemctl status saqr-bridge
|
|
journalctl -u saqr-bridge -n 100 --no-pager
|
|
```
|
|
|
|
Common causes:
|
|
- `start_saqr.sh` not executable → `chmod +x ~/Saqr/start_saqr.sh`
|
|
- conda env name wrong → check `CONDA_ENV`
|
|
- `unitree_sdk2py` missing in the env → run `~/Saqr/start_saqr.sh` by hand to see the import error
|
|
- DDS interface wrong → set `DDS_IFACE=enp...` if the G1 isn't on `eth0`
|
|
|
|
### "No device connected" when pressing R2+X
|
|
|
|
The RealSense USB hiccup. The bridge stays alive and announces
|
|
**"Camera not connected. Please plug in the camera and try again."** —
|
|
just unplug/replug the camera and press R2+X again. If it persists,
|
|
fall back to the V4L2 path:
|
|
|
|
```bash
|
|
sudo systemctl edit saqr-bridge
|
|
# add:
|
|
[Service]
|
|
Environment=SAQR_SOURCE=/dev/video2
|
|
# save, then:
|
|
sudo systemctl restart saqr-bridge
|
|
```
|
|
|
|
### Bridge is running twice
|
|
|
|
```bash
|
|
ps -ef | grep saqr_g1_bridge
|
|
# If you see two python processes, kill the manual one and let systemd own it:
|
|
sudo systemctl restart saqr-bridge
|
|
```
|