最简洁的麦克纳姆轮控制原理与控制方法

0.写在前面

对于第一次接触麦轮的小伙伴们肯定是没办法十分清晰地想象出麦轮底盘的各种运动该如何控制的。而在实际使用中,麦轮的运动灵活性与控制难度之比又非常高,可以说是在比较平整的路面中最香的轮组之一了。
为了让跟我一样急切地想明白麦轮的原理、希望能快速地达到能控制各种运动的水平,我将麦轮的原理精简再精简,以最简洁的方式呈现给大家,并附上了一个包含各种运动与解算的代码示例。

1.物理原理

1.1两种轮

对于四轮小车来说,一套麦克纳姆轮至少应含有两种不同的轮子,民间叫法有很多,百度上将他们称为:“麦克纳姆轮左和麦克纳姆轮右”

下面简称左轮和右轮

左轮:正转可以向左前方运动,反转向右后方的轮(注意是运动方向,与给地面摩擦力的方向相反)
在这里插入图片描述

右轮:正转向右前方运动,反转向左后方的轮
在这里插入图片描述
当主轮转动时会带动周边轮的转动,而周边轮与主轮的转动成一定角度,所以可以产生一个斜向的力。因此多个麦轮组合使用、分别控制就可以使小车在主轮方向不变的情况下实现全向移动了(如果一时没想清楚就请继续看下面对各个运动状态的分析)。

对于左右轮旋转会产生什么方向的力是关键,你可以尝试着进行受力分析,这里就没必要讲解了,只需要大脑里稍微想象应该一下就明白了(或者直接记上面的结论也是一样的)

核心就是利用安装的对称性抵消不需要的力,叠加目标速度方向的力。

只需知道麦轮这些基本的物理特性就足够控制麦轮了。

1.2一种可行的安装方式

对于四轮小车来说;一般来说的安装方式是:

图为一辆麦轮小车的俯视图,其中左前方和右后方的轮为左轮,其余两个为右轮
图为一辆麦轮小车的俯视图,其中左前方和右后方的轮为左轮,其余两个为右轮

不同的安装方式必然导致控制的不同,但是原理都是类似的,以下的讲解均以此安装方式为例,其他的控制方式可以以相同的方式分析。

2.控制

2.1.1前进/后退

以上述方式安装的麦轮同时正转时,前部两个轮与后方两个轮的侧方的力都可以抵消,只剩下向前方的力。小车就可以向前运动
在这里插入图片描述
图为,向前时横向移动的力

后退反转即可,分析同理

2.1.2左右平移

原理是将小车同一侧的两个麦轮以相反的方向旋转,这样沿前后方的力就会抵消,而横向的力有恰好是同一方向。
在这里插入图片描述

例如向左移动就所有右轮全反转,左轮全正转。

2.1.3自旋

原理就是一侧的轮子向后,另一侧的轮子向前;这样对于同一侧的两个轮子来说,横向的力还是可以抵消
在这里插入图片描述

如左侧两个轮子正转,右侧两个轮子反转就可以使小车顺势针旋转,反之则逆时针

以上这几种运动方式需要注意的是,四个轮子虽然转的方向不同,但是转速需要严格相同,不然运动就不再准确。
但是
当我们需要向其他任意方向平动的话,可以将小车速度分解为xy两轴上的方向,分别将这两个分速度的值计算出四个轮子的转速,再将这两套轮子的转度叠加,就可以还原回最开始要求的特殊的小车合速度。
这样四个轮子的转速就不再相同,小车的运动也就不再限于前后与左右,而是你需要的任何方向。

2.1.4转弯

这个对于可以做到全向移动的麦轮小车不是很有必要,不过原理不麻烦,和普通的车轮一样,就是让一侧的速度大于另一侧就行了,因为同侧的两个轮子速度是相同的,所以横向(向心)的力还是可以抵消,只是原来的直线力/速度变成了切线而已。

2.2代码示例

void Chassis_Ctrl(void)
{
	/*底盘运动控制函数*/
	
	//虚拟坐标系根据云台指向得出
	    f_ang=DOUBLE_ECHO.GM_UP_ECHO.yaw_curangle-ORIN_ANGLE;
	//底盘实时保持跟随
      cha_goal_angle=f_ang;
	//s2上,陀螺,跟随的基础上额外增加一个角速度
	    if(RC_CtrlData.rc.s2==2)cha_goal_angle+=800;
  //角度比例控制速度
			wv=(cha_goal_angle)*0.3;
	//遥控器给的是相对于车身的速度
	    r_vx=RC_CtrlData.rc.ch0;	
	    r_vy=RC_CtrlData.rc.ch1;
	//转换为云台参考系,前方永远是云台的前方
	    vx=(r_vx*cos(f_ang*PI/180.f)-r_vy*sin(f_ang*PI/180.f)) / 220;
			vy=(r_vy*cos(f_ang*PI/180.f)+r_vx*sin(f_ang*PI/180.f)) / 220;
  //解算为四轮的速度
			vw2 = -(+vx - vy - wv * MOTOR_TO_CENTER) / (WHEEL_RADIUS * 2 * PI) * REDUCE_RATIO * 60;
			vw3 = -(+vx + vy - wv * MOTOR_TO_CENTER) / (WHEEL_RADIUS * 2 * PI) * REDUCE_RATIO * 60;
			vw4 = (+vx - vy + wv * MOTOR_TO_CENTER) / (WHEEL_RADIUS * 2 * PI) * REDUCE_RATIO * 60;
			vw1 = (+vx + vy + wv * MOTOR_TO_CENTER) / (WHEEL_RADIUS * 2 * PI) * REDUCE_RATIO * 60;
	//限速
	    if(vw1>=1800)vw1=1800;
			if(vw2>=1800)vw2=1800;
			if(vw3>=1800)vw3=1800;
			if(vw4>=1800)vw4=1800;
			
			if(vw1<=-1800)vw1=-1800;
			if(vw2<=-1800)vw2=-1800;
			if(vw3<=-1800)vw3=-1800;
			if(vw4<=-1800)vw4=-1800;
  //pid闭环控制
      GUARD_CHASSIS_MOTOR.data.output_current1= pidProcess(&hpid3508, vw1, m3508.m1.speed);
      GUARD_CHASSIS_MOTOR.data.output_current2 = pidProcess(&hpid3508, vw2, m3508.m2.speed);
      GUARD_CHASSIS_MOTOR.data.output_current3 = pidProcess(&hpid3508, vw3, m3508.m3.speed);
      GUARD_CHASSIS_MOTOR.data.output_current4 = pidProcess(&hpid3508, vw4, m3508.m4.speed);

	//通过can来控制电机
      ctrl.pack = M3508_PACK_1_4;
      ctrl.setcur[0] = (int16_t)GUARD_CHASSIS_MOTOR.data.output_current1;
      ctrl.setcur[1] = (int16_t)GUARD_CHASSIS_MOTOR.data.output_current2;
      ctrl.setcur[2] = (int16_t)GUARD_CHASSIS_MOTOR.data.output_current3;
      ctrl.setcur[3] = (int16_t)GUARD_CHASSIS_MOTOR.data.output_current4;
      m3508SetCurrent(&ctrl, &CAN1Handle);
			
		vw1=vw2=vw3=vw4=0;
		control_on++;//调试用
	
}
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐