arm/User/module/arm.cpp

508 lines
18 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// /* Includes ----------------------------------------------------------------- */
// #include <math.h>
// #include <stdint.h>
// #include <string.h>
// #include "arm.h"
// #include "bsp/mm.h"
// #include "bsp/time.h"
// #include "component/user_math.h"
// #include "device/motor_dm.h"
// #include "device/motor_lz.h"
// /* Private typedef ---------------------------------------------------------- */
// /* Private define ----------------------------------------------------------- */
// /* Private macro ------------------------------------------------------------ */
// /* Private variables -------------------------------------------------------- */
// /* Private function -------------------------------------------------------- */
// // ============================================================================
// // Joint关节级别操作 - 面向对象接口
// // ============================================================================
// /**
// * @brief 初始化单个关节
// */
// int8_t Joint_Init(Joint_t *joint, uint8_t id, Joint_MotorType_t motor_type,
// const Arm6dof_DHParams_t *dh_params, const KPID_Params_t *pid_params, float freq) {
// if (joint == NULL || dh_params == NULL || pid_params == NULL) {
// return -1;
// }
// joint->id = id;
// joint->motor_type = motor_type;
// memcpy(&joint->dh_params, dh_params, sizeof(Arm6dof_DHParams_t));
// joint->q_offset = 0.0f;
// PID_Init(&joint->pid, KPID_MODE_CALC_D, freq, pid_params);
// joint->state.current_angle = 0.0f;
// joint->state.current_velocity = 0.0f;
// joint->state.current_torque = 0.0f;
// joint->state.target_angle = 0.0f;
// joint->state.target_velocity = 0.0f;
// joint->state.online = false;
// return 0;
// }
// /**
// * @brief 更新关节状态
// */
// int8_t Joint_Update(Joint_t *joint) {
// if (joint == NULL) return -1;
// if (joint->motor_type == JOINT_MOTOR_TYPE_LZ) {
// joint->state.current_angle = joint->motor.lz_motor.motor.feedback.rotor_abs_angle - joint->q_offset;
// joint->state.current_velocity = joint->motor.lz_motor.motor.feedback.rotor_speed;
// joint->state.current_torque = joint->motor.lz_motor.motor.feedback.torque_current;
// joint->state.online = joint->motor.lz_motor.motor.header.online;
// } else {
// joint->state.current_angle = joint->motor.dm_motor.motor.feedback.rotor_abs_angle - joint->q_offset;
// joint->state.current_velocity = joint->motor.dm_motor.motor.feedback.rotor_speed;
// joint->state.current_torque = joint->motor.dm_motor.motor.feedback.torque_current;
// joint->state.online = joint->motor.dm_motor.motor.header.online;
// }
// return 0;
// }
// /**
// * @brief 关节位置控制
// */
// int8_t Joint_PositionControl(Joint_t *joint, float target_angle, float dt) {
// if (joint == NULL) return -1;
// if (target_angle < joint->dh_params.qmin || target_angle > joint->dh_params.qmax) {
// return -1;
// }
// joint->state.target_angle = target_angle;
// float pid_output = PID_Calc(&joint->pid, target_angle, joint->state.current_angle, 0, dt);
// if (joint->motor_type == JOINT_MOTOR_TYPE_LZ) {
// joint->output.lz_output.target_angle = target_angle + joint->q_offset;
// joint->output.lz_output.target_velocity = 0.0f;
// joint->output.lz_output.kp = 10.0f;
// joint->output.lz_output.kd = 0.5f;
// joint->output.lz_output.torque = pid_output;
// MOTOR_LZ_MotionControl(&joint->motor_params.lz_params, &joint->output.lz_output);
// } else {
// joint->output.dm_output.angle = target_angle + joint->q_offset;
// joint->output.dm_output.velocity = 0.0f;
// joint->output.dm_output.kp = 50.0f;
// joint->output.dm_output.kd = 3.0f;
// joint->output.dm_output.torque = pid_output;
// MOTOR_DM_MITCtrl(&joint->motor_params.dm_params, &joint->output.dm_output);
// }
// return 0;
// }
// /**
// * @brief 关节松弛
// */
// int8_t Joint_Relax(Joint_t *joint) {
// if (joint == NULL) return -1;
// if (joint->motor_type == JOINT_MOTOR_TYPE_LZ) {
// MOTOR_LZ_Relax(&joint->motor_params.lz_params);
// } else {
// MOTOR_DM_Relax(&joint->motor_params.dm_params);
// }
// return 0;
// }
// /**
// * @brief 检查关节是否到达目标
// */
// bool Joint_IsReached(const Joint_t *joint, float tolerance) {
// if (joint == NULL) return false;
// return fabsf(joint->state.target_angle - joint->state.current_angle) < tolerance;
// }
// // ============================================================================
// // Arm机械臂级别操作
// // ============================================================================
// /* Exported functions ------------------------------------------------------- */
// int8_t Arm_Init(Arm_t *arm, Arm_Params_t *arm_param, float freq) {
// if (arm == NULL||arm_param == NULL) {
// return -1;
// }
// arm->param = arm_param;
// BSP_CAN_Init();
// MOTOR_LZ_Init();
// // 初始化控制参数
// arm->control.mode = ARM_MODE_IDLE;
// arm->control.state = ARM_STATE_STOPPED;
// arm->control.position_tolerance = 0.02f; // 关节角容差0.02rad ≈ 1.15度
// arm->control.velocity_tolerance = 0.01f; // 速度容差0.01rad/s
// arm->control.enable = false;
// return 0;
// }
// int8_t Arm_Updata(Arm_t *arm) {
// if (arm == NULL) {
// return -1;
// }
// MOTOR_LZ_Update(&arm->param->jointMotor1_params);
// MOTOR_LZ_Update(&arm->param->jointMotor2_params);
// MOTOR_LZ_Update(&arm->param->jointMotor3_params);
// MOTOR_DM_Update(&arm->param->jointMotor4_params);
// MOTOR_DM_Update(&arm->param->jointMotor5_params);
// MOTOR_DM_Update(&arm->param->jointMotor6_params);
// // 同步电机实例数据到actuator
// MOTOR_LZ_t *motor1 = MOTOR_LZ_GetMotor(&arm->param->jointMotor1_params);
// if (motor1 != NULL) {
// memcpy(&arm->actuator.jointMotor1, motor1, sizeof(MOTOR_LZ_t));
// }
// MOTOR_LZ_t *motor2 = MOTOR_LZ_GetMotor(&arm->param->jointMotor2_params);
// if (motor2 != NULL) {
// memcpy(&arm->actuator.jointMotor2, motor2, sizeof(MOTOR_LZ_t));
// }
// MOTOR_LZ_t *motor3 = MOTOR_LZ_GetMotor(&arm->param->jointMotor3_params);
// if (motor3 != NULL) {
// memcpy(&arm->actuator.jointMotor3, motor3, sizeof(MOTOR_LZ_t));
// }
// MOTOR_DM_t *motor4 = MOTOR_DM_GetMotor(&arm->param->jointMotor4_params);
// if (motor4 != NULL) {
// memcpy(&arm->actuator.jointMotor4, motor4, sizeof(MOTOR_DM_t));
// }
// MOTOR_DM_t *motor5 = MOTOR_DM_GetMotor(&arm->param->jointMotor5_params);
// if (motor5 != NULL) {
// memcpy(&arm->actuator.jointMotor5, motor5, sizeof(MOTOR_DM_t));
// }
// MOTOR_DM_t *motor6 = MOTOR_DM_GetMotor(&arm->param->jointMotor6_params);
// if (motor6 != NULL) {
// memcpy(&arm->actuator.jointMotor6, motor6, sizeof(MOTOR_DM_t));
// }
// // 从电机反馈更新当前关节角度
// arm->stateVariable.currentJointAngles.q[0] =
// arm->actuator.jointMotor1.motor.feedback.rotor_abs_angle - arm->param->q_offset[0];
// arm->stateVariable.currentJointAngles.q[1] =
// arm->actuator.jointMotor2.motor.feedback.rotor_abs_angle - arm->param->q_offset[1];
// arm->stateVariable.currentJointAngles.q[2] =
// arm->actuator.jointMotor3.motor.feedback.rotor_abs_angle - arm->param->q_offset[2];
// arm->stateVariable.currentJointAngles.q[3] =
// arm->actuator.jointMotor4.motor.feedback.rotor_abs_angle - arm->param->q_offset[3];
// arm->stateVariable.currentJointAngles.q[4] =
// arm->actuator.jointMotor5.motor.feedback.rotor_abs_angle - arm->param->q_offset[4];
// arm->stateVariable.currentJointAngles.q[5] =
// arm->actuator.jointMotor6.motor.feedback.rotor_abs_angle - arm->param->q_offset[5];
// // 正运动学:计算当前末端位姿
// Arm6dof_ForwardKinematics(&arm->stateVariable.currentJointAngles,
// &arm->stateVariable.currentEndPose);
// return 0;
// }
// int8_t Arm_Ctrl(Arm_t *arm) {
// if (arm == NULL) {
// return -1;
// }
// arm->timer.now = BSP_TIME_Get_us() / 1000000.0f;
// arm->timer.dt = (BSP_TIME_Get_us() - arm->timer.last_wakeup) / 1000000.0f;
// arm->timer.last_wakeup = BSP_TIME_Get_us();
// // 如果未使能,松弛所有电机
// if (!arm->control.enable) {
// MOTOR_LZ_Relax(&arm->param->jointMotor1_params);
// MOTOR_LZ_Relax(&arm->param->jointMotor2_params);
// MOTOR_LZ_Relax(&arm->param->jointMotor3_params);
// MOTOR_DM_Relax(&arm->param->jointMotor4_params);
// MOTOR_DM_Relax(&arm->param->jointMotor5_params);
// MOTOR_DM_Relax(&arm->param->jointMotor6_params);
// arm->control.state = ARM_STATE_STOPPED;
// return 0;
// }
// // 根据控制模式执行不同的控制策略
// switch (arm->control.mode) {
// case ARM_MODE_IDLE:
// // 空闲模式:电机松弛
// MOTOR_LZ_Relax(&arm->param->jointMotor1_params);
// MOTOR_LZ_Relax(&arm->param->jointMotor2_params);
// MOTOR_LZ_Relax(&arm->param->jointMotor3_params);
// MOTOR_DM_Relax(&arm->param->jointMotor4_params);
// MOTOR_DM_Relax(&arm->param->jointMotor5_params);
// MOTOR_DM_Relax(&arm->param->jointMotor6_params);
// arm->control.state = ARM_STATE_STOPPED;
// break;
// case ARM_MODE_JOINT_POSITION:
// case ARM_MODE_CARTESIAN_POSITION:
// // 关节位置控制(关节空间和笛卡尔空间最终都转为关节角控制)
// {
// // 检查是否到达目标
// bool reached = true;
// float max_error = 0.0f;
// for (int i = 0; i < 6; i++) {
// float error = arm->stateVariable.targetJointAngles.q[i] -
// arm->stateVariable.currentJointAngles.q[i];
// if (fabsf(error) > arm->control.position_tolerance) {
// reached = false;
// }
// if (fabsf(error) > max_error) {
// max_error = fabsf(error);
// }
// }
// if (reached) {
// arm->control.state = ARM_STATE_REACHED;
// } else {
// arm->control.state = ARM_STATE_MOVING;
// }
// // PID位置控制关节1-3使用LZ电机
// for (int i = 0; i < 3; i++) {
// float pid_output = PID_Calc(&arm->controller.joint_pid[i],
// arm->stateVariable.targetJointAngles.q[i],
// arm->stateVariable.currentJointAngles.q[i],
// 0,
// arm->timer.dt
// );
// MOTOR_LZ_MotionParam_t* output = NULL;
// if (i == 0) output = &arm->output.jointMotor1_output;
// else if (i == 1) output = &arm->output.jointMotor2_output;
// else output = &arm->output.jointMotor3_output;
// output->target_angle = arm->stateVariable.targetJointAngles.q[i] + arm->param->q_offset[i];
// output->target_velocity = 0.0f; // 位置模式速度由PID控制
// output->kp = 10.0f; // 可调参数
// output->kd = 0.5f;
// output->torque = pid_output;
// }
// // MIT模式控制关节4-6使用DM电机
// for (int i = 3; i < 6; i++) {
// float pid_output = PID_Calc(&arm->controller.joint_pid[i],
// arm->stateVariable.targetJointAngles.q[i],
// arm->stateVariable.currentJointAngles.q[i],
// 0,
// arm->timer.dt
// );
// MOTOR_MIT_Output_t* output = NULL;
// if (i == 3) output = &arm->output.jointMotor4_output;
// else if (i == 4) output = &arm->output.jointMotor5_output;
// else output = &arm->output.jointMotor6_output;
// output->angle = arm->stateVariable.targetJointAngles.q[i] + arm->param->q_offset[i];
// output->velocity = 0.0f;
// output->kp = 50.0f; // 位置刚度(提供阻抗和稳定性)
// output->kd = 3.0f; // 速度阻尼(抑制振荡)
// output->torque = pid_output; // PID输出作为前馈力矩主要驱动力
// }
// // 发送控制命令
// MOTOR_LZ_MotionControl(&arm->param->jointMotor1_params, &arm->output.jointMotor1_output);
// MOTOR_LZ_MotionControl(&arm->param->jointMotor2_params, &arm->output.jointMotor2_output);
// MOTOR_LZ_MotionControl(&arm->param->jointMotor3_params, &arm->output.jointMotor3_output);
// MOTOR_DM_MITCtrl(&arm->param->jointMotor4_params, &arm->output.jointMotor4_output);
// MOTOR_DM_MITCtrl(&arm->param->jointMotor5_params, &arm->output.jointMotor5_output);
// MOTOR_DM_MITCtrl(&arm->param->jointMotor6_params, &arm->output.jointMotor6_output);
// }
// break;
// case ARM_MODE_TRAJECTORY:
// // 轨迹跟踪模式(待实现)
// arm->control.state = ARM_STATE_ERROR;
// break;
// case ARM_MODE_TEACH:
// // 示教模式(待实现)
// arm->control.state = ARM_STATE_ERROR;
// break;
// default:
// arm->control.state = ARM_STATE_ERROR;
// break;
// }
// return 0;
// }
// /**
// * @brief 逆运动学求解:根据目标末端位姿计算关节角度
// * @note 此函数计算量大,不要在控制循环中频繁调用
// */
// int8_t Arm_SolveIK(Arm_t *arm, const Arm6dof_Pose_t* target_pose, Arm6dof_JointAngles_t* result_angles) {
// if (arm == NULL || target_pose == NULL || result_angles == NULL) {
// return -1;
// }
// // 验证目标位姿的有效性
// if (isnan(target_pose->x) || isnan(target_pose->y) || isnan(target_pose->z) ||
// isnan(target_pose->roll) || isnan(target_pose->pitch) || isnan(target_pose->yaw) ||
// isinf(target_pose->x) || isinf(target_pose->y) || isinf(target_pose->z) ||
// isinf(target_pose->roll) || isinf(target_pose->pitch) || isinf(target_pose->yaw)) {
// return -1; // 无效的目标位姿
// }
// // 使用当前关节角度作为初始猜测值(如果已初始化)
// Arm6dof_JointAngles_t initial_guess;
// // 检查currentJointAngles是否已初始化不全为0
// bool has_init = false;
// for (int i = 0; i < 6; i++) {
// if (arm->stateVariable.currentJointAngles.q[i] != 0.0f) {
// has_init = true;
// break;
// }
// }
// if (has_init) {
// // 使用当前角度作为初始猜测
// memcpy(&initial_guess, &arm->stateVariable.currentJointAngles, sizeof(Arm6dof_JointAngles_t));
// } else {
// // 使用零位作为初始猜测(机械臂竖直向上)
// memset(&initial_guess, 0, sizeof(Arm6dof_JointAngles_t));
// }
// // 调用逆运动学求解容限1mm最大迭代10次减少计算量
// int ret = Arm6dof_InverseKinematics(target_pose, &initial_guess, result_angles, 1.0f, 10);
// if (ret == 0) {
// // 求解成功更新到inverseKineJointAngles
// memcpy(&arm->stateVariable.inverseKineJointAngles, result_angles, sizeof(Arm6dof_JointAngles_t));
// }
// return ret;
// }
// // ============================================================================
// // 控制API函数实现
// // ============================================================================
// /**
// * @brief 设置控制模式
// */
// int8_t Arm_SetMode(Arm_t *arm, Arm_ControlMode_t mode) {
// if (arm == NULL) {
// return -1;
// }
// arm->control.mode = mode;
// arm->control.state = ARM_STATE_STOPPED;
// return 0;
// }
// /**
// * @brief 使能/失能机械臂
// */
// int8_t Arm_Enable(Arm_t *arm, bool enable) {
// if (arm == NULL) {
// return -1;
// }
// arm->control.enable = enable;
// if (!enable) {
// // 失能时切换到空闲模式
// arm->control.mode = ARM_MODE_IDLE;
// arm->control.state = ARM_STATE_STOPPED;
// }
// return 0;
// }
// /**
// * @brief 关节空间位置控制
// */
// int8_t Arm_MoveJoint(Arm_t *arm, const Arm6dof_JointAngles_t* target_angles) {
// if (arm == NULL || target_angles == NULL) {
// return -1;
// }
// // 检查关节角度是否在限制范围内
// for (int i = 0; i < 6; i++) {
// float qmin = arm->param->arm6dof_params.DH_params[i].qmin;
// float qmax = arm->param->arm6dof_params.DH_params[i].qmax;
// if (target_angles->q[i] < qmin || target_angles->q[i] > qmax) {
// return -1; // 超出关节限位
// }
// }
// // 更新目标角度
// memcpy(&arm->stateVariable.targetJointAngles, target_angles, sizeof(Arm6dof_JointAngles_t));
// // 切换到关节位置控制模式
// arm->control.mode = ARM_MODE_JOINT_POSITION;
// arm->control.state = ARM_STATE_MOVING;
// return 0;
// }
// /**
// * @brief 笛卡尔空间位置控制
// */
// int8_t Arm_MoveCartesian(Arm_t *arm, const Arm6dof_Pose_t* target_pose) {
// if (arm == NULL || target_pose == NULL) {
// return -1;
// }
// // 求解逆运动学
// Arm6dof_JointAngles_t ik_solution;
// if (Arm_SolveIK(arm, target_pose, &ik_solution) != 0) {
// return -1; // 逆运动学求解失败
// }
// // 更新目标
// memcpy(&arm->stateVariable.targetEndPose, target_pose, sizeof(Arm6dof_Pose_t));
// memcpy(&arm->stateVariable.targetJointAngles, &ik_solution, sizeof(Arm6dof_JointAngles_t));
// // 切换到笛卡尔位置控制模式
// arm->control.mode = ARM_MODE_CARTESIAN_POSITION;
// arm->control.state = ARM_STATE_MOVING;
// return 0;
// }
// /**
// * @brief 急停
// */
// int8_t Arm_Stop(Arm_t *arm) {
// if (arm == NULL) {
// return -1;
// }
// // 将目标设置为当前位置
// memcpy(&arm->stateVariable.targetJointAngles,
// &arm->stateVariable.currentJointAngles,
// sizeof(Arm6dof_JointAngles_t));
// arm->control.state = ARM_STATE_STOPPED;
// return 0;
// }
// /**
// * @brief 获取当前运动状态
// */
// Arm_MotionState_t Arm_GetState(Arm_t *arm) {
// if (arm == NULL) {
// return ARM_STATE_ERROR;
// }
// return arm->control.state;
// }