控制带轮子的小车
感谢网友动力老男孩 的翻译


控制带轮子的小车

双轮小车是一种常见的机器人,两个轮子都由独立的马达控制。 这种设计的小车可以使用不同的转向控制方式来控制。 leJOS NXT有很多类可以用来控制这种小车。

Pilot类

Pilot类通过调节小车马达的转速和转动方向来控制小车。 为了实现对小车的控制,Pilot类必须先知道机器人的配线图, 例如:各个马达分别连接在哪些端口;如何驱动马达来使小车前进或后退。 此外还需要知道轮子的直径,以及轨迹的宽度(也就是两个轮子之间的距离) Pilot类通过轮子的直径来计算小车走过的距离,通过距离的比例来计算小车转过的角度。 显然,所有的参数必须使用相同的长度单位,但是具体用什么长度单位都是可以的(例如厘米,寸等,都可以) 如果设置参数准确的话,小车行驶的距离和旋转的角度,计算误差可以控制在2%以内甚至更小。 这些参数是通过Pilot类的构造器来设置的。

构造器:

  • Pilot(float wheelDiameter, float trackWidth, Motor leftMotor, Motor rightMotor)

    参数分别为:wheelDiameter 轮子直径;trackWidth 轨迹宽度; leftMotor 左轮的马达;rightMotor 右轮的马达。另外一个构造器函数是:

  • Pilot(float wheelDiameter, float trackWidth, Motor leftMotor, Motor rightMotor, boolean reverse)

    如果你是从反向控制小车的话,可以把reverse 参数设置为true

沿直线的运动

要控制小车沿直线运动,可以使用下列函数:

  • void setSpeed(int speed) - 设置马达的转速,单位是:度/秒

  • void forward() - 启动小车,向前行驶

  • void backward() - 反向行驶

  • void stop() - 停止

要控制小车前进或后退的距离,可以使用下列函数:

  • void travel(float distance)

  • void travel(float distance, boolean immediateReturn)

    distance 必须使用和直径相同的长度单位; 负数的distance值表示向后运动。 你可以使用下面这个函数来获取某个时刻小车已经运动的距离

  • int getTravelDistance(); - 这个函数将返回在最后一次调用resetTachoCount();之后,小车行驶过的距离

例子:


import lejos.nxt.*;
import lejos.navigation.Pilot;

/**
 * 一个在行驶途中遇到障碍物,会自动停止的机器人示例
 */
public class TravelTest {
  Pilot pilot;
  TouchSensor bump = new TouchSensor(SensorPort.S1);

  public void go() {
    pilot.travel(20, true);
    while (pilot.isMoving()) {
      if (bump.isPressed()) pilot.stop();
    }
    System.out.println(" "+pilot.getTravelDistance());
    Button.ewaitForPress();
  }

  public static void main(String[] args) {
    TravelTest traveler = new TravelTest();
    traveler.pilot = new Pilot(2.25f, 5.5f, Motor.A, Motor,C);
    traveler.go();
  }
}
			

你可以通过下面的方法,使机器人在原地旋转指定的角度:

  • void rotate(int degrees)

    必须指定精确的轮子直径和轮间距,才能获得精确的转向角度。

编程练习:正方形行程

使用Pilot类的travel和rotate函数编写一段代码,让小车运动轨迹呈现一个正方形。

答案看这里

编程练习:正方形行程2

编写一段代码,让小车的轨迹形成两个正方形的形状,然后沿原路返回。修改上一个程序中的traceSquare方法,让它可以沿任一方向走出正方形轨迹,然后在这个程序中使用它。这是一个非常严格的测试,可以知道你在pilot类中指定的“直径”和“轮间距”常量是否准确。

答案看这里

沿曲线路径运动

pilot类可以让机器人原地转身,方法是让一个轮子正转,同时另一个轮子反转。这个功能使用的方法是:

  • void rotate(int angle)

  • void rotate(int angle, boolean immediateReturn )

    如果angle 参数是正的,机器人会转向左边。immediateReturn 参数的作用和在 Motor类的方法中是一样的–允许调用这个方法的线程在机器人旋转的同时进行其他的工作。

Pilot类也可以控制机器人沿一条弧线运动,使用的方法如下:

  • void steer(int turnRate) – 沿一个圆弧线运动,直到另一个函数把它停止下来

  • void steer(int turnRate, int angle)

  • void steer(int turnRate, int angle, boolean immediateReturn)

其中的turnRate参数决定了曲线路径的半径。这个参数为正时,表示圆弧转向的方向是机器人的左边(也就是说,左侧的轮子运动在内侧)。相应的,这个参数为负数时,圆弧会偏向机器人的右边。这个参数的绝对值必须在0到200之间,这个值取决于内、外两侧轮子的速度比。其中外侧轮子的转速就是机器人设定的转速,内侧轮子的转速更低,这样就可以使机器人转弯了。如果turnRate参数是0,那么内外侧轮子的速度比是1:1,机器人会向前直行。如果参数是200,那么速度比值是1:-1,机器人会原地旋转。如果参数是100,那么速度比值是0,内侧的轮子会静止不动(外侧的轮子绕着它旋转)。所以使用的公式应该是:speedRatio=1-abs(turnRate)/100。

其中的angle参数,表示旋转多少角度之后才停止,如果这个参数是负值,那么机器人会沿着上面说的路径的反方向旋转。

  • getAngle() - 返回在最后一次调用resetTachoCount()之后,小车总共旋转过的角度值

编程练习:方向控制测试

编写一个程序,使用按钮来输入路径的角度(turn rate)参数和角度(angle)参数。然后调用steer()函数观察小车的运动轨迹。这个程序可以循环运行,这样你就可以尝试各种不同的参数来控制轨迹。

答案看这里

Pilot类的其他方法

  • void resetTachocount()

    重置两个马达的参数。这个函数不会被任何其他方法调用,所以如果你想使用getTravelDistance()和getAngle()这两个方法的话,必须自己调用这个函数。

  • void regulateSpeed(Boolean yes)

    如果你想使用自己的方向传感器,加上steer方法来控制小车的运动,你需要用这个方法把速度自动校正功能取消。

  • boolean isMoving()

    只要有任意一个轮子在运动,这个函数就会返回True。当你使用了immediateReturn参数,并且希望知道当前运动任务是否完成的时候,这个方法就非常游泳了。

  • boolean stalled()

    如果两个轮子的速度都是0,这个方法会返回True。请注意,速度是通过每100毫秒采样一次获得的,所以在这个函数在小车开始运动的前100毫秒,会返回True。

如果你非要单独控制左右两个轮子,你可以使用下面的方法:

  • Motor getLeft()

  • Motor getRight()

返回顶部

罗盘导航

CompassPilot类(罗盘导航类)是Pilot类的一个扩展。它和Pilot类提供了一样的方法和功能,但是它支持的是第三方公司生产的电子罗盘传感器(compass sensor)。通过调用这个类的方法,才能保证机器人的运动不会偏离正确的方向。

这种模式下,需要HiTechnic或Mindsensors公司生产的电子罗盘传感器(接在NXT的一个传感器接口上)。这个类的构造器和Pilot类几乎一样,只是多了一个接入端口的参数信息。

C构造器:

  • CompassPilot(SensorPort compassPort, float wheelDiameter,float trackWidth,Motor leftMotor, Motor rightMotor)

  • CompassPilot(SensorPort compassPort, float wheelDiameter,float trackWidth,Motor leftMotor, Motor rightMotor, boolean reverse)

CompassPilot类中,新增的功能:

  • void calibrate()

    校正电子罗盘传感器,让机器人原地缓慢旋转360度。

  • setHeading(int angle)

    设置机器人期望的运动方向,以笛卡尔坐标系的角度方向表示(角度增加时,小车向左偏移)

  • int getHeading()

    返回期望的运动方向角度值

  • int getAngle()

    返回当前传感器的角度值,也就是小车真正转过的角度

代码练习:CompassPilot类的新功能:

编写一段代码,按一下步骤完成运动:

  1. 校正电子罗盘传感器

  2. 旋转机器人90度

  3. 重置角度基准方向为0,也就是以当前方向为基准

  4. 向前移动一段固定的距离

  5. 再向左旋转90度

  6. 按原路返回

  7. 在每个步骤结束时,显示电子罗盘旋转的角度,和轮子移动过的距离。

建议:在机器人移动的时候,用手轻轻推动它,看看是否能转回正确的方向。

答案看这里

返回顶部

转速器导航

在控制两轮小车类中,有三个抽象的层。这种结构可以使你很容易的得到你需要的层,而不被其他低层次的层干扰。

转速器导航执行导航接口,这些接口定义了基本导航工作的方法。导航保持追踪机器人的坐标(x,y)和它前进的角度(机器人所面对的方向)。它使用了直角坐标系,和度数的角度。0度时指x轴,90度时y轴的正向。因为转速器导航需要一个导引来控制小车,它完成了你需要使用的通用的导引运动命令。

构造器:

  • TachoNavigator(Pilot aPilot)

    要使用这个构造器,你必须构造一个导引,并且将它作为参数

此外,你也可以使用一个构造器,从你提供的信息中创建导引。参数列表与导引构造器里的相同。

  • TachoNavigator(float wheelDiameter,,float trackWidth, Motor leftMotor, Motor rightMotor)

  • TachoNavigator(float wheelDiameter,,float trackWidth, Motor leftMotor Motor rightMotor,boolean reverse)

基础的导航方法

设置和得到机器人坐标和分向量的方法:

  • void setPosition(float x, float y, float directionAngle)

  • float getX()

  • float getY()

  • float getAngle()

得到角度和到某点坐标为(x,y)的距离的方法

  • float angleTo(float x, float y)

  • float distanceTo(float x, float y)

更新机器人位置坐标(x,y,角度)

  • void updatePosition()

    更新机器人坐标(x,y)和方向夹角。停止被调用,直到机器人停下来前,运动的命令都不会退出。如果你使用了一个立即返回值的运动命令,那么你必须在运动完成时调用这个方法。它也许会在运动还在进行中就被调用,所以你可以调用方法得到机器人位置的分向量。

在一个平面上控制机器人的运动

对于Pilot类,导航运动的控制方法有两个版本。一个版本只有当运动完成,并且机器人的位置被更新后才返回值。另一个版本可以选择在运动开始就立即返回值。当你使用这个选项时,你必须确定在机器人再次开始运动前,它的位置背更新过。

这个方法会在返回前自动调用updatePosition()

  • void stop()

  • void travel(float distance)

  • void rotate(float angle)

  • void rotateTo(float angle)

  • goTo(float x, float y)

  • 这个方法让机器人在某圆弧上运动.(它调用了pilot.steer()). 如果半径是负值,旋转的中心就在机器人的右边。如果角度是负值,机器人就向后走。

这个方法要求你当运动结束包括需要immediateReturn 设置为True时,调用最新的位置。

  • void travel(float distance, boolean immediateReturn)

  • void rotate(float angle, boolean immediateReturn)

  • void rotateTo(float angle, boolean immediateReturn)

  • goTo(float x, float y , boolean immediateReturn)

  • turn(float radius, float angle, boolean immediateReturn)

  • forward()

  • backward()

  • rotateLeft()

  • rotateRight()

编程练习:测试转速器导航

写一个程序完成如下步骤:

  1. 将速度设置为500,初始航线为90度(即指向y轴)

  2. 运动到点(-10,0)

  3. 运动到点(10,20)

    在运动过程中,在新一行中,每半秒显示一次x,y坐标。

答案看这里

返回顶部

罗盘导航

罗盘导航是转速控制导航的一个子类,它能执行所有的转速控制导航方法。

构造器:

  • CompassNavigator(CompassPilot aPilot)

    要使用这个构造器,你必须建立一个导引,让它作为一个参数。

也可以使用一个能从你给的信息中创建导引的构造器。参数列表与罗盘引导构造器中的一样。

  • CompassNavigator(SensorPort compassPort ,float wheelDiameter, float trackWidth, Motor leftMotor, Motor rightMotor)

  • CompassNavigator(SensorPort compassPort ,float wheelDiameter, float trackWidth, Motor leftMotor, Motor rightMotor, boolean reverse)

其他方法

  • void calibrate()

    这个方法仅仅是在罗盘导引上调用相同的方法。

  • void updateHeading()

    读取罗盘,更新机器人的方向

编程练习: 测试罗盘导航

对罗盘导航写一个程序,使它能够实现与转速器导航相同的步骤

返回顶部