[release] 规范 ROS 2 三代目录并校准训练说明

This commit is contained in:
2026-07-27 18:43:29 +08:00
parent 196044b993
commit 117b02bec7
171 changed files with 12741 additions and 6472 deletions
@@ -0,0 +1,22 @@
# Orin 触控屏控制面板
`fullscreen_quit.py` 是比赛 Orin 外接 `800×600` 屏幕使用的控制面板,通过本机 `http://127.0.0.1:18080/api/*` 调用 ROS 2 Web bridge,不建立第二套控制协议。
```bash
cd <sim2real_ros2_v3工作区>
DISPLAY=:0 python3 screen/fullscreen_quit.py
```
程序默认从脚本父目录自动确定工作区,也可设置 `SIM2REAL_REPO_DIR` 覆盖。显示权限检查:
```bash
python3 screen/check_display.py
```
自启动脚本:
- `install_autostart.sh`:图形桌面登录后启动。
- `install_boot_service.sh <用户名>`:安装 systemd 服务。
- `uninstall_boot_service.sh`:卸载服务。
使用屏幕启动系统前,先完成工作区构建、Odin 配置、CAN 映射检查和急停验证。
@@ -0,0 +1,114 @@
#!/usr/bin/env python3
"""
Print display-related diagnostics for launching the fullscreen quit screen.
"""
import glob
import getpass
import os
import shlex
import subprocess
from typing import List, Optional
def run(command: List[str]) -> str:
try:
result = subprocess.run(
command,
check=False,
capture_output=True,
text=True,
)
except OSError as exc:
return f"<failed: {exc}>"
output = result.stdout.strip()
error = result.stderr.strip()
if error:
return f"{output}\n{error}".strip()
return output
def current_user() -> str:
try:
return getpass.getuser()
except OSError:
return os.environ.get("USER", "unknown")
def xauth_from_x_processes() -> List[str]:
output = run(["ps", "-eo", "args"])
candidates = []
for line in output.splitlines():
if "Xorg" not in line and "Xwayland" not in line:
continue
try:
parts = shlex.split(line)
except ValueError:
parts = line.split()
for index, part in enumerate(parts[:-1]):
if part == "-auth":
candidates.append(parts[index + 1])
return candidates
def print_path_status(label: str, path: Optional[str]) -> None:
if not path:
print(f"{label}: <unset>")
return
exists = os.path.exists(path)
readable = os.access(path, os.R_OK) if exists else False
print(f"{label}: {path} exists={exists} readable={readable}")
def main() -> int:
uid = os.getuid()
print(f"user: {run(['whoami'])}")
print(f"uid: {uid}")
print(f"DISPLAY: {os.environ.get('DISPLAY', '<unset>')}")
print(f"XAUTHORITY: {os.environ.get('XAUTHORITY', '<unset>')}")
print()
print("candidate XAUTHORITY files:")
candidates = [
os.environ.get("XAUTHORITY"),
*xauth_from_x_processes(),
os.path.expanduser("~/.Xauthority"),
f"/run/user/{uid}/gdm/Xauthority",
f"/run/user/{uid}/Xauthority",
*glob.glob(f"/run/user/{uid}/*Xauthority*"),
]
seen = set()
for candidate in candidates:
key = candidate or "<unset>"
if key in seen:
continue
seen.add(key)
print_path_status(" -", candidate)
print()
print("X server processes:")
x_lines = [
line
for line in run(["ps", "-eo", "user,args"]).splitlines()
if "Xorg" in line or "Xwayland" in line
]
if x_lines:
for line in x_lines:
print(f" {line}")
else:
print(" <none found>")
print()
print("recommended SSH launch:")
print(" cd <workspace>/screen")
print(" bash run_fullscreen_quit.sh")
print()
print("if authorization fails, run this on the Nano desktop terminal once:")
print(f" DISPLAY=:0 xhost +SI:localuser:{current_user()}")
return 0
if __name__ == "__main__":
raise SystemExit(main())
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,27 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
AUTOSTART_DIR="$HOME/.config/autostart"
DESKTOP_FILE="$AUTOSTART_DIR/sim2real-screen.desktop"
mkdir -p "$AUTOSTART_DIR"
chmod +x "$SCRIPT_DIR/run_fullscreen_quit.sh"
cat > "$DESKTOP_FILE" <<EOF
[Desktop Entry]
Type=Application
Name=sim2real Screen
Comment=Start the sim2real touch control panel
Exec=$SCRIPT_DIR/run_fullscreen_quit.sh
Path=$SCRIPT_DIR
Terminal=false
X-GNOME-Autostart-enabled=true
StartupNotify=false
EOF
echo "Installed desktop autostart:"
echo " $DESKTOP_FILE"
echo
echo "It will start after this user logs into the graphical desktop."
echo "For boot-time use, enable automatic login for this user on the Orin desktop."
@@ -0,0 +1,73 @@
#!/usr/bin/env bash
set -euo pipefail
if ! command -v systemctl >/dev/null 2>&1; then
echo "systemctl not found; this installer is for systemd-based Linux." >&2
exit 1
fi
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SERVICE_NAME="sim2real-screen.service"
SERVICE_PATH="/etc/systemd/system/$SERVICE_NAME"
if [ "${EUID:-$(id -u)}" -eq 0 ]; then
RUN_USER="${1:-${SUDO_USER:-rc2}}"
else
RUN_USER="${1:-$(id -un)}"
fi
if ! id "$RUN_USER" >/dev/null 2>&1; then
echo "User '$RUN_USER' does not exist. Usage: bash install_boot_service.sh rc2" >&2
exit 1
fi
RUN_GROUP="$(id -gn "$RUN_USER")"
RUN_HOME="$(getent passwd "$RUN_USER" | cut -d: -f6)"
AUTOSTART_FILE="$RUN_HOME/.config/autostart/sim2real-screen.desktop"
chmod +x "$SCRIPT_DIR/run_fullscreen_quit.sh" "$SCRIPT_DIR/run_boot_screen_service.sh"
if [ -f "$AUTOSTART_FILE" ]; then
rm -f "$AUTOSTART_FILE"
echo "Removed desktop autostart to avoid duplicate screen instances:"
echo " $AUTOSTART_FILE"
fi
SERVICE_CONTENT="[Unit]
Description=sim2real touchscreen control panel
Wants=display-manager.service
After=systemd-user-sessions.service display-manager.service
StartLimitIntervalSec=0
[Service]
Type=simple
User=$RUN_USER
Group=$RUN_GROUP
WorkingDirectory=$SCRIPT_DIR
Environment=HOME=$RUN_HOME
Environment=DISPLAY=:0
Environment=PYTHONUNBUFFERED=1
ExecStart=$SCRIPT_DIR/run_boot_screen_service.sh
Restart=always
RestartSec=2
KillSignal=SIGINT
TimeoutStopSec=20
[Install]
WantedBy=graphical.target
"
printf "%s" "$SERVICE_CONTENT" | sudo tee "$SERVICE_PATH" >/dev/null
sudo systemctl daemon-reload
sudo systemctl enable "$SERVICE_NAME"
echo "Installed and enabled:"
echo " $SERVICE_PATH"
echo
echo "Start now:"
echo " sudo systemctl restart $SERVICE_NAME"
echo
echo "Check status/logs:"
echo " systemctl status $SERVICE_NAME --no-pager"
echo " journalctl -u $SERVICE_NAME -f"
echo
echo "Important: the graphical desktop for user '$RUN_USER' must auto-login, otherwise Tk cannot open DISPLAY=:0."
@@ -0,0 +1,23 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
export DISPLAY="${DISPLAY:-:0}"
export PYTHONUNBUFFERED=1
echo "[sim2real-screen] service starting as $(id -un), DISPLAY=$DISPLAY"
for _ in $(seq 1 120); do
if [ -S "/tmp/.X11-unix/X${DISPLAY#:}" ]; then
break
fi
sleep 1
done
if [ ! -S "/tmp/.X11-unix/X${DISPLAY#:}" ]; then
echo "[sim2real-screen] X11 socket for DISPLAY=$DISPLAY not found" >&2
exit 1
fi
exec "$SCRIPT_DIR/run_fullscreen_quit.sh"
@@ -0,0 +1,24 @@
#!/usr/bin/env bash
set -u
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"
export DISPLAY="${DISPLAY:-:0}"
if [ -z "${XAUTHORITY:-}" ]; then
UID_VALUE="$(id -u)"
for candidate in \
"$HOME/.Xauthority" \
"/run/user/$UID_VALUE/gdm/Xauthority" \
"/run/user/$UID_VALUE/Xauthority"
do
if [ -f "$candidate" ]; then
export XAUTHORITY="$candidate"
break
fi
done
fi
python3 fullscreen_quit.py
Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

@@ -0,0 +1,11 @@
#!/usr/bin/env bash
set -euo pipefail
SERVICE_NAME="sim2real-screen.service"
SERVICE_PATH="/etc/systemd/system/$SERVICE_NAME"
sudo systemctl disable --now "$SERVICE_NAME" 2>/dev/null || true
sudo rm -f "$SERVICE_PATH"
sudo systemctl daemon-reload
echo "Removed $SERVICE_NAME"