Skip to main content
The Ghost Robotics Vision60 + Ghost Arm as GRID drives it — what this robot actually implements, with the signatures it actually accepts. connect("<name>") returns a RemoteRobot. Its attributes are the methods and subcomponents below, and every call runs on the robot; the driver behind it is Vision60WithArm. Connecting neither starts nor moves the robot — it attaches to one that is already up. A method that fails on the robot arrives as RuntimeError naming the original error in its message. The client packages this page uses are preinstalled in every GRID session workspace and in the Python environment the GRID CLI prepares when you run a program with skill run; there is nothing to install.

Methods on the robot

Called as robot.<method>(...).

cleanup()

Signature
Shut down the robot tree; alias kept for the historical Vision60 API. Equivalent to shutdown(): recursive, idempotent, best-effort.

enableWalking()

Signature
Enable walking mode for the robot.

getGPS()

Signature
Return latest GPS data: position, orientation, linear & angular velocity. Returns: A dict with position, orientation, linear_velocity, and angular_velocity — or None if no GPS message has been received yet.

getIMU()

Signature
Get the latest IMU reading. Returns: A dict with orientation, angular_velocity, and linear_acceleration — or None if no IMU message has been received yet.

getImage()

Signature
Return the image of camera. Which camera a no-argument call reads is decided by cardinality alone — no robot, config, or class declares a default. A robot with exactly one camera needs no name; a robot with several requires one, so adding a second camera never silently changes which one a bare getImage() returns.
str
default:"''"
Name of the camera to get image from — either a directly attached camera’s name or a /-separated path through subcomponents to a nested one (left_arm/wrist). May be omitted when the robot has exactly one camera.
Forwarded to the underlying sensor’s getImage. Lets callers pass camera-specific options (e.g. image_type="depth", compressed=False) without the base class having to enumerate them.
Returns: Image: The captured image. Raises: RuntimeError: If no cameras are configured, or the name is omitted on a robot with more than one camera; the message lists every configured camera path. KeyError: If camera_name is given but names no camera on this robot.

getLidarPointCloud()

Signature
Get a point cloud from the named LiDAR sensor.
str
default:"''"
Name of the lidar. If empty, uses the first available lidar.
Returns: Optional[PointCloud]: The point cloud, or None if lidar not found

getOrientation()

Signature
Get the robot orientation from odometry data. Returns: World-frame orientation, or None if no odometry message has been received yet.

getPoseRel()

Signature
Return the body pose from the Vision60 mcu/state/rel_pose topic. Ghost’s firmware publishes this as a PoseStamped where the orientation is the body’s attitude relative to a gravity-aligned ground frame (from the onboard IMU/EKF). The position field does not carry a world-frame position — on the hardware sampled, x and y read zero and z a small non-zero value — so use getPosition() / getState() when world-frame position is what’s wanted. Returns: Body pose whose orientation is the gravity-relative attitude and whose position is not a world-frame position, or None if no message has been received yet.

getPosition()

Signature
Get the robot position from odometry data. Returns: World-frame position, or None if no odometry message has been received yet.

getState()

Signature
Get a live state snapshot of this component’s tree. Recursive walk owned by the base class, following the lifecycle template: each class contributes only the protected local hook _local_state, and the walk composes the per-component results into one nested mapping. Subclasses must not replace this method — per-component state belongs in _local_state. With no keys, returns this component’s local state merged with one nested node per subcomponent name — the tree structure is the nesting itself, and the names mirror subcomponents (and therefore serialize() and edge introspection): a two-arm rig returns &#123;"left_arm": &#123;"joint_positions": ...&#125;, "right_arm": &#123;...&#125;&#125;, and a leaf component returns its local state alone. A component whose state could not be read (dead telemetry, not yet started, already shut down) carries an "error" entry — &#123;"error": "&lt;ExceptionType>: &lt;message>"&#125;, with its children still nested alongside — instead of its state keys. Errors are contained per node: one failing component never loses the rest of the snapshot, and the walk still descends into the failing component’s children. "error" is reserved for that purpose, and local state keys must not collide with subcomponent names; a hook violating either is reported as that node’s error. With keys, returns a flat mapping with one entry per match. Each key is a /-separated path through the component tree: every segment names a subcomponent, and the final segment may instead name an entry in that component’s local state. Because structure is the nesting, a literal path is the same as plain indexing — getState(["left_arm/joint_positions"]) returns the value of getState()["left_arm"]["joint_positions"] — and a path ending on a subcomponent yields that component’s full nested node. Segments may use shell-style wildcards over subcomponent names — * matches within one chunk and ** matches any chain of chunks — so "*_arm/joint_positions" fans out to one entry per arm, keyed by the concrete matched path. Wildcards never match state entries; only a literal final segment does. A key that matches nothing raises, so a typo is loud rather than silently absent. A matched component whose state read failed yields &#123;"error": "..."&#125; at its path. Keyed reads are lazy: a hook runs only where a key lands — a literal path executes the final component’s hook alone (not the nodes traversed on the way), a glob executes only the matched nodes, and each component’s hook runs at most once per call however many keys reach it. Components with a selective-read hook (_local_state_entries — every Robot with registered state getters) go further and execute only the getters a key names, so a ** glob probes their registries without touching hardware. The caller pays only for the state actually requested; ** and the no-keys form visit the whole tree because that is the request. State is cheap by convention: local state carries kinematics, status, and health — never bulk sensor payloads (camera frames, point clouds, scans), which stay in their dedicated methods (getImage, getPointCloud, …). Callable on a stopped tree — reading state after a soft e-stop is when it matters most — and on a partially started one, where unstarted components report a per-node error instead of failing the call.
State paths to read, or None for the full nested snapshot. A single string is shorthand for a one-element list.
Returns: The nested state snapshot when keys is None, otherwise a flat mapping of matched path to state value or nested node. Raises: TypeError: If keys is neither None, a string, nor a list/tuple of strings. ValueError: If a key is empty, has an empty path segment, or matches no subcomponent path or state entry.

getVelocity()

Signature
Return the latest body-frame linear velocity (m/s). Angular velocity is available via getIMU() or getState(). Returns: Body-frame linear velocity, or None if no base-velocity message has been received yet.

lieDown()

Signature
Make the robot lie down.

moveByVelocity()

Signature
Command body-frame twist. The command is republished at _CMD_RATE_HZ Hz until a new command (including stop) is issued, or until duration seconds elapse — Vision60’s controller treats a gap as “stop”, so continuous republish is required to hold a velocity.
required
Body-frame linear velocity (m/s).
required
Body-frame angular velocity (rad/s); only the z component is used for yaw.
default:"'body'"
Reference frame. Only "body" is supported.
default:"1.0"
Seconds to hold the command. Pass None to republish indefinitely until stop().
Raises: NotImplementedError: If frame == "world" (matches Go2; world frame is not supported on Vision60). ValueError: If frame is any value other than "body" or "world".

setDefaultJointAngles()

Signature
Set the default joint position for the robot.
required
Value of the joint position.

setDefaultJointVelocities()

Signature
Set the default joint velocity for the robot.
required
Value of the joint velocity.

standUp()

Signature
Make the robot stand up.

stop()

Signature
Halt all motion across this component’s tree (soft e-stop). Recursive walk owned by the base class: every subcomponent is stopped first (children before their parent, leaf-to-root; siblings in subcomponents insertion order), then this component’s own _stop_self hook runs. The walk is best-effort — a failing component never prevents the rest of the tree from being stopped; failures are collected and raised together after the walk completes. Components (and their subtrees) that have already been shut down are skipped. Safe to call repeatedly: stopping an already-stopped tree re-runs the hooks, which must tolerate that. Blocks until every hook has returned. Stops motion only; resources stay live and the component remains usable — telemetry and every other public method keep working on a stopped tree. Use shutdown to release resources. Stopping re-arms each visited component, so a later start re-runs the bring-up hooks — that is the stop-then-start restart path — but it does not revoke callability: only shutdown does that. Subclasses must not replace this method — per-component stop behavior belongs in _stop_self. An override may only extend the walk (adding a driver-specific mode, as UR5e does with its immediate escape hatch) and must delegate to super().stop() for the normal path; it must never re-implement the recursion. Raises: ComponentStopError: If one or more stop hooks raised. The walk still visited every component; the exception carries every (component_path, exception) pair.

robot.front_left and 4 more — camera

Reached as any of robot.front_left, robot.front_right, robot.rear, robot.side_left, robot.side_right; each is a Vision60Camera and its methods are Vision60Camera’s and run on the robot. Below, <camera> stands for any one of those names. Camera sensor for the Vision60, bridging a ROS 2 Image topic to the Methods inherited from the component base are shown in brief here; their full descriptions are under Methods on the robot above.

<camera>.cleanup()

Signature
Cleanup camera resources (no-op; shared node owned by caller).

<camera>.getCameraExtrinsics()

Signature
Get the extrinsic parameters for the camera.

<camera>.getCameraIntrinsics()

Signature
Get the intrinsic parameters for the camera.

<camera>.getCameraSettings()

Signature
Get the camera settings.

<camera>.getData()

Signature
Get the image from the camera.

<camera>.getImage()

Signature
Read image from shared memory file path. Returns: The latest image as an Image object, or None if no image message has been received yet.

<camera>.getState()

Signature
Get a live state snapshot of this component’s tree.

<camera>.recordCalibration()

Signature
Install a recorded extrinsic calibration on this camera in place.

<camera>.reloadCalibration()

Signature
Re-read this camera’s calibration from the robot’s config and install it.

<camera>.setCameraExtrinsics()

Signature
Set the extrinsic parameters for the camera.

<camera>.setCameraIntrinsics()

Signature
Set the intrinsic parameters for the camera.

<camera>.setCameraSettings()

Signature
Set the camera settings.

<camera>.stop()

Signature
Halt all motion across this component’s tree (soft e-stop).

robot.arm — arm

Reached as robot.arm; its methods are Vision60Arm’s and run on the robot. Control the Ghost Robotics arm mounted on a Vision60 via ROS 2. Methods inherited from the component base are shown in brief here; their full descriptions are under Methods on the robot above.

arm.addNamedPose()

Signature
Define a pose_name:joint_angles pair in the dictionary of named poses

arm.ensureMode()

Signature
Set a mode and confirm it via the /state/heartbeat echo. Falls back to fire-and-forget when ghost_manager_interfaces is not available or no heartbeat has been received yet.
required
Mode field name (see setMode).
required
Desired value.
default:"50"
Maximum publish-and-check attempts.
default:"0.1"
Pause between attempts.
Raises: ValueError: If field_name is not a known Ghost mode field. RuntimeError: If the heartbeat doesn’t confirm the mode within the retry budget.

arm.getEndEffectorPose()

Signature

arm.getImage()

Signature
Return the image of camera.

arm.getJointAngles()

Signature
Get current arm joint angles, sliced from the body’s jointURDF. Returns: Joint angles in radians (length _NUM_JOINTS). Raises: RuntimeError: If no jointURDF message has been received, or the message doesn’t contain enough joint values to slice.

arm.getJointVelocities()

Signature
Get current arm joint velocities, sliced from the body’s jointURDF. Returns: Joint velocities in rad/s. Raises: RuntimeError: If no jointURDF message has been received, or the velocity field is empty.

arm.getLidarPointCloud()

Signature
Get a point cloud from the named LiDAR sensor.

arm.getNamedPose()

Signature
Get the list of joint angles corresponding to a named pose.

arm.getOrientation()

Signature
Return the EE orientation. Delegates to getPose. Raises: NotImplementedError: See getPose.

arm.getPosition()

Signature
Return the EE position. Delegates to getPose. Raises: NotImplementedError: See getPose.

arm.getState()

Signature
Get a live state snapshot of this component’s tree.

arm.grasp()

Signature
Close the gripper to closed_position.

arm.moveByVelocity()

Signature
Publish a single EE twist to /mcu/command/arm/ee_twist. Ghost arm EE twist is expected to be republished by the caller at high rate for sustained motion — this method publishes once and returns.
required
Linear velocity in m/s.
required
Angular velocity in rad/s.
default:"'body'"
Reference frame is determined by the ARM_C_B_FRAME parameter on the robot. The argument is accepted for interface compatibility but does not change the frame.

arm.moveToDeltaPose()

Signature
Offset the robot end effector by the specified delta pose from its current pose

arm.moveToHome()

Signature
Move the arm to its predefined home pose.

arm.moveToNamedPose()

Signature
Move the robot to the joint angles of a named pose.

arm.moveToPose()

Signature
Send an end-effector pose target to /mcu/command/arm/ee_pose. The active EE frame (body vs. gripper) is determined by the ARM_C_B_FRAME parameter on the robot. Set it via setParam if you need to change frames.
required
Target EE pose (position in meters, orientation as a unit quaternion).
default:"True"
If True, republish for moving_time seconds at publish_rate_hz.
default:"2.0"
Hold duration in seconds when blocking.
default:"100.0"
Republish rate (the Ghost docs recommend 100 Hz for sustained pose commands).

arm.release()

Signature
Open the gripper to open_position.

arm.removeNamedPose()

Signature
Remove a named pose from the dictionary of pose_name:joint_angles pairs.

arm.setControlMode()

Signature
Publish to /command/setControlMode. Lower values have higher priority; the Ghost docs recommend 140 for ROS 2 control and 180 for app/MAVLink.

arm.setGripperPosition()

Signature
Publish a raw gripper position command (Float32).

arm.setGripperVelocity()

Signature
Publish a raw gripper velocity command (Float32).

arm.setJointAngles()

Signature
Publish target joint angles for the arm. Joint position commands take precedence over joint velocity commands on the Ghost arm, so only the position field of the JointState message is set. Pass length _NUM_JOINTS to leave the gripper joint held constant, or _NUM_JOINTS + 1 to command the full arm.
required
Target joint angles in radians. Length must be _NUM_JOINTS or _NUM_JOINTS + 1.
default:"True"
If True, republish the command for moving_time seconds at publish_rate_hz. If False, publish once.
Hold duration in seconds when blocking. Defaults to 2.0 seconds when blocking and unset.
default:"20.0"
Republish rate while blocking.
Raises: ValueError: If angles does not have length _NUM_JOINTS or _NUM_JOINTS + 1.

arm.setJointVelocities()

Signature
Publish target joint velocities for the arm.
required
Target joint velocities in rad/s. Length must be _NUM_JOINTS or _NUM_JOINTS + 1.
default:"1.0"
Seconds to republish the command.
default:"20.0"
Republish rate in Hz.
Raises: ValueError: If velocities does not have length _NUM_JOINTS or _NUM_JOINTS + 1.

arm.setMode()

Signature
Publish a robotMode command (fire-and-forget). Use ensureMode for confirmed sets.
required
Mode field name (e.g. "arm", "action", "vision_mode").
required
Desired value for that field.
Raises: ValueError: If field_name is not a known Ghost mode field.

arm.setParam()

Signature
Set a robot or planner parameter via /mcu/command/param. Confirmed by the matching /mcu/state/param echo.
required
Parameter name (e.g. "ARM_PREDEF_CFG", "ARM_PAYLOAD").
required
Parameter value as a list of floats.
default:"False"
True for planner parameters, False for robot parameters.
default:"10"
Maximum publish-and-check attempts.
default:"0.05"
Pause between attempts.
Raises: RuntimeError: If ghost_manager_interfaces is not installed, or the parameter set is not confirmed within the retry budget.

arm.setPredefinedConfig()

Signature
Send the arm to a predefined configuration via ARM_PREDEF_CFG. Valid values per the Ghost low-level parameters doc are 0 (None) and 1..8 (predefined configs). The robot resets the parameter automatically once the arm reaches or fails the requested config.
required
Predefined config id in [0, 8].
Raises: ValueError: If config_id is outside the range [0, 8]. RuntimeError: If ghost_manager_interfaces is not available or the parameter set is not confirmed within the retry budget.

arm.stop()

Signature
Halt all motion across this component’s tree (soft e-stop).

arm.stow()

Signature
Stow the arm to its rest configuration. Raises: RuntimeError: If the heartbeat doesn’t confirm arm_fsm == 0 within the retry budget.

arm.unstow()

Signature
Unstow the arm so it accepts motion commands. Raises: RuntimeError: If the heartbeat doesn’t confirm arm_fsm == 1 within the retry budget (only checked when ghost_manager_interfaces is available).

arm.validateGrasp()

Signature
Check whether the end effector is currently holding an object.

robot.vision60_lidar — lidar

Reached as robot.vision60_lidar; its methods are Vision60Lidar’s and run on the robot. LiDAR sensor for the Vision60, bridging a ROS 2 PointCloud2 topic. Methods inherited from the component base are shown in brief here; their full descriptions are under Methods on the robot above.

vision60_lidar.cleanup()

Signature
Cleanup lidar resources (no-op; shared node owned by caller).

vision60_lidar.getData()

Signature

vision60_lidar.getPointCloud()

Signature
Return the most recently received point cloud, or None.

vision60_lidar.getState()

Signature
Get a live state snapshot of this component’s tree.

vision60_lidar.stop()

Signature
Halt all motion across this component’s tree (soft e-stop).

Not implemented on this robot

Declared by the interface, raises NotImplementedError here: getJointAngles, getJointStates, setJointAngles, arm.endFreeDrive, arm.followJointTrajectory, arm.getPose, arm.startFreeDrive.

Lifecycle and configuration

The driver’s own bring-up and configuration hooks. The edge runs them when the robot comes up; do not call them from a program. Note that robot.shutdown() on the proxy is not the method below — it is RemoteRobot.shutdown(), which closes your connection and leaves the robot as it was.
  • addSensor() — Add an external sensor to the robot.
  • addSubcomponent() — Attach a child component under a name.
  • builtin_subcomponents() — Declare the five on-board cameras the Vision60 always ships with.
  • configHash() — Hash this component’s serialized config subtree.
  • config_schema()
  • from_config() — Construct this component and its config-declared subtree.
  • getIdentity() — Get this component’s own hardware identity (serial, model, version, MAC).
  • getRobotId() — Stable, readable identifier for a robot or rig, for a database key.
  • serialize() — Serialize this component tree back to its config envelope.
  • setup_shutdown_handlers() — Register the process-wide atexit and signal handlers for safe teardown.
  • shutdown() — Shut down this component’s tree, halting motion and releasing resources.
  • start() — Bring this component’s tree online (connect, enable, arm).
The contract these methods implement is Robot interface; values returned are grid-types (camera reads return Image — call decode() for an ndarray). You reach the robot through connect.