双轮差速轮系的移动机器人列表:
- BalanceXE
- Icar
- mazebot
- miniagv
- minicup
轮系结构图如下:
相关物理量的定义如下:
- p点 : 机器人旋转中心
- o点 : 机器人几何中心
- r : 机器人旋转中心与几何中心连线的距离(m)
- D : 机器人左右轮之间的距离(m)
- d : 机器人几何中心到一个轮子的距离(m),d=D/2
相关变量的定义如下:
- vx : 机器人局部坐标系x方向线速度(m/s)
- vy : 机器人局部坐标系y方向线速度(m/s)
- ω : 机器人局部坐标系绕z轴旋转角速度(rad/s)
- v : 双轮差速轮系中等效于vx,机器人局部坐标系x方向线速度(m/s)
- vl : 左轮线速度(m/s)
- vr : 右轮线速度(m/s)
在刚体中,每一点的角速度相等,因此有
ω=ωl=ωr(1) 逆解已知量为
[vω],
逆解待解量为
[vlvr]
。
由几何关系不难得到
vl=v−ωd(2) vl=v+ωd(3) 写为矩阵形式:
[vlvr]=[11−dd]⋅[vω](4) 示例程序:
#define WHEEL_SEPARATION 0.032
void ikine_diff2(float vel_x, float vel_y, float w_z)
{
float vel_l, vel_r;
vel_l = vel_x - w_z * WHEEL_SEPARATION;
vel_r = vel_x + w_z * WHEEL_SEPARATION;
}
正解已知量为
[vlvr]
待解量为
[vω]
。
由角速度与线速度的关系可知
vl=ωl(r−d)(5) vr=ωr(r+d)(6) 通过式(1)已知ωl=ωr
联立式(1)、(5)、(6)可得旋转半径r:
⇒⇒r−dvl=r+dvrvl(r+d)=vr(r−d)r=vr−vl(vr+vl)d(7) 所以r+d可表示为:
r+d=vr−vl(vr+vl)d+vr−vl(vr−vl)d=vr−vl2vrd(8) 将式(8)带入式(6)中可得求出角速度ω:
ω=r+dvr=2vrdvr(vr−vl)=2dvr−vl(9) 线速度v:
v=w×r=2dvr−vl×vr−vl(vr+vl)d=2vr+vl(10) 写为矩阵形式为:
[vw]=[1/2−1/2d1/21/2d]⋅[vlvr](11) 示例程序:
#define WHEEL_SEPARATION 0.032
void fkine_diff2(float vel_l, float vel_r)
{
float vel_x, float vel_y, float w_z;
vel_x = (vel_r + vel_l) / 2;
w_z = (vel_r - vel_l) / (2 * WHEEL_SEPARATION);
}
里程计关系图:
由几何关系图可得下式:
⎣⎡x′y′θ′⎦⎤=⎣⎡xyθ⎦⎤+⎣⎡cosθsinθ0−sinθcosθ0001⎦⎤⋅⎣⎡dxdydθ⎦⎤ 上式中:
- (x′,y′,θ′) 为当前时刻在全局坐标系下的位姿
- (x,y,θ) 为上一时刻在全局坐标系下的位姿
- (dx,dy,dθ) 在机器人局部坐标系下的运动增量
到此为止我们已得到里程计积分公式,里程计的计算过程就是不断的将固定采样间隔T时间内全局的x、y、θ变化量进行累加。
在有了全局积分公式之后,我们需要求得每个周期内的位姿变化量,一般有两种方法,一是通过车体质点速度,二是直接通过编码器反馈角度,对双轮差速轮系来说,两种方法都适用,接下来分别进行推导。
将车体看做一个质点,通过正解解出的车体状态量[vω],在采样间隔时间&T&内使用微分的思想将机器人的运动看做匀速直线运动,则(dx,dy,dθ)可以使用下式计算得出:
dx=v×Tdy=0dθ=ω×T 写成矩阵形式为:
⎣⎡dxdydθ⎦⎤=⎣⎡T0000T⎦⎤⋅[vω] 轮子里程求微分量的意思是:我们可以直接获取每个轮子在单位时间T中的位移量,通过运动学关系计算出车体姿态变化量,相比通过编码器旋转角度微分计算速度,再通过速度积分计算车体位移,省去了微分计算速度的过程,计算量较小,且能够减少计算误差。
设在在单位时间T内,左轮转过的角度(Rad)为drl,右轮转过的角度(Rad)为drr,则有以下关系:
dsl=drl×Tdsr=drr×T 上式中,dsl为左轮走过的距离(m),dsr为右轮走过的距离(m),则单位时间内机器人局部坐标系的位移量可以由此计算得:
dx=2(dsl+dsr)=2(drr+drl)Tdy=0dθ=D(drr−drl)T 上式中D为左右轮间距,写为矩阵形式:
⎣⎡dxdydθ⎦⎤=⎣⎡T/20−T/DT/20T/D⎦⎤⋅[drldrr] 综上,所有流程已打通,接下来是示例代码。
该函数中使用左右轮的角度来计算里程计,原始数据为last_diff_tick
,含义为左右轮的编码器脉冲数;传入参数为diff_time
,为该函数两次调用之间的时间间隔;顺便计算出了实时的速度v和角速度w,速度和位姿分别填入odom_pose
数组和odom_vel
数组中。
bool calcOdometry(double diff_time)
{
float *orientation;
double wheel_l, wheel_r;
double delta_s, theta, delta_theta;
static double last_theta = 0.0;
double v, w;
double step_time;
wheel_l = wheel_r = 0.0;
delta_s = delta_theta = theta = 0.0;
v = w = 0.0;
step_time = 0.0;
step_time = diff_time;
if (step_time == 0)
return false;
wheel_l = TICK2RAD * (double)last_diff_tick[LEFT];
wheel_r = TICK2RAD * (double)last_diff_tick[RIGHT];
if (isnan(wheel_l))
wheel_l = 0.0;
if (isnan(wheel_r))
wheel_r = 0.0;
delta_s = WHEEL_RADIUS * (wheel_r + wheel_l) / 2.0;
delta_theta = WHEEL_RADIUS * (wheel_r - wheel_l) / WHEEL_SEPARATION;
odom_pose[2] += delta_theta;
odom_pose[0] += delta_s * cos(odom_pose[2]);
odom_pose[1] += delta_s * sin(odom_pose[2]);
v = delta_s / step_time;
w = delta_theta / step_time;
odom_vel[0] = v;
odom_vel[1] = 0.0;
odom_vel[2] = w;
last_velocity[LEFT] = wheel_l / step_time;
last_velocity[RIGHT] = wheel_r / step_time;
return true;
}