Skip to main content

franka/wire/
gripper.rs

1//! Gripper wire structs, ported from `common/include/research_interface/gripper/types.h`
2//! (libfranka 0.21.2). The gripper speaks the same framing as the robot but with a 10-byte
3//! header (`uint16_t` command) and `uint16_t` statuses.
4
5use zerocopy::little_endian::{F64, U16, U32};
6use zerocopy::{FromBytes, FromZeros, Immutable, IntoBytes, KnownLayout, Unaligned};
7
8/// Gripper protocol version implemented by this crate (`research_interface::gripper::kVersion`).
9pub const GRIPPER_VERSION: u16 = 3;
10
11/// Gripper command TCP port (`research_interface::gripper::kCommandPort`).
12pub const GRIPPER_COMMAND_PORT: u16 = 1338;
13
14/// Gripper command identifiers (`research_interface::gripper::Command`, `uint16_t`).
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16#[repr(u16)]
17pub enum GripperCommand {
18    /// Handshake that opens the session (`kConnect`).
19    Connect = 0,
20    /// Homes the gripper and calibrates its maximum width (`kHoming`).
21    Homing = 1,
22    /// Grasps an object (`kGrasp`).
23    Grasp = 2,
24    /// Moves the fingers to a width at a speed (`kMove`).
25    Move = 3,
26    /// Aborts the running gripper command (`kStop`).
27    Stop = 4,
28}
29
30impl GripperCommand {
31    /// Wire value.
32    pub const fn to_u16(self) -> u16 {
33        self as u16
34    }
35
36    /// Parses a wire value.
37    pub const fn from_u16(v: u16) -> Option<GripperCommand> {
38        Some(match v {
39            0 => GripperCommand::Connect,
40            1 => GripperCommand::Homing,
41            2 => GripperCommand::Grasp,
42            3 => GripperCommand::Move,
43            4 => GripperCommand::Stop,
44            _ => return None,
45        })
46    }
47}
48
49/// `gripper::CommandBase::Status` (`uint16_t`), shared by every command but `Connect`.
50#[derive(Debug, Clone, Copy, PartialEq, Eq)]
51#[repr(u16)]
52pub enum GripperStatus {
53    /// The command completed (`kSuccess`).
54    Success = 0,
55    /// The command could not be started (`kFail`).
56    Fail = 1,
57    /// The command ran but did not achieve its goal, e.g. a grasp that found nothing
58    /// (`kUnsuccessful`).
59    Unsuccessful = 2,
60    /// The command was aborted, typically by [`GripperCommand::Stop`] (`kAborted`).
61    Aborted = 3,
62}
63
64impl GripperStatus {
65    /// Wire value.
66    pub const fn to_u16(self) -> u16 {
67        self as u16
68    }
69
70    /// Parses a wire value.
71    pub const fn from_u16(v: u16) -> Option<GripperStatus> {
72        Some(match v {
73            0 => GripperStatus::Success,
74            1 => GripperStatus::Fail,
75            2 => GripperStatus::Unsuccessful,
76            3 => GripperStatus::Aborted,
77            _ => return None,
78        })
79    }
80}
81
82/// `gripper::Connect::Status` (`uint16_t`).
83#[derive(Debug, Clone, Copy, PartialEq, Eq)]
84#[repr(u16)]
85pub enum GripperConnectStatus {
86    /// The gripper accepted the announced protocol version (`kSuccess`).
87    Success = 0,
88    /// The gripper speaks another protocol version (`kIncompatibleLibraryVersion`).
89    IncompatibleLibraryVersion = 1,
90}
91
92impl GripperConnectStatus {
93    /// Wire value.
94    pub const fn to_u16(self) -> u16 {
95        self as u16
96    }
97
98    /// Parses a wire value.
99    pub const fn from_u16(v: u16) -> Option<GripperConnectStatus> {
100        Some(match v {
101            0 => GripperConnectStatus::Success,
102            1 => GripperConnectStatus::IncompatibleLibraryVersion,
103            _ => return None,
104        })
105    }
106}
107
108/// `gripper::CommandHeader` — 10 bytes.
109#[derive(Debug, Clone, Copy, FromBytes, IntoBytes, Immutable, KnownLayout, Unaligned)]
110#[repr(C, packed)]
111pub struct GripperCommandHeader {
112    /// [`GripperCommand`] as a `u16`.
113    pub command: U16,
114    /// Identifier echoed by the server; used to demultiplex responses.
115    pub command_id: U32,
116    /// Total message size in bytes, header included.
117    pub size: U32,
118}
119
120impl GripperCommandHeader {
121    /// Builds a header. `size` counts the header.
122    pub fn new(command: GripperCommand, command_id: u32, size: u32) -> Self {
123        GripperCommandHeader {
124            command: U16::new(command.to_u16()),
125            command_id: U32::new(command_id),
126            size: U32::new(size),
127        }
128    }
129}
130
131/// `gripper::Connect::Request` — 4 bytes.
132#[derive(Debug, Clone, Copy, FromBytes, IntoBytes, Immutable, KnownLayout, Unaligned)]
133#[repr(C, packed)]
134pub struct GripperConnectRequest {
135    /// Gripper protocol version this client speaks ([`GRIPPER_VERSION`]).
136    pub version: U16,
137    /// UDP port the client wants gripper states sent to.
138    pub udp_port: U16,
139}
140
141impl GripperConnectRequest {
142    /// Builds a request announcing `version` and the client's `udp_port`.
143    pub fn new(version: u16, udp_port: u16) -> Self {
144        GripperConnectRequest {
145            version: U16::new(version),
146            udp_port: U16::new(udp_port),
147        }
148    }
149}
150
151/// `gripper::Connect::Response` — 4 bytes.
152#[derive(Debug, Clone, Copy, FromBytes, IntoBytes, Immutable, KnownLayout, Unaligned)]
153#[repr(C, packed)]
154pub struct GripperConnectResponse {
155    /// [`GripperConnectStatus`] as a `u16`.
156    pub status: U16,
157    /// Gripper protocol version implemented by the server.
158    pub version: U16,
159}
160
161/// `gripper::Move::Request` — 16 bytes.
162#[derive(Debug, Clone, Copy, FromBytes, IntoBytes, Immutable, KnownLayout, Unaligned)]
163#[repr(C, packed)]
164pub struct GripperMoveRequest {
165    /// Target width in metres.
166    pub width: F64,
167    /// Closing speed in m/s.
168    pub speed: F64,
169}
170
171impl GripperMoveRequest {
172    /// Builds the request.
173    pub fn new(width: f64, speed: f64) -> Self {
174        GripperMoveRequest {
175            width: F64::new(width),
176            speed: F64::new(speed),
177        }
178    }
179}
180
181/// `gripper::Grasp::Request` — 40 bytes (`epsilon` is the nested `GraspEpsilon` struct).
182#[derive(Debug, Clone, Copy, FromBytes, IntoBytes, Immutable, KnownLayout, Unaligned)]
183#[repr(C, packed)]
184pub struct GraspRequest {
185    /// Target width in metres.
186    pub width: F64,
187    /// `GraspEpsilon::inner`, in metres.
188    pub epsilon_inner: F64,
189    /// `GraspEpsilon::outer`, in metres.
190    pub epsilon_outer: F64,
191    /// Closing speed in m/s.
192    pub speed: F64,
193    /// Grasping force in N.
194    pub force: F64,
195}
196
197impl GraspRequest {
198    /// Builds the request. Argument order matches `franka::Gripper::grasp`.
199    pub fn new(width: f64, epsilon_inner: f64, epsilon_outer: f64, speed: f64, force: f64) -> Self {
200        GraspRequest {
201            width: F64::new(width),
202            epsilon_inner: F64::new(epsilon_inner),
203            epsilon_outer: F64::new(epsilon_outer),
204            speed: F64::new(speed),
205            force: F64::new(force),
206        }
207    }
208}
209
210/// The response of `Homing`, `Grasp`, `Move` and `Stop` — 2 bytes.
211#[derive(Debug, Clone, Copy, FromBytes, IntoBytes, Immutable, KnownLayout, Unaligned)]
212#[repr(C, packed)]
213pub struct GripperCommandResponse {
214    /// [`GripperStatus`] as a `u16`.
215    pub status: U16,
216}
217
218/// `gripper::GripperState` — 23 bytes, streamed over UDP at roughly 60 Hz.
219#[derive(Debug, Clone, Copy, FromBytes, IntoBytes, Immutable, KnownLayout, Unaligned)]
220#[repr(C, packed)]
221pub struct GripperState {
222    /// Monotonically increasing message counter; also the gripper's time in milliseconds.
223    pub message_id: U32,
224    /// Current opening width in metres.
225    pub width: F64,
226    /// Maximum opening width in metres.
227    pub max_width: F64,
228    /// C++ `bool`: whether an object is currently grasped.
229    pub is_grasped: u8,
230    /// Gripper temperature in degrees Celsius.
231    pub temperature: U16,
232}
233
234impl Default for GripperState {
235    fn default() -> Self {
236        GripperState::new_zeroed()
237    }
238}