fix: 更新 README 和配置文件,调整模式和工具设置
This commit is contained in:
@@ -9,7 +9,7 @@ set_initial_tool_state: false
|
||||
tools_in_ee:
|
||||
scissor:
|
||||
# x, y, z, qx, qy, qz, qw
|
||||
pose: [0.0, 0.0, 0.19, 0.0, 0.0, 0.0, 1.0]
|
||||
pose: [0.0, 0.0, 0.165, 0.0, 0.0, 0.0, 1.0]
|
||||
# mass, center_x, center_y, center_z, reserved...
|
||||
load: [0.66, 0.0, 0.0, 0.06, 0.0, 0.0, 0.0]
|
||||
omnipic:
|
||||
@@ -24,6 +24,6 @@ tools_in_ee:
|
||||
|
||||
arms:
|
||||
left:
|
||||
scissorgripper: 2
|
||||
scissorgripper: 0
|
||||
right:
|
||||
scissorgripper: 1
|
||||
|
||||
@@ -13,6 +13,100 @@ assert SPEC.loader is not None
|
||||
SPEC.loader.exec_module(launcher_ui)
|
||||
|
||||
|
||||
class LauncherCommandsTest(unittest.TestCase):
|
||||
def test_modes_expose_the_confirmed_command_matrix(self) -> None:
|
||||
expected_titles = {
|
||||
"Simulation": [
|
||||
"Dual Arm Mock Launch",
|
||||
"XRobotoolkit UDP Bridge (90 Hz)",
|
||||
"Sample UDP Sender (Both Staggered, 60s)",
|
||||
"Open Controller Hz Monitor",
|
||||
"Open ROS Topic/Node List Monitor",
|
||||
"Open Controller Topic Monitor",
|
||||
],
|
||||
"MuJoCo": [
|
||||
"Dual Arm MuJoCo Mock Launch",
|
||||
"Dual Arm MuJoCo Real Hardware Launch",
|
||||
"XRobotoolkit UDP Bridge (90 Hz)",
|
||||
"Open Controller Hz Monitor",
|
||||
"Open ROS Topic/Node List Monitor",
|
||||
"Open Controller Topic Monitor",
|
||||
],
|
||||
"Real Hardware": [
|
||||
"Ping Left RM75",
|
||||
"Ping Right RM75",
|
||||
"Left Arm RealMan Launch",
|
||||
"Right Arm RealMan Launch",
|
||||
"Dual Arm RealMan Launch",
|
||||
"XRobotoolkit UDP Bridge (90 Hz)",
|
||||
"Left Gripper Open",
|
||||
"Left Gripper Close",
|
||||
"Right Gripper Open",
|
||||
"Right Gripper Close",
|
||||
"Open ROS Topic/Node List Monitor",
|
||||
"Open Controller Topic Monitor",
|
||||
],
|
||||
"Diagnostics": [
|
||||
"ROS Doctor Report",
|
||||
"XR-RM Bringup Prefix",
|
||||
"XR-RM Input Prefix",
|
||||
"XR-RM Teleop Prefix",
|
||||
"XR-RM MuJoCo Prefix",
|
||||
"Open Controller Position Monitor",
|
||||
"Open Controller Hz Monitor",
|
||||
"Open ROS Topic/Node List Monitor",
|
||||
"Open Controller Topic Monitor",
|
||||
],
|
||||
}
|
||||
|
||||
self.assertEqual(launcher_ui.MODES, list(expected_titles))
|
||||
for mode, titles in expected_titles.items():
|
||||
actual = [
|
||||
indexed_title.split(". ", 1)[1]
|
||||
for indexed_title, _command in launcher_ui.build_commands_by_mode(mode)
|
||||
]
|
||||
self.assertEqual(actual, titles)
|
||||
|
||||
def test_mujoco_launches_distinguish_mock_and_real_hardware(self) -> None:
|
||||
commands = dict(launcher_ui.build_commands_by_mode("MuJoCo"))
|
||||
|
||||
self.assertIn(
|
||||
"arm:=both use_mock:=true use_mujoco:=true",
|
||||
commands["1. Dual Arm MuJoCo Mock Launch"],
|
||||
)
|
||||
self.assertIn(
|
||||
"arm:=both use_mock:=false use_mujoco:=true",
|
||||
commands["2. Dual Arm MuJoCo Real Hardware Launch"],
|
||||
)
|
||||
|
||||
def test_cmd_vel_monitor_is_completely_removed(self) -> None:
|
||||
self.assertFalse(hasattr(launcher_ui, "CMD_VEL_MONITOR_ACTION"))
|
||||
for mode in launcher_ui.MODES:
|
||||
self.assertNotIn("cmd_vel", repr(launcher_ui.build_commands_by_mode(mode)))
|
||||
|
||||
def test_environment_check_includes_mujoco_package(self) -> None:
|
||||
app = object.__new__(launcher_ui.LauncherApp)
|
||||
app.workspace_root = launcher_ui._find_workspace_root()
|
||||
app.terminal_command = lambda _title, _script: ["terminal"]
|
||||
app.x_terminal_target = lambda: "terminator"
|
||||
checked_packages = []
|
||||
app._ros_package_available = lambda package: checked_packages.append(package) or True
|
||||
app.show_text_dialog = lambda *_args: None
|
||||
app.status = mock.Mock()
|
||||
|
||||
with mock.patch.object(
|
||||
launcher_ui.shutil,
|
||||
"which",
|
||||
return_value="/usr/bin/x-terminal-emulator",
|
||||
):
|
||||
app.check_prerequisites()
|
||||
|
||||
self.assertEqual(
|
||||
checked_packages,
|
||||
["xr_rm_bringup", "xr_rm_input", "xr_rm_teleop", "xr_rm_mujoco"],
|
||||
)
|
||||
|
||||
|
||||
class LauncherCleanupTest(unittest.TestCase):
|
||||
def test_xrobotoolkit_cleanup_policy_only_stops_service_on_window_close(self) -> None:
|
||||
stop_all_patterns = set(
|
||||
@@ -89,6 +183,34 @@ class LauncherCleanupTest(unittest.TestCase):
|
||||
],
|
||||
)
|
||||
|
||||
def test_stop_all_and_window_close_stop_mujoco(self) -> None:
|
||||
for stop_pc_service in (False, True):
|
||||
app = object.__new__(launcher_ui.LauncherApp)
|
||||
app.status = mock.Mock()
|
||||
app.close_related_terminal_windows = lambda: 0
|
||||
|
||||
def fake_check_output(command, **_kwargs):
|
||||
if command == ["pgrep", "-f", "dual_arm_simulator"]:
|
||||
return "404\n"
|
||||
raise subprocess.CalledProcessError(1, command)
|
||||
|
||||
with (
|
||||
mock.patch.object(
|
||||
launcher_ui.subprocess,
|
||||
"check_output",
|
||||
side_effect=fake_check_output,
|
||||
),
|
||||
mock.patch.object(launcher_ui.os, "kill") as kill,
|
||||
mock.patch.object(launcher_ui.time, "sleep"),
|
||||
):
|
||||
app.stop_launched_processes(
|
||||
confirm=False,
|
||||
notify=False,
|
||||
stop_pc_service=stop_pc_service,
|
||||
)
|
||||
|
||||
kill.assert_called_once_with(404, signal.SIGTERM)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#!/usr/bin/env python3
|
||||
"""XR-RM 桌面调试启动器。
|
||||
|
||||
提供 Tkinter 图形界面,按“仿真/左臂/右臂/双臂/诊断”组织常用 ROS2
|
||||
launch、sample_udp_sender、topic 监控和环境检查命令,降低现场调试时的命令输入成本。
|
||||
提供 Tkinter 图形界面,按“仿真/MuJoCo/真机/诊断”组织常用 ROS2 launch、
|
||||
sample_udp_sender、topic 监控和环境检查命令,降低现场调试时的命令输入成本。
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -44,8 +44,6 @@ SAMPLE_SENDER_ARGS = (
|
||||
TERMINAL_TITLE_PREFIX = "XR-RM Terminal - "
|
||||
TOPIC_MONITOR_TITLE = "XR-RM Topic Monitor"
|
||||
TOPIC_MONITOR_ACTION = "__xr_rm_topic_monitor__"
|
||||
CMD_VEL_MONITOR_TITLE = "XR-RM Target Velocity Monitor"
|
||||
CMD_VEL_MONITOR_ACTION = "__xr_rm_cmd_vel_monitor__"
|
||||
ROS_GRAPH_MONITOR_TITLE = "XR-RM ROS Graph Monitor"
|
||||
ROS_GRAPH_MONITOR_ACTION = "__xr_rm_ros_graph_monitor__"
|
||||
|
||||
@@ -54,11 +52,6 @@ TOPIC_MONITORS = [
|
||||
("Right Controller", "/xr/right_controller"),
|
||||
]
|
||||
|
||||
CMD_VEL_MONITORS = [
|
||||
("Left Target Vel", "/xr_rm/left_rm75/cmd_vel"),
|
||||
("Right Target Vel", "/xr_rm/right_rm75/cmd_vel"),
|
||||
]
|
||||
|
||||
CONTROLLER_POSITION_MONITOR_TITLE = "XR-RM Controller Position Monitor"
|
||||
CONTROLLER_POSITION_MONITOR_ACTION = "__xr_rm_controller_position_monitor__"
|
||||
CONTROLLER_HZ_MONITOR_TITLE = "XR-RM Controller Hz Monitor"
|
||||
@@ -81,9 +74,8 @@ ROS_GRAPH_MONITORS = [
|
||||
|
||||
MODES = [
|
||||
"Simulation",
|
||||
"Left Arm",
|
||||
"Right Arm",
|
||||
"Dual Arm",
|
||||
"MuJoCo",
|
||||
"Real Hardware",
|
||||
"Diagnostics",
|
||||
]
|
||||
|
||||
@@ -177,21 +169,6 @@ def _source_lines(workspace_root: Path) -> list[str]:
|
||||
return lines
|
||||
|
||||
|
||||
def _one_click_mock(arm: str, hand: str) -> str:
|
||||
sender_seconds = SAMPLE_SENDER_STAGGERED_SECONDS if hand == "both" else SAMPLE_SENDER_SECONDS
|
||||
both_mode = "staggered" if hand == "both" else "synchronized"
|
||||
return "\n".join([
|
||||
f"ros2 launch xr_rm_bringup arm_debug.launch.py arm:={arm} use_mock:=true &",
|
||||
"launch_pid=$!",
|
||||
"sleep 2",
|
||||
_sample_udp_sender_command(hand, sender_seconds, both_mode),
|
||||
"echo",
|
||||
"echo 'Sample sender finished. The launch process is still running in this terminal.'",
|
||||
"echo 'Press Ctrl-C here, or use the cleanup button in the launcher, to stop it.'",
|
||||
"wait \"$launch_pid\"",
|
||||
])
|
||||
|
||||
|
||||
def _diagnostic_commands() -> list[tuple[str, str]]:
|
||||
return [
|
||||
("Open ROS Topic/Node List Monitor", ROS_GRAPH_MONITOR_ACTION),
|
||||
@@ -202,14 +179,9 @@ def _topic_monitor_item() -> tuple[str, str]:
|
||||
return ("Open Controller Topic Monitor", TOPIC_MONITOR_ACTION)
|
||||
|
||||
|
||||
def _cmd_vel_monitor_item() -> tuple[str, str]:
|
||||
return ("Open Target Velocity Monitor", CMD_VEL_MONITOR_ACTION)
|
||||
|
||||
|
||||
def _is_topic_monitor_action(action: str) -> bool:
|
||||
return action in (
|
||||
TOPIC_MONITOR_ACTION,
|
||||
CMD_VEL_MONITOR_ACTION,
|
||||
CONTROLLER_POSITION_MONITOR_ACTION,
|
||||
CONTROLLER_HZ_MONITOR_ACTION,
|
||||
)
|
||||
@@ -232,14 +204,6 @@ def _topic_monitor_spec(action: str) -> tuple[str, list[tuple[str, str]], str, s
|
||||
"xr_rm_controller_hz_monitor_",
|
||||
"controller hz topic",
|
||||
)
|
||||
if action == CMD_VEL_MONITOR_ACTION:
|
||||
return (
|
||||
CMD_VEL_MONITOR_TITLE,
|
||||
[(title, f"ros2 topic echo {topic}") for title, topic in CMD_VEL_MONITORS],
|
||||
"xr_rm_cmd_vel_monitor",
|
||||
"xr_rm_cmd_vel_monitor_",
|
||||
"target velocity topic",
|
||||
)
|
||||
return (
|
||||
TOPIC_MONITOR_TITLE,
|
||||
[(title, f"ros2 topic echo {topic}") for title, topic in TOPIC_MONITORS],
|
||||
@@ -249,16 +213,10 @@ def _topic_monitor_spec(action: str) -> tuple[str, list[tuple[str, str]], str, s
|
||||
)
|
||||
|
||||
|
||||
def _finalize_items(
|
||||
items: list[tuple[str, str]],
|
||||
one_click: tuple[str, str] | None = None,
|
||||
) -> list[tuple[str, str]]:
|
||||
def _finalize_items(items: list[tuple[str, str]]) -> list[tuple[str, str]]:
|
||||
final_items = items + _diagnostic_commands() + [
|
||||
_topic_monitor_item(),
|
||||
_cmd_vel_monitor_item(),
|
||||
]
|
||||
if one_click is not None:
|
||||
final_items.append(one_click)
|
||||
return _with_index(final_items)
|
||||
|
||||
|
||||
@@ -266,25 +224,64 @@ def build_commands_by_mode(mode: str) -> list[tuple[str, str]]:
|
||||
# UI 列表只维护命令模板;真正执行时统一套上工作空间 source 和终端包装。
|
||||
if mode == "Simulation":
|
||||
items = [
|
||||
("Left Arm Mock Launch", "ros2 launch xr_rm_bringup arm_debug.launch.py arm:=left use_mock:=true"),
|
||||
("Right Arm Mock Launch", "ros2 launch xr_rm_bringup arm_debug.launch.py arm:=right use_mock:=true"),
|
||||
("Dual Arm Mock Launch", "ros2 launch xr_rm_bringup arm_debug.launch.py arm:=both use_mock:=true"),
|
||||
("XRobotoolkit UDP Bridge (90 Hz)", _xrobotoolkit_bridge_command()),
|
||||
(
|
||||
"Sample UDP Sender (Left, 30s)",
|
||||
_sample_udp_sender_command("left"),
|
||||
),
|
||||
(
|
||||
"Sample UDP Sender (Right, 30s)",
|
||||
_sample_udp_sender_command("right"),
|
||||
),
|
||||
(
|
||||
"Sample UDP Sender (Both Staggered, 60s)",
|
||||
_sample_udp_sender_command("both", SAMPLE_SENDER_STAGGERED_SECONDS, "staggered"),
|
||||
),
|
||||
("One-Click Left Mock Demo", _one_click_mock("left", "left")),
|
||||
("One-Click Right Mock Demo", _one_click_mock("right", "right")),
|
||||
("One-Click Dual Mock Demo", _one_click_mock("both", "both")),
|
||||
(
|
||||
"Open Controller Hz Monitor",
|
||||
CONTROLLER_HZ_MONITOR_ACTION,
|
||||
),
|
||||
]
|
||||
elif mode == "MuJoCo":
|
||||
items = [
|
||||
(
|
||||
"Dual Arm MuJoCo Mock Launch",
|
||||
"ros2 launch xr_rm_bringup arm_debug.launch.py "
|
||||
"arm:=both use_mock:=true use_mujoco:=true",
|
||||
),
|
||||
(
|
||||
"Dual Arm MuJoCo Real Hardware Launch",
|
||||
"ros2 launch xr_rm_bringup arm_debug.launch.py "
|
||||
"arm:=both use_mock:=false use_mujoco:=true",
|
||||
),
|
||||
("XRobotoolkit UDP Bridge (90 Hz)", _xrobotoolkit_bridge_command()),
|
||||
(
|
||||
"Open Controller Hz Monitor",
|
||||
CONTROLLER_HZ_MONITOR_ACTION,
|
||||
),
|
||||
]
|
||||
elif mode == "Real Hardware":
|
||||
items = [
|
||||
("Ping Left RM75", f"ping -c 4 {DEFAULT_LEFT_IP}"),
|
||||
("Ping Right RM75", f"ping -c 4 {DEFAULT_RIGHT_IP}"),
|
||||
(
|
||||
"Left Arm RealMan Launch",
|
||||
"ros2 launch xr_rm_bringup arm_debug.launch.py arm:=left use_mock:=false",
|
||||
),
|
||||
(
|
||||
"Right Arm RealMan Launch",
|
||||
"ros2 launch xr_rm_bringup arm_debug.launch.py arm:=right use_mock:=false",
|
||||
),
|
||||
(
|
||||
"Dual Arm RealMan Launch",
|
||||
"ros2 launch xr_rm_bringup arm_debug.launch.py arm:=both use_mock:=false",
|
||||
),
|
||||
("XRobotoolkit UDP Bridge (90 Hz)", _xrobotoolkit_bridge_command()),
|
||||
("Left Gripper Open", _tool_command("left", True)),
|
||||
("Left Gripper Close", _tool_command("left", False)),
|
||||
("Right Gripper Open", _tool_command("right", True)),
|
||||
("Right Gripper Close", _tool_command("right", False)),
|
||||
]
|
||||
else:
|
||||
items = [
|
||||
("ROS Doctor Report", "ros2 doctor --report"),
|
||||
("XR-RM Bringup Prefix", "ros2 pkg prefix xr_rm_bringup"),
|
||||
("XR-RM Input Prefix", "ros2 pkg prefix xr_rm_input"),
|
||||
("XR-RM Teleop Prefix", "ros2 pkg prefix xr_rm_teleop"),
|
||||
("XR-RM MuJoCo Prefix", "ros2 pkg prefix xr_rm_mujoco"),
|
||||
(
|
||||
"Open Controller Position Monitor",
|
||||
CONTROLLER_POSITION_MONITOR_ACTION,
|
||||
@@ -294,64 +291,7 @@ def build_commands_by_mode(mode: str) -> list[tuple[str, str]]:
|
||||
CONTROLLER_HZ_MONITOR_ACTION,
|
||||
),
|
||||
]
|
||||
one_click = None
|
||||
elif mode == "Left Arm":
|
||||
items = [
|
||||
("Ping Left RM75", f"ping -c 4 {DEFAULT_LEFT_IP}"),
|
||||
(
|
||||
"Left Arm RealMan Launch",
|
||||
"ros2 launch xr_rm_bringup arm_debug.launch.py arm:=left use_mock:=false",
|
||||
),
|
||||
("XRobotoolkit UDP Bridge (90 Hz)", _xrobotoolkit_bridge_command()),
|
||||
("Left Tool Open", _tool_command("left", True)),
|
||||
("Left Tool Close", _tool_command("left", False)),
|
||||
(
|
||||
"Sample UDP Sender (Left, 30s)",
|
||||
_sample_udp_sender_command("left"),
|
||||
),
|
||||
]
|
||||
one_click = None
|
||||
elif mode == "Right Arm":
|
||||
items = [
|
||||
("Ping Right RM75", f"ping -c 4 {DEFAULT_RIGHT_IP}"),
|
||||
(
|
||||
"Right Arm RealMan Launch",
|
||||
"ros2 launch xr_rm_bringup arm_debug.launch.py arm:=right use_mock:=false",
|
||||
),
|
||||
("XRobotoolkit UDP Bridge (90 Hz)", _xrobotoolkit_bridge_command()),
|
||||
("Right Tool Open", _tool_command("right", True)),
|
||||
("Right Tool Close", _tool_command("right", False)),
|
||||
(
|
||||
"Sample UDP Sender (Right, 30s)",
|
||||
_sample_udp_sender_command("right"),
|
||||
),
|
||||
]
|
||||
one_click = None
|
||||
elif mode == "Dual Arm":
|
||||
items = [
|
||||
("Ping Left RM75", f"ping -c 4 {DEFAULT_LEFT_IP}"),
|
||||
("Ping Right RM75", f"ping -c 4 {DEFAULT_RIGHT_IP}"),
|
||||
(
|
||||
"Dual Arm RealMan Launch",
|
||||
"ros2 launch xr_rm_bringup arm_debug.launch.py arm:=both use_mock:=false",
|
||||
),
|
||||
("XRobotoolkit UDP Bridge (90 Hz)", _xrobotoolkit_bridge_command()),
|
||||
(
|
||||
"Sample UDP Sender (Both Staggered, 60s)",
|
||||
_sample_udp_sender_command("both", SAMPLE_SENDER_STAGGERED_SECONDS, "staggered"),
|
||||
),
|
||||
]
|
||||
one_click = None
|
||||
else:
|
||||
items = [
|
||||
("ROS Doctor Report", "ros2 doctor --report"),
|
||||
("XR-RM Bringup Prefix", "ros2 pkg prefix xr_rm_bringup"),
|
||||
("XR-RM Input Prefix", "ros2 pkg prefix xr_rm_input"),
|
||||
("XR-RM Teleop Prefix", "ros2 pkg prefix xr_rm_teleop"),
|
||||
("XRobotoolkit UDP Bridge (90 Hz)", _xrobotoolkit_bridge_command()),
|
||||
]
|
||||
one_click = None
|
||||
return _finalize_items(items, one_click)
|
||||
return _finalize_items(items)
|
||||
|
||||
|
||||
class LauncherApp:
|
||||
@@ -608,7 +548,7 @@ class LauncherApp:
|
||||
else:
|
||||
warnings.append("[WARN] Could not identify x-terminal-emulator target.")
|
||||
|
||||
for package in ("xr_rm_bringup", "xr_rm_input", "xr_rm_teleop"):
|
||||
for package in ("xr_rm_bringup", "xr_rm_input", "xr_rm_teleop", "xr_rm_mujoco"):
|
||||
if self._ros_package_available(package):
|
||||
ok.append(f"[OK] ROS package available: {package}")
|
||||
else:
|
||||
@@ -1254,7 +1194,6 @@ class LauncherApp:
|
||||
title_patterns = (
|
||||
TERMINAL_TITLE_PREFIX,
|
||||
TOPIC_MONITOR_TITLE,
|
||||
CMD_VEL_MONITOR_TITLE,
|
||||
CONTROLLER_POSITION_MONITOR_TITLE,
|
||||
CONTROLLER_HZ_MONITOR_TITLE,
|
||||
ROS_GRAPH_MONITOR_TITLE,
|
||||
@@ -1326,24 +1265,21 @@ class LauncherApp:
|
||||
*_xrobotoolkit_cleanup_patterns(stop_pc_service=stop_pc_service),
|
||||
TERMINAL_TITLE_PREFIX,
|
||||
TOPIC_MONITOR_TITLE,
|
||||
CMD_VEL_MONITOR_TITLE,
|
||||
ROS_GRAPH_MONITOR_TITLE,
|
||||
"xr_rm_topic_monitor_",
|
||||
"xr_rm_cmd_vel_monitor_",
|
||||
"xr_rm_controller_position_monitor_",
|
||||
"xr_rm_controller_hz_monitor_",
|
||||
"xr_rm_ros_graph_monitor_",
|
||||
"udp_controller_receiver",
|
||||
"sample_udp_sender",
|
||||
"single_arm_velocity_teleop",
|
||||
"dual_arm_simulator",
|
||||
"ros2 topic echo /xr/left_controller --field pose.position",
|
||||
"ros2 topic echo /xr/right_controller --field pose.position",
|
||||
"ros2 topic echo /xr/left_controller",
|
||||
"ros2 topic echo /xr/right_controller",
|
||||
"ros2 topic hz /xr/left_controller",
|
||||
"ros2 topic hz /xr/right_controller",
|
||||
"ros2 topic echo /xr_rm/left_rm75/cmd_vel",
|
||||
"ros2 topic echo /xr_rm/right_rm75/cmd_vel",
|
||||
"ros2 topic list",
|
||||
"ros2 node list",
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user