use pyo3::{PyResult, exceptions::PyException, pyclass, pymethods, types::PyAnyMethods};
use robot_behavior::{
RobotException, behavior::*, py_arm_behavior, py_arm_param, py_arm_preplanned_motion,
py_arm_preplanned_motion_ext, py_arm_preplanned_motion_impl, py_arm_real_time_control,
py_arm_real_time_control_ext, py_arm_streaming_handle, py_arm_streaming_motion,
py_robot_behavior,
};
use crate::{
FRANKA_DOF, FrankaEmika, FrankaFR3, FrankaGripper, model::FrankaModel, robot::FrankaHandle,
types::robot_types::*,
};
#[pyclass(name = "FrankaEmika")]
pub struct PyFrankaEmika(FrankaEmika);
#[pyclass(name = "FrankaFR3")]
pub struct PyFrankaFR3(FrankaFR3);
#[pyclass(name = "FrankaHandle")]
pub struct PyFrankaHandle(FrankaHandle);
#[pyclass(name = "FrankaGripper")]
pub struct PyFrankaGripper(FrankaGripper);
#[pyclass(name = "RobotModel")]
pub struct PyFrankaModel(FrankaModel);
#[pymethods]
impl PyFrankaEmika {
#[new]
fn new(ip: &str) -> Self {
PyFrankaEmika(FrankaEmika::new(ip))
}
fn __repr__(&self) -> String {
"FrankaEmika".to_string()
}
#[allow(clippy::too_many_arguments)]
fn set_collision_behavior(
&mut self,
lower_torque_thresholds_acceleration: [f64; 7],
upper_torque_thresholds_acceleration: [f64; 7],
lower_torque_thresholds_nominal: [f64; 7],
upper_torque_thresholds_nominal: [f64; 7],
lower_force_thresholds_acceleration: [f64; 6],
upper_force_thresholds_acceleration: [f64; 6],
lower_force_thresholds_nominal: [f64; 6],
upper_force_thresholds_nominal: [f64; 6],
) -> PyResult<()> {
let data = SetCollisionBehaviorData {
lower_torque_thresholds_acceleration,
upper_torque_thresholds_acceleration,
lower_torque_thresholds_nominal,
upper_torque_thresholds_nominal,
lower_force_thresholds_acceleration,
upper_force_thresholds_acceleration,
lower_force_thresholds_nominal,
upper_force_thresholds_nominal,
};
self.0.set_collision_behavior(data).map_err(map_err)
}
fn set_joint_impedance(&mut self, data: [f64; 7]) -> PyResult<()> {
self.0.set_joint_impedance(data.into()).map_err(map_err)
}
fn set_cartesian_impedance(&mut self, data: [f64; 6]) -> PyResult<()> {
self.0.set_cartesian_impedance(data.into()).map_err(map_err)
}
fn set_guiding_mode(&mut self, guiding_mode: [bool; 6], nullspace: bool) -> PyResult<()> {
let data = SetGuidingModeData { guiding_mode, nullspace };
self.0.set_guiding_mode(data).map_err(map_err)
}
fn set_ee_to_k(&mut self, pose: [f64; 16]) -> PyResult<()> {
self.0.set_ee_to_k(pose.into()).map_err(map_err)
}
fn set_ne_to_ee(&mut self, pose: [f64; 16]) -> PyResult<()> {
self.0.set_ne_to_ee(pose.into()).map_err(map_err)
}
fn set_default_behavior(&mut self) -> PyResult<()> {
self.0.set_default_behavior().map_err(map_err)
}
fn model(&mut self) -> PyResult<PyFrankaModel> {
Ok(PyFrankaModel(self.0.model().map_err(map_err)?))
}
}
#[pymethods]
impl PyFrankaFR3 {
#[new]
fn new(ip: &str) -> Self {
PyFrankaFR3(FrankaFR3::new(ip))
}
fn __repr__(&self) -> String {
"FrankaFR3".to_string()
}
#[allow(clippy::too_many_arguments)]
fn set_collision_behavior(
&mut self,
lower_torque_thresholds_acceleration: [f64; 7],
upper_torque_thresholds_acceleration: [f64; 7],
lower_torque_thresholds_nominal: [f64; 7],
upper_torque_thresholds_nominal: [f64; 7],
lower_force_thresholds_acceleration: [f64; 6],
upper_force_thresholds_acceleration: [f64; 6],
lower_force_thresholds_nominal: [f64; 6],
upper_force_thresholds_nominal: [f64; 6],
) -> PyResult<()> {
let data = SetCollisionBehaviorData {
lower_torque_thresholds_acceleration,
upper_torque_thresholds_acceleration,
lower_torque_thresholds_nominal,
upper_torque_thresholds_nominal,
lower_force_thresholds_acceleration,
upper_force_thresholds_acceleration,
lower_force_thresholds_nominal,
upper_force_thresholds_nominal,
};
self.0.set_collision_behavior(data).map_err(map_err)
}
fn set_joint_impedance(&mut self, data: [f64; 7]) -> PyResult<()> {
self.0.set_joint_impedance(data.into()).map_err(map_err)
}
fn set_cartesian_impedance(&mut self, data: [f64; 6]) -> PyResult<()> {
self.0.set_cartesian_impedance(data.into()).map_err(map_err)
}
fn set_guiding_mode(&mut self, guiding_mode: [bool; 6], nullspace: bool) -> PyResult<()> {
let data = SetGuidingModeData { guiding_mode, nullspace };
self.0.set_guiding_mode(data).map_err(map_err)
}
fn set_ee_to_k(&mut self, pose: [f64; 16]) -> PyResult<()> {
self.0.set_ee_to_k(pose.into()).map_err(map_err)
}
fn set_ne_to_ee(&mut self, pose: [f64; 16]) -> PyResult<()> {
self.0.set_ne_to_ee(pose.into()).map_err(map_err)
}
fn set_default_behavior(&mut self) -> PyResult<()> {
self.0.set_default_behavior().map_err(map_err)
}
fn model(&mut self) -> PyResult<PyFrankaModel> {
Ok(PyFrankaModel(self.0.model().map_err(map_err)?))
}
}
#[pymethods]
impl PyFrankaHandle {}
impl From<FrankaHandle> for PyFrankaHandle {
fn from(handle: FrankaHandle) -> Self {
PyFrankaHandle(handle)
}
}
py_arm_streaming_handle!(PyFrankaHandle<{7}>(FrankaHandle));
py_robot_behavior!(PyFrankaEmika(FrankaEmika));
py_arm_behavior!(PyFrankaEmika<{7}>(FrankaEmika));
py_arm_param!(PyFrankaEmika<{7}>(FrankaEmika));
py_arm_preplanned_motion!(PyFrankaEmika<{7}>(FrankaEmika));
py_arm_preplanned_motion_impl!(PyFrankaEmika<{7}>(FrankaEmika));
py_arm_preplanned_motion_ext!(PyFrankaEmika<{7}>(FrankaEmika));
py_arm_streaming_motion!(PyFrankaEmika<{7}>(FrankaEmika) -> PyFrankaHandle);
py_arm_real_time_control!(PyFrankaEmika<{7}>(FrankaEmika));
py_arm_real_time_control_ext!(PyFrankaEmika<{7}>(FrankaEmika));
py_robot_behavior!(PyFrankaFR3(FrankaFR3));
py_arm_behavior!(PyFrankaFR3<{7}>(FrankaFR3));
py_arm_param!(PyFrankaFR3<{7}>(FrankaFR3));
py_arm_preplanned_motion!(PyFrankaFR3<{7}>(FrankaFR3));
py_arm_preplanned_motion_impl!(PyFrankaFR3<{7}>(FrankaFR3));
py_arm_preplanned_motion_ext!(PyFrankaFR3<{7}>(FrankaFR3));
py_arm_streaming_motion!(PyFrankaFR3<{7}>(FrankaFR3) -> PyFrankaHandle);
py_arm_real_time_control!(PyFrankaFR3<{7}>(FrankaFR3));
py_arm_real_time_control_ext!(PyFrankaFR3<{7}>(FrankaFR3));
#[pymethods]
impl PyFrankaGripper {
#[new]
fn new(ip: &str) -> Self {
PyFrankaGripper(FrankaGripper::new(ip))
}
fn __repr__(&self) -> String {
"FrankaGripper".to_string()
}
fn homing(&mut self) -> PyResult<bool> {
self.0.homing().map_err(map_err)
}
fn grasp(&mut self, width: f64, speed: f64, force: f64) -> PyResult<bool> {
self.0.grasp(width, speed, force).map_err(map_err)
}
fn move_gripper(&mut self, width: f64, speed: f64) -> PyResult<bool> {
self.0.move_gripper(width, speed).map_err(map_err)
}
fn stop(&mut self) -> PyResult<bool> {
self.0.stop().map_err(map_err)
}
}
#[pymethods]
impl PyFrankaModel {
#[new]
fn new(path: &str) -> PyResult<Self> {
Ok(PyFrankaModel(FrankaModel::new(path).map_err(map_err)?))
}
fn __repr__(&self) -> String {
"FrankaModel".to_string()
}
fn coriolis(
&self,
q: [f64; FRANKA_DOF],
dq: [f64; FRANKA_DOF],
m: f64,
x: [f64; 3],
i: [f64; 9],
) -> PyResult<[f64; FRANKA_DOF]> {
Ok(self.0.coriolis(&q, &dq, &i, m, &x))
}
fn gravity(
&self,
q: [f64; FRANKA_DOF],
m: f64,
x: [f64; 3],
gravity: [f64; 3],
) -> PyResult<[f64; FRANKA_DOF]> {
Ok(self.0.gravity(&q, m, &x, &gravity))
}
}
fn map_err(e: RobotException) -> pyo3::PyErr {
PyException::new_err(e.to_string())
}