| name | teleop-bridge | |||||||
|---|---|---|---|---|---|---|---|---|
| description | Wire a `geniesim_teleop` VR/Pico session into a running Genie Sim RT Engine scene — pick the right scene yaml, launch `wbc.launch.py` with `use_ros2_control:=false` so move_group serves `/compute_ik` while the teleop publisher owns `/joint_command`, and confirm no topic fighting. Trigger: When the user asks to "connect teleop to the sim", "桥接 teleop", "drive the engine with VR", "use teleop instead of ros2_control", "stop the controllers from fighting teleop", or has a teleop loop ready and a scene up but the robot jitters / flicks. | |||||||
| license | MPL-2.0 | |||||||
| metadata |
|
|||||||
| prerequisites |
|
|||||||
| inputs |
|
|||||||
| outputs |
|
- VR teleop loop (
geniesim_teleopskillrun-teleop) and an RT Engine scene (launch-sceneskill) need to share/joint_commandwithout the ros2_control hardware interface rebroadcasting it at the controller-manager update rate. - User sees "the arm jitters / payloads get flung" — that's the classic two-publisher symptom.
- External motion script (e.g.
wok_flip_cmds.py) and MoveIt are both interested in the same topic.
Do not use for:
- Starting the teleop loop itself →
run-teleopskill ingeniesim_teleop. - MoveIt planning with the simulator's controllers driving →
moveit-wbcskill (default mode). - Recording the teleop session →
record-episodeskill.
use_ros2_control:=falseis the bridge switch. With it,wbc.launch.pystartsmove_grouponly (/compute_ik,/compute_fk) and skips the ros2_control node + controller spawners./joint_commandthen has exactly one source: teleop.- Match scene gripper to teleop config.
run-teleopdefaults toG2_omnipicker.json. Usescene_pnp_g2_op(or anyscene_*_g2_op) so the engine is built with the same gripper the teleop loop expects. Mismatched grippers produce a robot MoveIt can plan against but the engine refuses to drive. - Three processes, three shells. Scene + MoveIt + teleop each run as a long-lived ROS node. Don't try to background them in one shell — the engine and teleop both want stdin / SIGINT semantics.
use_sim_time:=trueis engine-side, but the teleop loop publishes wall-clock by default. The bridge uses sim time inside the scene; the publisher rate adapts. Don't override unless you know what you're doing.
- Scene is up via
launch-sceneskill (e.g.scene_pnp_g2_op×launcher_ovrtx_isaac_physx). - Teleop config matches the scene's gripper.
- VR device reachable, default port
8080.
In a fresh shell:
source devel/setup.bash
ros2 launch genie_sim_moveit wbc.launch.py \
arm:=crsB \
gripper:=omnipicker \
use_ros2_control:=falseConsole banner should print:
[wbc.launch.py] use_ros2_control=false → move_group only (no ros2_control
node / controllers); drive the arm via /joint_command.
In another shell (geniesim docker into):
geniesim teleop run \
--device_type=pico \
--port=8080 \
--robot_config=G2_omnipicker.jsonros2 topic info /joint_command -v
# Publishers should list exactly one: the teleop node.If you see two publishers, you forgot use_ros2_control:=false —
stop MoveIt and relaunch with the flag.
Even without ros2_control, /compute_ik is still available. So you
can:
- Use MoveIt's RViz markers to plan and call
/compute_ikfor manual goals. - Hand the resulting joint target to your teleop publisher (or skip MoveIt entirely for direct VR drive).
# Shell 1 — scene
source devel/setup.bash
ros2 launch genie_sim_bringup app.launch.py \
scene:=scene_pnp_g2_op \
launcher_config:=launcher_ovrtx_isaac_physx \
headless:=false # local workstation with a screen; flip to true on a remote/headless host
# Shell 2 — MoveIt, no controllers
source devel/setup.bash
ros2 launch genie_sim_moveit wbc.launch.py \
arm:=crsB gripper:=omnipicker use_ros2_control:=false
# Shell 3 — teleop loop
geniesim teleop run --device_type=pico --port=8080 \
--robot_config=G2_omnipicker.json
# Verify single publisher
ros2 topic info /joint_command -vsimple_body_controlleris configured but not auto-spawned even in the controller mode — it conflicts withsimple_waist_controller+simple_torso_controlleron the same body-joint resources. The teleop bridge avoids that ambiguity by not spawning any of them.- For wok-flip / scripted motion (
wok_flip_cmds.py, benchmark replay scripts), the sameuse_ros2_control:=falseflag applies — anything that owns/joint_commanddirectly needs the controllers out of the way. - The teleop loop has its own per-episode recording hooks
(
--record-dir). For raw-topic recording on top, see therecord-episodeskill.
- Teleop CLI + skill: source/geniesim_teleop/skills/run-teleop/SKILL.md
- MoveIt launch with the bridge switch: source/geniesim_ros/src/ros_ws/src/genie_sim_moveit/launch/wbc.launch.py
- Related skills:
launch-scene,moveit-wbc,record-episode