这是一篇

关于行驶的

代码教学

(本次代码教学由某位不愿意透露姓名的包大佬提供。)

我们今天来解读一下基层代码——关于如何实现行驶。先上代码:

public void drive(double speed,double turn) {

             //Squared input for better experience

             speed*=Math.abs(speed);

             //Set max acceleration

             speed=boundAcceleration(speed);

             //Record

             mLastSpeed=speed;

             mLastTime=System.currentTimeMillis();

             //Adjust

             if(mAdjustActivated) {

                     turn=(mAngle-mGyro.getAngle())*MANUAL_ANGLE_ADJUSTION;

             }      

             speed*=DIRECTION;

             //Drive

             double speedL=speed+turn;

             double speedR=speed-turn;

           mDifferentialDrive.tankDrive(clearFriction(speedL),clearFriction(speedR),false);

    }

这个过程需要两个参数:speed速度,turn两侧轮子的转速差即实现转向。

speed*=Math.abs(speed);

读取的参数speed首先要处理一下,就像上一行的注释代码所说:平方speed以获得更好的手感。

speed=boundAcceleration(speed);

boundAcceleration()函数如下:

private double boundAcceleration(double speed) {

double bound=(System.currentTimeMillis()-mLastTime)*MAX_ACCELERATION_PER_MS;

                     bound=Math.min(bound,MAX_ACCELERATION_DISCRETE);

if(Math.abs(speed-mLastSpeed)>bound) { speed=mLastSpeed+Math.signum(speed-mLastSpeed)*bound;

}

     return speed;

}

具体来看

bound=(System.currentTimeMillis()-mLastTime)*MAX_ACCELERATION_PER_MS;

bound代表的是自从上一次调用drive过程到现在为止,这台机器速度有可能做到的最大速度变化量。System.currentTimeMillis()-mLastTime就是现在的时刻System.currentTimeMillis()减去上一次的时刻mLastTime。MAX_ACCELERATION_PER_MS就是我们规定的加速度最大值。

bound=Math.min(bound,MAX_ACCELERATION_DISCRETE);

bound的值不能超过MAX_ACCELERATION_DISCRETE我们规定的最大速度变化量。

if(Math.abs(speed-mLastSpeed)>bound) { speed=mLastSpeed+Math.signum(speed-mLastSpeed)*bound;

}

如果现在的速度speed距离上一次调用drive过程的速度mLastSpeed的变化值大于bound,就把speed改为上一次的速度加上bound。这是为了防止加速度过大,机器翻倒。

再回到drive的过程,经过这一行代码的处理后,加速度受到了有效的控制。

mLastSpeed=speed;

mLastTime=System.currentTimeMillis();

这两句话做的就是让下一次调用drive过程的时候,能够获得正确的mLastSpeed以及mLastTime。

if(mAdjustActivated) {

turn=(mAngle-mGyro.getAngle())*MANUAL_ANGLE_ADJUSTION;

}

这个if语句使得要求机器进行人为强制转向的命令得以操作(其优先级还高于drive过程读入的turn)。比如比赛场上我们突然发现我们的机器让他走直线会走歪,就可以将mAdjustActivated改为真,并使用MANUAL_ANGLE_ADJUSTION进行调整机器的方向。

speed*=DIRECTION;

(DIRECTION表示电机的方向)

double speedL=speed+turn;

double speedR=speed-turn;

mDifferentialDrive.tankDrive(clearFriction(speedL),clearFriction(speedR),false);

这三句话执行的就是用speed,turn这两个参数决定左侧轮子以及右侧轮子的转速。转向就是靠+turn以及-turn来实现。最后调用

mDifferentialDrive.tankDrive()来让drive过程最后反馈到机器上。我们发现,当电机功率达到0.4时马达才会发生转动,由于不确定具体原因,我们姑且认定这仅因为摩擦力,而clearFriction()就是清除摩擦力—,把0.4—1这一段值投影到了0—1。这样就不会出现调用drive(0.1,0)的时候机器动不了了。