当前位置: 首页 > ai >正文

第三章、运动学逆解(双足轮根据腿高求舵机角度)

0 前言

该部分作为开发过程中的学习记录,可能有错误及不足欢迎小伙伴们一起讨论~

注:该部分是根据灯哥开源的代码来进行学习,具体数学计算部分不做过多叙述,bilibili的教学视频中已经非常清晰了,本节只对个人学习过程中的代码做对应和解释。

1 腿高控制代码

首先,在上一章中我们已经了解了标准Arduino代码由setup()loop()两个函数组成。

void setup() {// put your setup code here, to run once:// 在这里加入你的setup代码,它只会运行一次:
}void loop() {// put your main code here, to run repeatedly://  在这里加入你的loop代码,它会不断重复运行:
}

本章我们首先来看setup()loop()两个函数

通过loop()主函数我们可以得到整个流程:

  • 获取控制器数据(可以理解为每个通道都对应一个按钮,每个按钮不同位置对应不同的数字,比如说下面代码中用到的2通道实际上对应了给定的手柄左边的摇杆,摇杆从下推到上的值从200到1800)
  • 将手柄数据范围映射到腿高数据范围(手柄推动高低即我们期望的腿高低,也就是所谓的腿高期望值。摇杆从下推到上的值从200到1800,腿高是70到130,这个映射的数学公式也很简单假设我们现在控制器数据为 x x x则映射后的腿高为 70 + x − 200 1800 − 200 ⋅ ( 130 − 70 ) 70+\frac{x-200}{1800-200}\cdot(130-70) 70+1800200x200(13070)
  • 根据腿高计算舵机角度值
  • 控制舵机运动到相应的角度
void setup() {Serial.begin(921600);// 初始化串口通信,用于调试输出,波特率921600Wire.begin(1,2,400000UL);// 初始化I2C总线(SDA=GPIO1, SCL=GPIO2),时钟频率400kHzservos.init();// 初始化舵机控制器servos.setAngleRange(0,300);// 设置舵机角度范围(0-300度)servos.setPluseRange(500,2500);// 设置舵机PWM脉宽范围(500-2500μs)sbusRx.Begin(SBUSPIN,-1);// 初始化SBUS接收机(指定信号引脚,无反向)
}void loop() {getRCValue();// 读取遥控器通道数据/* 高度控制逻辑:* 将遥控器通道3的值映射到高度范围[lowest, highest]* RCCHANNEL3_MIN/MAX: 遥控器通道3的原始最小/最大值* Y_demand: 目标高度需求值*/Y_demand = ((int)map(RCValue[2], RCCHANNEL3_MIN, RCCHANNEL3_MAX, lowest, highest));// 调试输出:原始通道值 -> 映射后高度Serial.printf("%d\n",RCValue[2]);Serial.printf("%f\n",Y_demand);// 位置控制参数X = 0;// 水平位置保持0(中心位置)/* 高度平滑过渡:* 使用一阶惯性环节 Y = Y + Kp*(Y_demand - Y)* Kp_Y=0.1 为比例系数,数值越大响应越快但可能振荡*/Y = Y + Kp_Y * (Y_demand - Y);// 设置逆运动学参数(左右腿对称)IKParam.XLeft = X; // 左腿X坐标IKParam.XRight = X;// 右腿X坐标 IKParam.YLeft = Y;// 左腿Y坐标(高度)IKParam.YRight = Y;// 右腿Y坐标Serial.printf("%f,%f,%f\n",X,Y,Y_demand);// 执行逆运动学计算并驱动舵机inverseKinematics();
}

接下来再看实际逆运动学求解部分,该图片来自灯哥教学。
在这里插入图片描述

void inverseKinematics(){float alpha1,alpha2,beta1,beta2;uint16_t servoLeftFront,servoLeftRear,servoRightFront,servoRightRear;/*------------------------ 左腿计算 ------------------------*/// 可以对应上面的图片来看基本一致(左腿参数)float aLeft = 2 * IKParam.XLeft * L1;float bLeft = 2 * IKParam.YLeft * L1;float cLeft = IKParam.XLeft * IKParam.XLeft + IKParam.YLeft * IKParam.YLeft + L1 * L1 - L2 * L2;float dLeft = 2 * L4 * (IKParam.XLeft - L5);float eLeft = 2 * L4 * IKParam.YLeft;float fLeft = ((IKParam.XLeft - L5) * (IKParam.XLeft - L5) + L4 * L4 + IKParam.YLeft * IKParam.YLeft - L3 * L3);// 解二次方程得到大腿关节角度 alpha 和 beta(两个可能解)alpha1 = 2 * atan((bLeft + sqrt((aLeft * aLeft) + (bLeft * bLeft) - (cLeft * cLeft))) / (aLeft + cLeft));alpha2 = 2 * atan((bLeft - sqrt((aLeft * aLeft) + (bLeft * bLeft) - (cLeft * cLeft))) / (aLeft + cLeft));beta1 = 2 * atan((eLeft + sqrt((dLeft * dLeft) + eLeft * eLeft - (fLeft * fLeft))) / (dLeft + fLeft));beta2 = 2 * atan((eLeft - sqrt((dLeft * dLeft) + eLeft * eLeft - (fLeft * fLeft))) / (dLeft + fLeft));// 角度规范化(确保在0-2π范围内)alpha1 = (alpha1 >= 0)?alpha1:(alpha1 + 2 * PI);alpha2 = (alpha2 >= 0)?alpha2:(alpha2 + 2 * PI);/* 解的选择策略:* 左后腿选择大于π/4(45度)的解* 左前选择0~π/4范围内的解*/if(alpha1 >= PI/4) IKParam.alphaLeft = alpha1;else IKParam.alphaLeft = alpha2;if(beta1 >= 0 && beta1 <= PI/4) IKParam.betaLeft = beta1;else IKParam.betaLeft = beta2;/*------------------------ 右腿计算 ------------------------*/// 可以对应上面的图片来看基本一致(右腿参数)float aRight = 2 * IKParam.XRight * L1;float bRight = 2 * IKParam.YRight * L1;float cRight = IKParam.XRight * IKParam.XRight + IKParam.YRight * IKParam.YRight + L1 * L1 - L2 * L2;float dRight = 2 * L4 * (IKParam.XRight - L5);float eRight = 2 * L4 * IKParam.YRight;float fRight = ((IKParam.XRight - L5) * (IKParam.XRight - L5) + L4 * L4 + IKParam.YRight * IKParam.YRight - L3 * L3);IKParam.alphaRight = 2 * atan((bRight + sqrt((aRight * aRight) + (bRight * bRight) - (cRight * cRight))) / (aRight + cRight));IKParam.betaRight = 2 * atan((eRight - sqrt((dRight * dRight) + eRight * eRight - (fRight * fRight))) / (dRight + fRight));// 解二次方程得到大腿关节角度 alpha 和 beta(两个可能解)alpha1 = 2 * atan((bRight + sqrt((aRight * aRight) + (bRight * bRight) - (cRight * cRight))) / (aRight + cRight));alpha2 = 2 * atan((bRight - sqrt((aRight * aRight) + (bRight * bRight) - (cRight * cRight))) / (aRight + cRight));beta1 = 2 * atan((eRight + sqrt((dRight * dRight) + eRight * eRight - (fRight * fRight))) / (dRight + fRight));beta2 = 2 * atan((eRight - sqrt((dRight * dRight) + eRight * eRight - (fRight * fRight))) / (dRight + fRight));// 角度规范化(确保在0-2π范围内)alpha1 = (alpha1 >= 0)?alpha1:(alpha1 + 2 * PI);alpha2 = (alpha2 >= 0)?alpha2:(alpha2 + 2 * PI);/* 解的选择策略:* 右后腿选择大于π/4(45度)的解* 右前选择0~π/4范围内的解*/if(alpha1 >= PI/4) IKParam.alphaRight = alpha1;else IKParam.alphaRight = alpha2;if(beta1 >= 0 && beta1 <= PI/4) IKParam.betaRight = beta1;else IKParam.betaRight = beta2;// 弧度转角度alphaLeftToAngle = (int)((IKParam.alphaLeft / 6.28) * 360);betaLeftToAngle = (int)((IKParam.betaLeft / 6.28) * 360);alphaRightToAngle = (int)((IKParam.alphaRight / 6.28) * 360);betaRightToAngle = (int)((IKParam.betaRight / 6.28) * 360);// 角度矫正servoLeftFront = 90 + betaLeftToAngle;servoLeftRear = 90 + alphaLeftToAngle;servoRightFront = 270 - betaRightToAngle;servoRightRear = 270 - alphaRightToAngle;setServoAngle(servoLeftFront,servoLeftRear,servoRightFront,servoRightRear);
}

以左腿为例,查看串口输出
在这里插入图片描述反计算角度修正
左前: β = 120 − 90 = 30 \beta=120-90=30 β=12090=30
左后: α = 280 − 90 = 190 \alpha=280-90=190 α=28090=190
在这里插入图片描述

http://www.xdnf.cn/news/9397.html

相关文章:

  • 完全卸载VS Code--Windows版
  • 在 Vue + Vite 项目中,直接使用相对路径或绝对路径引用本地图片资源时,图片无法正确显示。
  • Claude 4对比Claude 3.7全面评测:2025最新AI模型实测对比
  • 山东大学软件学院创新项目实训开发日志——第十三周
  • xilinx 7系列底层可配置逻辑块CLB中的LUT、FF等资源
  • IT编程学习资料大全​​​​​​​​
  • 嵌入式学习之系统编程(六)线程
  • 打破边界 智启新篇 新一代质检LIMS系统的演进蓝图
  • QGis实现geoserver上的样式展示(方便样式编辑)
  • ShardingSphere-读写分离
  • leetcode0611. 有效三角形的个数-medium
  • ROS2学习(14)------ ROS2Launch 多节点启动与配置脚本
  • 基于stm32的 永磁同步电机二电平驱动控制系统设计
  • OpenKylin文件管理器界面层级切换问题
  • 多相电机驱动控制学习(1)——基于双dq坐标系的六相/双三相PMSM驱动控制
  • ABC 377
  • 互联网医疗问诊APP原型设计:12个实战案例解析
  • Workflow
  • 如何合理选择智能外呼机器人:多维评估
  • SAP-ABAP:SAP的DMS根据物料号获取附件详解
  • 网络通信的基石:深入理解帧与报文
  • [BUG记录]0X10 会话切换服务响应NRC 0x10
  • <<运算符重载 和 c_str() 的区别和联系
  • TF 卡和 NM 卡有何区别?
  • openinstall支持豆瓣广告监测,赋能品牌深挖社交流量
  • Baklib知识中台体系构建与应用解析
  • 比较转录组-油料作物-文献精读133
  • Jenkins实践(10):pipeline构建历史展示包名和各阶段间传递参数
  • 【深度学习新浪潮】智能眼镜关键技术拆解(简要版)
  • 什么是 BOM 表,如何通过 BOM 表做好生产管理