跳转至

实现驱动

一个机械臂驱动通常从小到大实现 trait。下面是当前源码对应的推荐顺序。

1. 实现 Robot

use robot_behavior::{ArmState, Robot, RobotResult};

struct MyArm {
    q: [f64; 6],
}

impl Robot for MyArm {
    type State = ArmState<6>;
    const CONTROL_PERIOD: f64 = 0.001;

    fn version() -> String {
        "MyArm 0.1".to_string()
    }

    fn read_state(&mut self) -> RobotResult<Self::State> {
        Ok(ArmState::default())
    }
}

initshutdownenabledisablestop 等生命周期方法都有安全的 no-op 默认实现;真实驱动应按硬件语义覆盖。

2. 描述关节和末端限位

use robot_behavior::{EndPoint, Joints};

impl Joints<6> for MyArm {
    const JOINT_MIN: [f64; 6] = [-3.14; 6];
    const JOINT_MAX: [f64; 6] = [ 3.14; 6];
    const JOINT_VEL_BOUND: [f64; 6] = [2.0; 6];
}

impl EndPoint for MyArm {
    const CARTESIAN_VEL_BOUND: f64 = 1.0;
    const ROTATION_VEL_BOUND: f64 = 1.57;
}

JOINT_MIN / JOINT_MAX 必填,其余限位默认是 f64::MAX

3. 实现运动空间

use robot_behavior::{FlangeSpace, JointSpace, MoveTo, Pose, RobotResult};

impl MoveTo<JointSpace<6>> for MyArm {
    fn move_to(&mut self, target: [f64; 6]) -> RobotResult<()> {
        self.q = target;
        Ok(())
    }
}

impl MoveTo<FlangeSpace> for MyArm {
    fn move_to(&mut self, target: Pose) -> RobotResult<()> {
        let _target = target;
        // 通常:Pose -> IK -> JointSpace -> hardware
        Ok(())
    }
}

MoveTraj<S> 是轨迹入口。若硬件只接受单点目标,可以在驱动中采样后逐点下发;若硬件支持原生轨迹,则直接映射到厂商 SDK。

4. 实现 Arm

Arm<N> 统一状态、负载和临时限位覆盖:

use robot_behavior::{Arm, ArmState, LoadState, Pose};

impl Arm<6> for MyArm {
    fn state(&mut self) -> RobotResult<ArmState<6>> {
        self.read_state()
    }

    fn set_load(&mut self, load: LoadState) -> RobotResult<()> {
        let _ = load;
        Ok(())
    }

    fn get_joint(&self) -> [f64; 6] { self.q }
    fn get_endpoint(&self) -> Pose { Pose::default() }

    fn with_joint_vel(self, _v: [f64; 6]) -> Self { self }
    fn with_joint_acc(self, _a: [f64; 6]) -> Self { self }
    fn with_joint_jerk(self, _j: [f64; 6]) -> Self { self }
    fn with_torque(self, _t: [f64; 6]) -> Self { self }
    fn with_torque_dot(self, _td: [f64; 6]) -> Self { self }
    fn with_cartesian_vel(self, _v: f64) -> Self { self }
    fn with_cartesian_acc(self, _a: f64) -> Self { self }
    fn with_cartesian_jerk(self, _j: f64) -> Self { self }
    fn with_rotation_vel(self, _v: f64) -> Self { self }
    fn with_rotation_acc(self, _a: f64) -> Self { self }
    fn with_rotation_jerk(self, _j: f64) -> Self { self }
}

真实驱动通常用 OverrideOnce 存储 with_* 的一次性覆盖值。

5. 实现运动学

若驱动需要 FK/IK:

use robot_behavior::{ArmForwardKinematics, DhParam, dh_param};

impl ArmForwardKinematics<6> for MyArm {
    const DH: [DhParam; 6] = [dh_param!(0.0, 0.0, 0.0, 0.0); 6];
}

如果有解析 IK,可实现 ArmInverseKinematics::ik_analytic_all;否则可以复用默认的 DLS、JT、Newton、LM 单步更新。