Skip to main content

Gento (Skye/Luna) ROS 2 Interfaces

This chapter is for customers who need to read Gento state, collect teleoperation data, or connect their own algorithms through Custom mode. The interface contract is based on the latest Gento source as of August 21, 2026.

ItemDescription
ProductsGento Skye and Gento Luna
Interface baselineGento source, August 21, 2026
Reference environmentUbuntu 22.04 and ROS 2 Humble
Default namespace/tj

Available interfaces depend on the delivered release, end-effector configuration, and running modules. Always verify the target system with ros2 topic list -t, ros2 service list -t, and ros2 interface show.

1. Load the ROS 2 environment​

Use the unified environment file when available:

source /etc/apex/apex_ros_env.sh
ros2 topic list -t | sort
ros2 service list -t | sort

If the unified environment file is unavailable:

source /opt/ros/humble/setup.bash
source /opt/kernelmind/apex/install/setup.bash
ros2 topic list -t | sort

Save an interface inventory:

mkdir -p ~/gento_ros_check
ros2 topic list -t | sort | tee ~/gento_ros_check/topic_list.txt
ros2 node list | sort | tee ~/gento_ros_check/node_list.txt
ros2 service list -t | sort | tee ~/gento_ros_check/service_list.txt

If a topic is missing, first verify that the required Robot, Teleop, Camera, or Tool module is running and that ROS_DOMAIN_ID matches.

1.1 Namespace Rules​

Gento Robot, Teleop, QP, and both input-mux nodes use APEX_ROS_NAMESPACE=tj by default. A relative source name such as info/joint_feedback therefore resolves to /tj/info/joint_feedback at runtime.

The following interfaces normally remain in the root namespace:

  • /hand_left/* and /hand_right/*: Wuji dexterous hands;
  • /controller/odom, /move/*, /control/base_*, and /info/base_*: independently launched mobile-base nodes;
  • /quad_tile/* and /recorder/set_recording: independent camera package;
  • /tf, /tf_static, and /rosout: ROS system interfaces.

If an upper-level launch applies /tj to the base nodes, /tj/info/base_* may also appear. Search both root and /tj paths on the target system.

2. Skye and Luna joint differences​

ItemSkyeLuna
robot_typeGento_SkyeGento_Luna
Left arm7 joints7 joints
Right arm7 joints7 joints
BODYLIFT 1 + BODY 2BODY 6
HEAD2 joints2 joints
Default QP rate250 Hz500 Hz
Controller UDP TCP gateDisabled by defaultEnabled by default; requires a TCP 9010 session

Identify the model first:

ros2 topic echo /tj/info/robot_info --once

The BODY topic names are shared, but their arrays differ:

  • Skye: positions[0] is LIFT and positions[1:3] are the two BODY joints. Remaining values are unused for this model.
  • Luna: positions[0:6] are the six BODY joints.
  • JointcmdHead.positions has a fixed length of 3, while both current models use the first two values.

Customer software must identify the model from /tj/info/robot_info. Do not reuse a BODY array between Skye and Luna.

3. Robot state topics​

After Robot starts:

TopicTypeRate / PublicationDescription
/tj/joint_statessensor_msgs/msg/JointStateNormally about 100 HzStandard whole-robot joint names, positions, velocities, and efforts
/tj/info/joint_feedbackmarvin_msgs/msg/JointfeedbackSDK-return driven; target about 500 HzReal-time Gento whole-robot joint feedback; verify the actual rate on the target
/tj/info/robot_statestd_msgs/msg/Int16MultiArrayNormally about 100 HzCurrent ARM, HEAD, BODY, and LIFT states
/tj/info/robot_infomarvin_msgs/msg/RobotInfoImmediately at startup, then about 0.2 HzRobot model and controller version
/tj/info/imu0sensor_msgs/msg/ImuFollows joint feedbackBody IMU data
ros2 topic echo /tj/info/robot_info --once
ros2 topic echo /tj/info/robot_state --once
ros2 topic echo /tj/info/joint_feedback --once
ros2 topic echo /tj/joint_states --once

In Jointfeedback, the 14 arm entries are ordered as left seven followed by right seven. Interpret BODY values according to the model rules above.

The current release creates a publisher for /tj/info/robot_cmd_state, but the source does not publish messages through it. Do not treat it as a customer-facing interface.

4. Headset and teleoperation topics​

After Teleop starts:

TopicTypeRate / PublicationDescription
/tj/control/target_poseLgeometry_msgs/msg/PoseStampedFollows headset inputLeft-arm target mapped from the left controller
/tj/control/target_poseRgeometry_msgs/msg/PoseStampedFollows headset inputRight-arm target mapped from the right controller
/tj/control/enableLstd_msgs/msg/BoolFollows headset input; about 10 Hz in glove modeLeft-arm teleoperation enable
/tj/control/enableRstd_msgs/msg/BoolFollows headset input; about 10 Hz in glove modeRight-arm teleoperation enable
/tj/control/vr_joy_Lsensor_msgs/msg/JoyFollows headset inputLeft-controller buttons and joystick
/tj/control/vr_joy_Rsensor_msgs/msg/JoyFollows headset inputRight-controller buttons and joystick
/tj/control/vr_bodymarvin_msgs/msg/VrBodyFollows headset inputTorso, head, elbow, leg, and other full-body tracking data
/tj/info/vr_connectedstd_msgs/msg/Bool1 HzHeadset connection state
/tj/info/eef_leftgeometry_msgs/msg/PoseStampedTarget 1000 HzCurrent left end-effector pose; actual rate depends on system load
/tj/info/eef_rightgeometry_msgs/msg/PoseStampedTarget 1000 HzCurrent right end-effector pose; actual rate depends on system load
/tj/info/teleop_motion_modestd_msgs/msg/Int32Event-driven0=full body, 1=arms only, 2=arms and head
/tj/info/body_pose_modestd_msgs/msg/Int32Event-driven0=skeleton, 1=neck_head_pose

VrBody contains left/right elbow, torso, head, pelvis, left/right foot, and left/right knee poses with matching available flags. A pose must not be treated as valid when its flag is false.

ros2 topic echo /tj/info/vr_connected --once
ros2 topic echo /tj/control/target_poseL --once
ros2 topic echo /tj/control/target_poseR --once
ros2 topic echo /tj/control/vr_body --once
ros2 topic echo /tj/info/eef_left --once
ros2 topic echo /tj/info/eef_right --once

Current Skye releases may not use the TCP connection state as the teleoperation gate. Do not diagnose Skye from /tj/info/vr_connected alone; also verify target-pose and enable updates.

The current release creates publishers for /tj/control/eef_cmd_A, /tj/control/eef_cmd_B, /tj/info/collision_statusA, and /tj/info/collision_statusB, but the source does not publish messages through them. Do not treat them as customer-facing interfaces.

4.1 Control-Chain Observation Interfaces​

Use these topics to identify whether a fault is in Teleop, IK/QP, or final command output. Customer programs must not publish directly to QP outputs or final command topics.

TopicTypeRate / PublicationDescription
/tj/control/teleop/ik_requestmarvin_msgs/msg/IKRequestTarget 1000 HzWhole-body IK request generated by Teleop
/tj/control/replay/ik_requestmarvin_msgs/msg/IKRequestFollows recorded timestampsIK request generated by Replay
/tj/control/ik_requestmarvin_msgs/msg/IKRequestFollows the active sourceRequest selected by the IK Mux
/tj/control/qp_controller/joint_cmd_Amarvin_msgs/msg/JointcmdArmSkye 250 Hz; Luna 500 HzQP left-arm output
/tj/control/qp_controller/joint_cmd_Bmarvin_msgs/msg/JointcmdArmSkye 250 Hz; Luna 500 HzQP right-arm output
/tj/control/qp_controller/joint_cmd_bodymarvin_msgs/msg/JointcmdBodySkye 250 Hz; Luna 500 HzQP body output
/tj/control/qp_controller/joint_cmd_headmarvin_msgs/msg/JointcmdHeadSkye 250 Hz; Luna 500 HzQP head output
/tj/control/joint_cmd_Amarvin_msgs/msg/JointcmdArmSteady state: Skye 250 Hz, Luna 500 Hz; about 100 Hz while switchingFinal left-arm command selected by Joint Mux
/tj/control/joint_cmd_Bmarvin_msgs/msg/JointcmdArmSteady state: Skye 250 Hz, Luna 500 Hz; about 100 Hz while switchingFinal right-arm command selected by Joint Mux
/tj/control/joint_cmd_bodymarvin_msgs/msg/JointcmdBodySteady state: Skye 250 Hz, Luna 500 Hz; about 100 Hz while switchingFinal body command selected by Joint Mux
/tj/control/joint_cmd_headmarvin_msgs/msg/JointcmdHeadSteady state: Skye 250 Hz, Luna 500 Hz; about 100 Hz while switchingFinal head command selected by Joint Mux

5. Custom whole-body command interfaces​

Customer algorithms publish to the user topics:

TopicTypeRate / PublicationDescription
/tj/control/user/joint_cmd_Amarvin_msgs/msg/JointcmdArmDefined by the customer programSeven left-arm joint targets in radians
/tj/control/user/joint_cmd_Bmarvin_msgs/msg/JointcmdArmDefined by the customer programSeven right-arm joint targets in radians
/tj/control/user/joint_cmd_bodymarvin_msgs/msg/JointcmdBodyDefined by the customer programSkye LIFT+BODY or Luna BODY targets
/tj/control/user/joint_cmd_headmarvin_msgs/msg/JointcmdHeadDefined by the customer programHEAD targets; current models use the first two values

Message layouts:

JointcmdArm:  std_msgs/Header header + float64[7] positions
JointcmdBody: std_msgs/Header header + float64[6] positions
JointcmdHead: std_msgs/Header header + float64[3] positions

Verify the installed definitions:

ros2 interface show marvin_msgs/msg/JointcmdArm
ros2 interface show marvin_msgs/msg/JointcmdBody
ros2 interface show marvin_msgs/msg/JointcmdHead

5.1 Enable sequence​

  1. Clear the robot workspace and keep the emergency stop within reach.
  2. Start Robot in Apex Teleop and set the robot Ready.
  3. Select Impedance Mode and execute Home.
  4. Set Input Mode to Custom, or call:
ros2 service call /tj/control/set_input \
marvin_msgs/srv/Int "{data: 3}"
  1. Continuously publish complete left-arm, right-arm, BODY, and HEAD targets for the identified model.
  2. Switch back to None before stopping:
ros2 service call /tj/control/set_input \
marvin_msgs/srv/Int "{data: 0}"

The system performs a smooth transition when the source changes. Output may remain inactive until initial feedback is available and all required targets have valid timestamps.

5.2 Safety constraints​

  • Start with small, slow, continuous targets and avoid steps.
  • Use current timestamps; stale commands may be rejected.
  • Respect position, velocity, and mechanical limits.
  • Do not publish directly to final /tj/control/joint_cmd_A/B/body/head topics.
  • Do not call internal native mux selectors; customers should use /tj/control/set_input.
  • If the customer process exits unexpectedly, immediately switch to None or trigger a safe stop.

6. Customer-facing services​

ServiceTypeDescription
/tj/control/set_readystd_srvs/srv/TriggerAllows real-time robot commands
/tj/control/set_modemarvin_msgs/srv/IntChanges whole-robot control mode
/tj/control/go_homestd_srvs/srv/TriggerMoves to the model-specific Home pose
/tj/control/clear_faultstd_srvs/srv/TriggerClears controller faults
/tj/control/set_inputmarvin_msgs/srv/IntCompatibility index: 0=None, 1=Teleop, 2=Planner, 3=Custom, 4=Replay
/tj/control/set_teleop_motion_modemarvin_msgs/srv/Int0=full body, 1=arms only, 2=arms and head
/tj/control/set_body_pose_modemarvin_msgs/srv/Int0=skeleton, 1=neck_head_pose
/tj/control/reset_grippersstd_srvs/srv/TriggerResets and re-enables the configured DM/ZY grippers
ros2 service call /tj/control/clear_fault std_srvs/srv/Trigger "{}"
ros2 service call /tj/control/set_ready std_srvs/srv/Trigger "{}"
ros2 service call /tj/control/set_mode marvin_msgs/srv/Int "{data: 3}"
ros2 service call /tj/control/go_home std_srvs/srv/Trigger "{}"

set_mode manages ARM, HEAD, BODY, and LIFT according to the Skye or Luna configuration. Prefer Apex Teleop for Ready, mode, and Home operations during normal use.

7. End effectors​

End-effector topics appear only when the matching hardware and driver are configured.

DM / ZY gripper​

TopicTypeRate / PublicationDescription
/tj/control/gripperValueLstd_msgs/msg/Float32Follows control inputLeft gripper target
/tj/control/gripperValueRstd_msgs/msg/Float32Follows control inputRight gripper target
/tj/info/gripper_feedback_Lstd_msgs/msg/Float32MultiArray200 HzLeft gripper feedback
/tj/info/gripper_feedback_Rstd_msgs/msg/Float32MultiArray200 HzRight gripper feedback
/tj/info/gripper_feedback_L_errstd_msgs/msg/Int32MultiArray200 HzLeft gripper error codes
/tj/info/gripper_feedback_R_errstd_msgs/msg/Int32MultiArray200 HzRight gripper error codes

Wuji dexterous hand​

TopicTypeRate / PublicationDescription
/hand_left/joint_commandssensor_msgs/msg/JointStateFollows control inputLeft-hand joint target
/hand_right/joint_commandssensor_msgs/msg/JointStateFollows control inputRight-hand joint target
/hand_left/joint_statesVerify on targetDefined by driver configurationLeft-hand joint feedback
/hand_right/joint_statesVerify on targetDefined by driver configurationRight-hand joint feedback
ros2 topic list -t | grep -E "gripper|hand"

8. Camera topic​

Gento video is normally carried over H.264/WebRTC. The current camera component generates the four-camera mosaic at 30 Hz by default, while most ROS image topics publish on demand. Verify the actual rate from the deployed configuration and target system.

TopicTypeFormatRate / PublicationDescription
/quad_tile/compressedsensor_msgs/msg/CompressedImageh264Published when subscribed; default maximum 30 HzRaw four-camera mosaic
/quad_tile/compressed_undistortedsensor_msgs/msg/CompressedImageh264Published when subscribed; default maximum 30 HzMosaic processed according to each slot's calibration
/quad_tile/jpeg/compressedsensor_msgs/msg/CompressedImagejpegPublished when subscribed; default maximum 30 HzProcessed JPEG mosaic, default 640x360
/camera/<name>/depth/image_rawsensor_msgs/msg/Image16UC1Depth and raw publication enabledRaw D405 depth image
/camera/<name>/depth/image_raw/compressedsensor_msgs/msg/CompressedImageh264Depth enabled and a subscriber existsD405 grayscale-mapped depth stream

For per-camera NV12 topics, slot configuration, recording services, and diagnostics, see Camera Configuration and ROS Interfaces. WebRTC may still work when ROS image topics are absent.

ros2 topic list -t | grep -Ei "camera|image|compressed|quad|usb_cam"

9. Input Mux, Replay, and Mobile Base​

9.1 Two-Level Input Mux​

Gento uses two input-mux layers. Customer programs normally select the final joint-command source through /tj/control/set_input:

TopicTypeRate / PublicationDescription
/tj/info/ik_request_mux/active_sourcestd_msgs/msg/Int32Event-driven and latchedIK source: 0=Teleop, 1=Replay
/tj/info/joint_cmd_mux/active_sourcestd_msgs/msg/Int32Event-driven and latchedNative source index: -1..3
/tj/control/input_modestd_msgs/msg/Int32Event-driven and latchedCompatibility index: 0=None, 1=Teleop, 2=Planner, 3=Custom, 4=Replay
/tj/info/joint_cmd_mux/latest_joint_cmdsensor_msgs/msg/JointStateFollows final joint commandsLatest complete joint-command snapshot

The controller transitions smoothly from current joint feedback when the source changes. Publishing to user topics without selecting Custom does not activate those commands.

9.2 Gento Replay​

InterfaceTypeRate / InvocationDescription
/tj/info/gento_replay/statusstd_msgs/msg/StringAbout 2 HzReplay JSON status
/tj/control/gento_replay/recordmarvin_msgs/srv/IntCalled on demanddata=1 starts recording; data=0 stops
/tj/control/gento_replay/playbackmarvin_msgs/srv/IntCalled on demanddata=1 starts playback; data=0 stops
/tj/control/gento_replay/record_namedmarvin_msgs/srv/GentoReplayCalled on demandStarts or stops a named recording
/tj/control/gento_replay/playback_namedmarvin_msgs/srv/GentoReplayCalled on demandStarts or stops named playback

New Gento integrations should use gento_replay. The old /recorder/* and /playback_* topics belong to the compatibility path and are not recommended for new customer applications.

9.3 Mobile Base​

Mobile-base nodes are normally launched independently in the root namespace:

Topic / ServiceTypeRate / InvocationDescription
/controller/odomnav_msgs/msg/OdometryDefined by the base driverBase odometry
/move/Statemove/msg/StateDefined by the base driverBase state
/move/ManualMoveCmdgeometry_msgs/msg/TwistStamped100 Hz while the corresponding mode is activeManual velocity command
/info/base_local_statemove/msg/StateFollows /move/StateState relative to the reset origin
/info/base_teleop/active_modestd_msgs/msg/Int32Event-driven and latched0=off, 1=joy, 2=wholebody
/control/base_local_resetstd_srvs/srv/TriggerCalled on demandResets the local base origin
/control/base_teleop/set_modemarvin_msgs/srv/IntCalled on demandSelects the base teleoperation mode

If these interfaces are absent, also check /tj/info/base_* and /tj/control/base_* in case the delivered launch applies the robot namespace to the base nodes.

10. Topic Rate Reference​

Gento control-loop and topic rates differ from Marvin Pro. The following values come from the current Skye/Luna source and default parameters and are not hard real-time guarantees.

Topic / chainSkyeLunaNotes
/tj/info/eef_left/right1000 Hz1000 HzMotion timer target; actual rate depends on load
/tj/control/teleop/ik_request1000 Hz1000 HzTeleop running
/tj/control/qp_controller/joint_cmd_*250 Hz500 HzReady, Home, and IK data are valid
/tj/control/joint_cmd_*Normally 250 HzNormally 500 HzMux steady-state pass-through; about 100 Hz during source transition
/tj/info/joint_feedbackTarget about 500 HzTarget about 500 HzSDK-return driven; verify the actual rate on the target
/tj/joint_states, /tj/info/robot_stateNormally about 100 HzNormally about 100 HzPublished every fifth successful joint-feedback cycle; actual rate follows feedback
/tj/info/gripper_feedback_L/R and error topics200 Hz200 HzDefault DM/ZY Tool configuration
/tj/info/gento_replay/status2 Hz2 HzEvery 500 ms while Replay is running
/move/ManualMoveCmd, /target_pose100 Hz100 HzWhile the corresponding base mode is active

Headset topics follow actual UDP packets, camera topics follow camera configuration, and event topics such as mode, source, and static TF have no continuous-rate requirement. The 1000 Hz internal gripper CAN loop does not mean the ROS feedback topics run at 1000 Hz.

source /etc/apex/apex_ros_env.sh

ros2 topic info -v /tj/info/joint_feedback --no-daemon
ros2 topic info -v /tj/joint_states --no-daemon

ros2 topic hz /tj/info/eef_left
ros2 topic hz /tj/control/teleop/ik_request
ros2 topic hz /tj/control/qp_controller/joint_cmd_A
ros2 topic hz /tj/control/joint_cmd_A
ros2 topic hz /tj/info/joint_feedback
ros2 topic hz /tj/joint_states
ros2 topic hz /tj/info/gripper_feedback_L

After startup or a control-source change, wait for the roughly two-second Mux transition before measuring final joint commands. Check publisher count first, and run formal full-load tests for at least 120 seconds.

CategoryRecommended topics
Whole-robot joint feedback/tj/joint_states, /tj/info/joint_feedback
Robot state/tj/info/robot_state, /tj/info/robot_info
End-effector pose/tj/info/eef_left, /tj/info/eef_right
Headset targets and enable/tj/control/target_poseL/R, /tj/control/enableL/R, /tj/control/vr_body
Customer command input/tj/control/user/joint_cmd_A/B/body/head
Gripper or dexterous handSelect according to the installed end effector
Video/quad_tile/jpeg/compressed only when enabled on the target

Before recording, use ros2 topic info -v, ros2 topic echo --once, and ros2 topic hz to verify that each topic exists and carries valid data.

To add body, head, or end-effector topics to recording, playback, or frontend forwarding, see Topic whitelist configuration and diagnostics.

12. Minimum Diagnostic Set​

source /etc/apex/apex_ros_env.sh
echo "ROS_DOMAIN_ID=${ROS_DOMAIN_ID}"
ros2 topic echo /tj/info/robot_info --once
ros2 topic echo /tj/info/robot_state --once
ros2 topic echo /tj/info/joint_feedback --once
ros2 topic echo /tj/info/vr_connected --once
ros2 topic info /tj/control/target_poseL -v
ros2 topic info /tj/control/user/joint_cmd_A -v
ros2 topic echo /tj/control/input_mode --once
SymptomCheck first
No /tj/info/robot_infoRobot is not running, or the ROS environment, namespace, or domain differs
RobotInfo exists but no joint feedbackRobot-controller communication
No headset target updatesTeleop, headset connection, network, and enable state
Custom topics have publishers but no motionReady, Impedance Mode, Home, Input Mode, timestamps, and complete targets
Arms work but BODY does notModel identification, BODY ordering, and component state
Gripper target exists but no motionTool, driver, power, and hardware connection
No compressed image topicVerify whether ROS compressed publication is enabled; WebRTC may still work

Trace state feedback, customer input, active Input Mode, and robot motion in sequence. The existence of one topic alone does not prove that the entire chain is healthy.