8自由度串联四足机器人实现前进功能

文章详细介绍了如何实现R253样机8自由度串联四足机器人的前进功能及转向步态,包括串联关节型机器人运动算法、硬件配置(如Basra主控板、Bigfish2.1扩展板和7.4V锂电池),以及基于Arduino的编程实现。此外,还提供了前进和转向的实验程序源代码和相关3D文件资源。
AI助手已提取文章相关产品:

1. 功能说明

     本文示例将实现R253样机8自由度串联四足机器人前进的功能,该机构是由4个 2自由度串联仿生腿 组成。

2. 串联关节型机器人运动算法

      8自由度串联四足机器人的前进步态是将机器人四足分成两组腿(身体一侧的前足与另一侧的后足)分别进行摆动和支撑,即处于对角线上的两条腿的动作一样,均处于摆动相或均处于支撑相,如下图所示:

      当转向时对角线上的腿部摆动方向会跟前进步态不一样,如下图所示为一个左转的步态:

3. 电子硬件

     本实验中采用了以下硬件:

主控板

Basra主控板(兼容Arduino Uno)

扩展板

Bigfish2.1扩展板

电池7.4V锂电池

电路连接说明: D3、D4;D7、D 8;D11、D12;A2、A3为舵机引脚分别对应8自由度串联四足机器人在Bigfish扩展板上的连接位置

注意:两个舵机为一条腿,不要分开连接】

      这里需要注意下,因为该机器人结构上有8个舵机,而Bigfish扩展板上的舵机接口是6个,所以我们需要对Bigfish扩展板进行改装(通过跳线的方式将Bigfish扩展板上常规使用的传感器接口转为舵机接口)。

4. 功能实现

      编程环境:Arduino 1.8.19

      下面提供一个8自由度串联四足机器人步态前进的参考例程(_1_17.ino),将参考例程下载到主控板中,具体实验效果可参考官网演示视频。

/*------------------------------------------------------------------------------------

  版权说明:Copyright 2023 Robottime(Beijing) Technology Co., Ltd. All Rights Reserved.

           Distributed under MIT license.See file LICENSE for detail or copy at

           https://opensource.org/licenses/MIT

           by 机器谱 2023-04-20 https://www.robotway.com/

  ------------------------------*/

/*------------------------------------------------------------------------------------

  实验功能:

    八自由度四足机器人运动

           

  实验接线:

                【--机器人头部(俯视图)--】

----------------------------------------------------



    左前腿[外侧腿----内侧腿]     右前腿[内侧腿----外侧腿]

            内侧    外侧                 内侧     外侧

             .--.      .--.                    .--.       .--.

             |   |---|   |                     |   |       |   |

    D3    |   |---|   |   D4        D7 |   |       |   | D8

             ---*   ---*                    *--*     *--*



    左后腿[外侧腿----内侧腿]     右后腿[内侧腿----外侧腿]

           内侧    外侧                  内侧     外侧

            .--.      .--.                    .--.       .--.

            |   |---|   |                     |   |      |   |

    A3   |   |---|   |   A2       D12 |   |      |   | D11

            ---*   ---*                    *--*    *--*

    ---------------------------------------------------

  版权说明:Copyright 2023 Robottime(Beijing) Technology Co., Ltd. All Rights Reserved.

    Distributed under MIT license.See file LICENSE for detail or copy at

     https://opensource.org/licenses/MIT   by 机器谱 2023-04-20 https://www.robotway.com/

-------------------------------------------------------------------------------------*/

#include <Arduino.h>

#include <avr/pgmspace.h>

#include <Servo.h>

#include "Config.h"

#include "PROGMEM_DATA.h"


Servo myServo[8];


void act_length();      //动作数组长度计算

void ServoStart();      //舵机连接

void ServoStop();       //舵机断开

void ServoGo();         //舵机转动

void readProgmem();     //读取PWM值

void servo_init();      //舵机初始化

void servo_move();      //动作执行



void setup() {

  Serial.begin(9600);

  act_length();             

}


void loop() {

  servo_move(ACTION_INIT, 2);

  delay(1000);

  servo_move(ACTION_MOVE, 20);

  while(1){};

}


void act_length()

{

  actPwmNum[0] = (sizeof(actionInit) / sizeof(actionInit[0]))/SERVO_NUM;

  actPwmNum[1] = (sizeof(actionMove) / sizeof(actionMove[0]))/SERVO_NUM;

  actPwmNum[2] = (sizeof(actionBack) / sizeof(actionBack[0]))/SERVO_NUM;

  actPwmNum[3] = (sizeof(actionLeft) / sizeof(actionLeft[0]))/SERVO_NUM;

  actPwmNum[4] = (sizeof(actionRight) / sizeof(actionRight[0]))/SERVO_NUM;


  /*******************+++++++++此处可以添加PWM数组++++++++++++****************/

}


void ServoStart(int which){

  if(!myServo[which].attached())myServo[which].attach(servo_port[which]);

  pinMode(servo_port[which], OUTPUT);

}


void ServoStop(int which){

  myServo[which].detach();

  digitalWrite(servo_port[which],LOW);

}


void ServoGo(int which , float where){

  ServoStart(which);

  myServo[which].writeMicroseconds(where);

}


void readProgmem(int p, int act){                                       

  switch(act)

  {

    case 0:   value_cur[p] = pgm_read_word_near(actionInit + p + (SERVO_NUM * count_input));   break;

    case 1:   value_cur[p] = pgm_read_word_near(actionMove + p + (SERVO_NUM * count_input));   break;

    case 2:   value_cur[p] = pgm_read_word_near(actionBack + p + (SERVO_NUM * count_input));   break;

    case 3:   value_cur[p] = pgm_read_word_near(actionLeft + p + (SERVO_NUM * count_input));   break;

    case 4:   value_cur[p] = pgm_read_word_near(actionRight + p + (SERVO_NUM * count_input));   break;

    default: break;

  }

}


void servo_init(int act, int num){                         

  if(!_b)

  {

    for(int i=0;i<SERVO_NUM;i++)

    {

      readProgmem(i, act);

      ServoGo(i, value_cur[i]);

      value_pre[i] = value_cur[i];

    }

  }

  num == 1 ? _b = true : _b = false;

}


void servo_move(int act, int num){           

  float value_delta[SERVO_NUM] = {};

  float in_value[SERVO_NUM] = {};

  servo_init(act, num);

  for(int i=0;i< num * actPwmNum[act];i++)

  {

    count_input++;

   

    if(count_input == actPwmNum[act])

    {

      count_input = 0;

      continue;

    }

   

    for(int i=0;i<SERVO_NUM;i++)

    {

      readProgmem(i, act);

      in_value[i] = value_pre[i];

      value_delta[i] = (value_cur[i] - value_pre[i]) / frequency;


      /**************************************************串口查看输出**************************************************/

//      Serial.print(value_pre[i]);

//      Serial.print(" ");

//      Serial.print(value_cur[i]);

//      Serial.print(" ");

//      Serial.print(value_delta[i]);

//      Serial.println();

      /**************************************************串口查看输出**************************************************/

    }

//    Serial.println();

   

    for(int i=0;i<frequency;i++)

    {

      for(int k=0;k<SERVO_NUM;k++)

      {

        in_value[k] += value_delta[k];  

        value_pre[k] = in_value[k];


        /**************************************************串口查看输出**************************************************/

//        Serial.print(in_value[k]);

//        Serial.print(" ");

        /**************************************************串口查看输出**************************************************/

      }

//      Serial.println();

     

      for(int j=0;j<SERVO_NUM;j++)

      {       

        ServoGo(j, in_value[j]);

      }

      delayMicroseconds(SERVO_SPEED);

    }


    /**************************************************串口查看输出**************************************************/

//    for(int i=0;i<SERVO_NUM;i++)

//    {

//      Serial.println(value_pre[i]);  

//    }

    /**************************************************串口查看输出**************************************************/

  }

}

      大家可根据转向的步态,参考上述例程,尝试自己编写下8自由度串联四足机器人转弯的实验程序。

5. 资料内容

①前进-例程源代码

②前进-样机3D文件

 资料内容详见:8自由度串联四足-前进

您可能感兴趣的与本文相关内容

<think>我们正在设计一个八自由度机器人的步态生成与逆运动学模块。八自由度意味着每条腿有两个自由度(通常为髋关节和膝关节)。步态生成模块负责规划机器人的腿部运动轨迹,而逆运动学模块负责将端轨迹转换为关节角度。 步骤1:步态生成 步态生成需要确定端在空间中的运动轨迹。常见的步态有行走、小跑、跳跃等。对于机器人,我们通常使用交替三角步态(trot)或步行(walk)等。步态生成模块输出的是端在机器人本体坐标系下的位置(x, y, z)随时间变化的轨迹。 我们可以使用标准轨迹,例如: - 支撑相:端固定在地面,推动身体前进。 - 摆动相:端抬起并向前移动,准备下一次支撑。 一个简单的轨迹可以是摆动相使用三次多项式插值,支撑相端保持直线运动(相对于身体)。 步骤2:逆运动学 对于每条腿,我们假设其结构为串联连杆。以一条腿为例,通常有两个旋转关节:髋关节(俯仰)和膝关节(俯仰)。这样,端位置与关节角度的关系可以用简单的几何关系表示。 设大腿长度为$L_1$,小腿长度为$L_2$,髋关节角度为$\theta_1$,膝关节角度为$\theta_2$。则端位置(相对于髋关节)为: $$ x = L_1 \cos(\theta_1) + L_2 \cos(\theta_1 + \theta_2) $$ $$ z = L_1 \sin(\theta_1) + L_2 \sin(\theta_1 + \theta_2) $$ 注意:这里假设机器人的腿在矢状面内运动(即只在x-z平面运动),y方向由机器人的宽度决定,通常每条腿的安装位置在机身两侧,所以y坐标是固定的(或者通过另一个关节控制,但八自由度通常没有侧摆关节,所以这里我们只考虑二维)。 但是,我们的机器人每条腿有两个自由度,因此只能控制端在二维平面(如x-z平面)内的运动。因此,我们通常将机器人的运动分解为身体的前进、侧移和旋转,然后通过每条腿在各自运动平面内的运动来实现。 逆运动学求解: 给定端位置(x, z),我们需要求解$\theta_1$和$\theta_2$。 通过几何关系,我们可以得到: $$ r = \sqrt{x^2 + z^2} $$ 然后,利用余弦定理: $$ \theta_2 = \pi - \arccos\left(\frac{L_1^2 + L_2^2 - r^2}{2 L_1 L_2}\right) $$ 或者 $$ \theta_2 = \arccos\left(\frac{r^2 - L_1^2 - L_2^2}{2 L_1 L_2}\right) $$ 注意:这里需要根据机器人的构型选择正确的解(通常膝关节是朝后的,所以取负值,但具体取决于定义)。 然后,$\theta_1$可以通过以下公式计算: $$ \theta_1 = \arctan2(z, x) - \arctan2(L_2 \sin(\theta_2), L_1 + L_2 \cos(\theta_2)) $$ 注意:这里有两个解(肘部向上和肘部向下),我们需要根据机器人的结构选择合理的解(通常膝关节向前弯曲,所以取负的$\theta_2$,即$\theta_2$为负值,这样腿是朝后弯曲的)。 步骤3:Simulink实现 1. 步态生成模块: - 输入:时间、步态参数(步长、步高、周期等) - 输出:条腿的端目标位置(每条腿有x, y, z,但注意y是固定的,因为每条腿在机身两侧,且没有侧摆关节,所以y坐标在腿的局部坐标系中为0,而x和z在局部坐标系中变化。但是,由于机器人的身体运动,我们需要将局部坐标系转换到世界坐标系?实际上,我们通常在机器人本体坐标系下规划,然后通过机器人本体的位姿转换到世界坐标系。但这里我们简化,假设机器人身体水平,那么每条腿的端位置是相对于髋关节安装点的。 2. 逆运动学模块: - 输入:端位置(在腿的局部坐标系中,即相对于髋关节安装点) - 输出:关节角度($\theta_1, \theta_2$) 我们可以为每条腿创建一个逆运动学模块。 在Simulink中,我们可以使用MATLAB Function模块或者Simulink块(如三角函数、代数运算)来实现逆运动学计算。 注意:由于每条腿的结构相同,我们可以设计一个子模块,然后复制次。 步骤4:整体架构 1. 步态生成模块:根据时间生成条腿的端轨迹(在机器人本体坐标系下)。 2. 对于每条腿,将步态生成模块输出的端位置(x, z)输入到逆运动学模块,计算出关节角度。 3. 将关节角度发送给机器人的关节控制器(例如PD控制器)。 注意:我们还需要考虑机器人的身体运动。如果机器人身体在移动(例如前进、旋转),那么我们需要将身体运动与端运动协调。通常,我们会使用一个状态机来管理每条腿的状态(摆动或支撑),并根据身体的速度和方向调整步态。 具体实现: 步态生成模块可以这样设计: - 使用一个计数器或时钟来产生周期性的步态。 - 对于每条腿,根据步态相位(例如trot步态是两条对角线腿同步)生成轨迹。 - 摆动相轨迹:可以使用一个三次多项式或抛物线来生成从起点到终点的轨迹,同时包含一个抬腿高度。 - 支撑相轨迹:端相对于身体向后移动,以推动身体前进。 逆运动学模块:用MATLAB Function模块实现,输入为x, z(注意:在腿的局部坐标系中,y=0),输出为theta1和theta2。 代码示例(MATLAB Function模块): ```matlab function [theta1, theta2] = inverse_kinematics(x, z, L1, L2) % 计算r r = sqrt(x^2 + z^2); % 检查是否可达 if r > L1+L2 || r < abs(L1-L2) % 不可达区域,我们可以设置一个默认值或者报错 theta1 = 0; theta2 = 0; else % 计算theta2,注意我们取负值表示膝关节弯曲(朝后弯曲) % 因为通常θ2为负,所以使用余弦定理时,我们取负解 % 余弦定理:r^2 = L1^2 + L2^2 - 2*L1*L2*cos(pi - theta2) % 即 r^2 = L1^2 + L2^2 + 2*L1*L2*cos(theta2) [因为cos(pi-theta2)=-cos(theta2)] % 所以:cos(theta2) = (r^2 - L1^2 - L2^2) / (2*L1*L2) cos_theta2 = (r^2 - L1^2 - L2^2) / (2 * L1 * L2); % 由于机器人膝关节只能朝后弯曲,所以theta2取负值(在0到-π之间) theta2 = -acos(cos_theta2); % 计算theta1 alpha = atan2(z, x); % 注意:在三角形中,利用正弦定理或几何关系,有: % beta = atan2(L2*sin(abs(theta2)), L1 + L2*cos(abs(theta2))); % 因为theta2是负的,所以取绝对值 beta = atan2(L2*sin(abs(theta2)), L1 + L2*cos(abs(theta2))); theta1 = alpha - beta; end end ``` 注意:上述代码中,我们假设了腿的结构是髋关节在原点,大腿向前(x正方向)和向上(z正方向)为正。膝关节弯曲方向为向后(即膝关节角度为负时,小腿向下向后)。具体需要根据机器人的实际构型调整。 步骤5:在Simulink中搭建模型 1. 创建步态生成模块:可以用多个MATLAB Function模块或者Simulink信号源(如Sine Wave,但需要组合)来生成轨迹。更复杂的可以用Stateflow或MATLAB S函数。 2. 创建逆运动学子系统:将上述MATLAB Function模块封装成一个子系统,输入为x,z,输出为theta1,theta2。注意,L1和L2可以作为参数输入,也可以在模块内部设置。 3. 连接:步态生成模块输出条腿的端坐标(每条腿两个坐标:x,z),分别连接到个逆运动学子系统,然后输出关节角度。 4. 关节控制:将关节角度作为期望值发送给关节控制器(如PD控制器),控制实际关节角度跟踪期望轨迹。 注意:实际中,我们还需要考虑机器人的姿态稳定,可能需要加入姿态反馈来调整步态,但这属于更高级的控制。 以上是一个基本框架。具体实现时,需要根据机器人的详细参数和运动要求进行调整。 参考文献: [1] 机器人步态规划与运动控制的相关文献。 §§相关问题§§ 1. 如何设计一个更复杂的步态(如跳跃步态)? 2. 在逆运动学计算中,如何处理奇点问题? 3. 如何通过Simulink进行机器人的整体仿真(包括动力学)? 4. 如何优化步态参数以实现稳定的行走?</think>### 八自由度机器人Simulink模块设计指南 #### 一、整体架构设计 在Simulink中设计八自由度机器人的步态生成与逆运动学模块,需采用分层架构: ``` [步态生成模块] → [端轨迹规划] → [逆运动学求解] → [关节控制] ↑ ↑ [步态参数] [机器人本体姿态反馈] ``` #### 二、步态生成模块设计 1. **步态参数配置**: - 输入:步长$S$、步高$H$、步态周期$T$(如小跑步态相位差$\Delta t = T/2$) - 输出:条腿的相位信号 $\phi_i = \begin{cases} 0 & \text{支撑相} \\ 1 & \text{摆动相} \end{cases}$ 2. **状态机实现**(使用Stateflow): ```m state Gait_StateMachine entry: % 小跑步态相位分配 phase_offset = [0, 0.5, 0.5, 0]; % 对角同步 during: for i=1:4 phi(i) = mod(t/T + phase_offset(i), 1); if phi(i) < duty_cycle state(i) = "STANCE"; else state(i) = "SWING"; end end end ``` #### 三、端轨迹规划 1. **摆动相轨迹**(三次多项式插值): $$ \begin{cases} x(t) = x_0 + (x_f - x_0)(3\tau^2 - 2\tau^3) \\ z(t) = H \sin(\pi \tau) \quad \text{其中} \ \tau = t/T_{\text{swing}} \end{cases} $$ 2. **支撑相轨迹**(直线推进): $$ x(t) = x_0 - V_b \cdot t, \quad z(t) = 0 $$ ($V_b$为机身速度) 3. **Simulink实现**: - 使用`MATLAB Function`模块实现轨迹方程 - 坐标系转换:髋关节坐标系→本体坐标系→世界坐标系 #### 、逆运动学模块设计 每条腿的2自由度(髋+膝)运动学模型: ``` 髋关节 │ ├── 大腿长度 L1 │ 膝关节 │ ├── 小腿长度 L2 │ 端 ``` 1. **运动学方程**: $$ \begin{cases} x = L_1 \cos\theta_1 + L_2 \cos(\theta_1 + \theta_2) \\ z = L_1 \sin\theta_1 + L_2 \sin(\theta_1 + \theta_2) \end{cases} $$ 2. **闭式逆解**: $$ \begin{aligned} D &= \frac{x^2 + z^2 - L_1^2 - L_2^2}{2L_1L_2} \\ \theta_2 &= \pm \arccos(D) \\ \theta_1 &= \atan2(z,x) - \atan2(L_2 \sin\theta_2, L_1 + L_2 \cos\theta_2) \end{aligned} $$ 3. **Simulink实现**: ```matlab function [theta1, theta2] = leg_ik(x, z, L1, L2) D = (x^2 + z^2 - L1^2 - L2^2)/(2*L1*L2); theta2 = -acos(D); % 取膝关节向下弯曲的解 theta1 = atan2(z,x) - atan2(L2*sin(theta2), L1 + L2*cos(theta2)); end ``` - 封装为`MATLAB Function`模块 - 添加工作空间限制保护: ```matlab if abs(D) > 1 theta1 = 0; theta2 = -pi/2; % 安全位置 end ``` #### 五、系统集成 1. **完整模型结构**: ``` [Gait Generator] ┬─> [Foot Trajectory 1] ─> [Leg IK 1] ─> [Joint Controller 1] ├─> [Foot Trajectory 2] ─> [Leg IK 2] ─> [Joint Controller 2] ├─> [Foot Trajectory 3] ─> [Leg IK 3] ─> [Joint Controller 3] └─> [Foot Trajectory 4] ─> [Leg IK 4] ─> [Joint Controller 4] ``` 2. **关键参数配置**: | 参数 | 符号 | 典型值 | |---|---|---| | 大腿长度 | $L_1$ | 0.2 m | | 小腿长度 | $L_2$ | 0.2 m | | 步态周期 | $T$ | 1.0 s | | 占空比 | $\beta$ | 0.6 | 3. **验证方法**: - 使用`Simscape Multibody`建立物理模型 - 通过`Scope`监控关节角度输出 - 使用`Animation`模块可视化步态 #### 六、优化建议 1. **步态平滑**:贝塞尔曲线替代三次多项式 2. **地形适应**:添加触地检测传感器反馈 3. **实时调整**:基于IMU数据动态修正轨迹[^1] > 设计要点:逆运动学模块需考虑奇异位置处理,当$z=0$且$x=L_1+L_2$时需添加角度限幅保护[^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值