Repository navigation
Add Reach Alpha 5 device id and manipulator arm messages - #315
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ManipulatorCtrl moves a manipulator arm by velocity, read in a control mode: cylindrical (the drone default) or cartesian in the drone frame. The arm velocities use the names and signs of MotionInput, so the same stick can drive the drone or the arm, and a speed modifier scales the drone's default speed down or up. The jaw and wrist velocities are the existing GripperVelocities; ManipulatorCtrl supersedes GripperCtrl while it keeps arriving, so clients that only send GripperCtrl keep working. ManipulatorPoseCtrl sends the arm to a named pose, stowed or deployed. ManipulatorTel reports the joint positions, the end position in the drone frame, and whether a joint limit, a collision or a fault stops the arm. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The protocol additions are consistent, documented, and compatible with existing generation workflows.
Review effort: Balanced
Findings: None
What changed in this PR
Adds protocol support for the Reach Robotics Reach Alpha 5 manipulator.
Changes:
- Adds device ID 52.
- Defines velocity, pose, and telemetry schemas.
- Adds manipulator control and telemetry messages.
| File | Description |
|---|---|
protobuf_definitions/message_formats.proto |
Defines manipulator data types and device ID. |
protobuf_definitions/control.proto |
Adds velocity and named-pose commands. |
protobuf_definitions/telemetry.proto |
Adds manipulator state telemetry. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
johannesschrimpf
left a comment
There was a problem hiding this comment.
I’d prefer extending GripperCtrl with arm input instead of introducing a separate ManipulatorCtrl. This keeps one command path and avoids arbitration between legacy gripper commands and manipulator commands.
Preserve gripper_velocities at field 1 and use a oneof for the arm input:
message GripperCtrl {
GripperVelocities gripper_velocities = 1;
oneof arm_input {
CartesianManipulatorInput cartesian = 2;
CylindricalManipulatorInput cylindrical = 3;
}
float speed_modifier = 4;
}The Cartesian input would contain x, y, z; the cylindrical input would contain radial, vertical, azimuth. Document the reference frames, positive directions, and normalized ranges for each.
This also removes the need for a separate control-mode field: the selected input determines how to interpret the command, and the two cannot disagree. Telemetry could still report the active mode if useful.
These names avoid overloading surge to mean radial extension, which is no longer forward relative to the drone once the arm swings sideways. Existing clients can continue sending their current commands; absent arm input should mean no arm movement, with consistent stop/watchdog behavior.
Following review: one command path instead of a separate ManipulatorCtrl, so there is no arbitration between gripper and manipulator commands. GripperCtrl keeps gripper_velocities at field 1 and gains an arm_input oneof, CartesianManipulatorInput (x, y, z in the drone body frame) or CylindricalManipulatorInput (radial, vertical, azimuth about the arm's base axis), and speed_modifier. The chosen input says how the command is read, so the separate control mode field goes; ManipulatorControlMode stays for telemetry only. Without arm input the arm does not move. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A pose move runs to the end by itself; a nonzero arm_input or a lapse of the client watchdog cancels it, gripper and rotation velocities do not. speed_modifier scales arm_input only. The telemetry end position is in the drone body frame, as the cartesian input is. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks, agreed. This is now one command path (20de6fb, 96d7b41):
|
|
Thanks, this addresses my review: extending Could we clarify the stop behavior during a named-pose move? I’d document that absent/zero arm input means no manual movement and does not cancel a pose. We should also define how a client explicitly cancels a pose without requesting movement or letting its watchdog expire—for example, whether |
Moving the arm to a named pose becomes an explicit, continuous action: KnownPoseManipulatorInput is a third arm_input of GripperCtrl, holding the pose and a velocity along the drone's path to it (0..1). The arm moves only while the velocity is above zero and resumes from wherever it stopped, so releasing the control stops it, as for the other inputs. ManipulatorPoseCtrl and its separate cancellation rules go away, and the telemetry mode gains KNOWN_POSE. The GripperCtrl comment now matches how clients send it, on change: each command stands until the next one, and the arm stops on a command without arm input or when the client watchdog lapses. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Good catch. We resolved it by removing the one-shot pose move altogether (08b3f6d), so there's no conflict left to document. Moving to a known pose is now an explicit, hold-to-run action, and a third case of message KnownPoseManipulatorInput {
ManipulatorPose pose = 1;
float velocity = 2; // Speed along the path (0.0..1.0): 0 holds the arm where it is.
}
oneof arm_input {
CartesianManipulatorInput cartesian = 2;
CylindricalManipulatorInput cylindrical = 3;
KnownPoseManipulatorInput known_pose = 5;
}
The idea is that moving the arm into a pose is never something that happens on its own: in the app it maps to holding a control (on a pad, the right stick pushed forward in a pose mode), and letting go stops the arm. |
To match GripperCtrl: GripperTel carries a Gripper, the state of the gripper and, on a manipulator arm, of the arm. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds what the drone needs for the Reach Robotics Reach Alpha 5, a five-function manipulator.
Device id
GUEST_PORT_DEVICE_ID_REACH_ROBOTICS_REACH_ALPHA_5 = 52, next to the Outland MP-200 (#310).Manipulator arm
GripperCtrlkeepsgripper_velocitiesat field 1 and gains:oneof arm_input:CartesianManipulatorInput:xforward,yright,zdown, in the drone body frame.CylindricalManipulatorInput:radialout from the base axis,verticaldown along it,azimuthclockwise seen from above.KnownPoseManipulatorInput: aManipulatorPose(stowed or deployed) and avelocity(0..1) along the drone's path to it. Hold-to-run: the arm moves only while the velocity is above zero, and resumes from wherever it stopped.speed_modifier(-1..1): negative is slower, positive faster, 0 the drone's default speed. Scalesarm_inputonly, notgripper_velocities.GripperTel { Gripper }: how the last arm input was read (ManipulatorControlMode), joint positions, end position in the drone body frame (m), flags for a joint at its limit, a collision, jaws holding something and a joint fault, and the pose being moved towards.Joint control stays a desk and service tool and is not in the protocol. Maximum speeds, grip current, where the arm sits on the hull and its obstacles stay in the drone's configuration.
The driver side (libblunux) follows in its own PR; nothing uses the new messages yet.
🤖 Generated with Claude Code