瞄准得分框(使用limelight)#

在这个部分,我们将讨论如何将 Limelight 整合到swerve底盘中。我们假设你已经具备了一些关于Limelight的基本知识。如果你使用了别的视觉解析软件,我们接下来讨论的概念也应该是类似的

视觉瞄准#

基本知识#

绝大部分的视觉解析软件都会给你提供两个变量,tx和ty,这是Limelight官方对于这两个变量的具体描述,Limelight 官方文档.

tx和ty 1

在最简单的瞄准过程中。你只需要用`tx` 。更复杂的目标瞄准则还会涉及ty

tx 和 ty 2

在上方左侧的图像中,我们展示了 Limelight 是如何返回tx值的。黑色虚线即为“y轴”。当目标落在这条线上时tx值为0。我们可以从图上看到tx告诉我们目标向左侧(此时tx取负数)或右侧(此时tx取正数)偏移了多少。

在上方左侧的图像中,我们展示了 Limelight 是如何返回tx值的。黑色虚线即为“x轴”。当目标落在这条线上时ty值为0。我们可以从图上看到ty告诉我们目标向上方(此时tx取正数)或下方(此时tx取负数)偏移了多少。

简单模式#

最简单的利用PID做瞄准的方式就是只用 tx 。基本上,你就只是希望你的机器能对着得分框。我们通过计算一个与 tx 的值相反的修正值来达成这一功能。你的PID函数可能是这样的:

double limelightXPID(double tx){
    double kP = 0.008;
    double correction = tx * kP;
    return correction;
}

kP常量应当将你与目标的偏移量(即error),变换为用于一个传入底盘使之移动的值

很不幸的是,这个方法并不是最好的,很多时候当我们的机器贴近目标时,它没有足够的力去修正偏移量。我们所找到的最好的解决方案在下一个部分

进阶模式#

视觉瞄准PID的进阶模式是添加一个最小的输出值和死区。tx的使用方法和上一个方法是一样的。但是,最小输出值允许机器缓慢移动到目标角度而死区则允许机器人在机器已经足够近的时候停止旋转。你的PID函数可能是像这样的:

double limelightXPID(double tx){
    double kP = 0.008;
    double correctionMin = 0.003;
    double deadZone = 0.05;
    double correction = tx * kP;
    if(correction < correctionMin) correction = copysignf(correctionMin, correction);
    if(abs(tx) < deadZone) correction = 0;
    return correction;
}

困难模式#

PID的困难模式将Integra,即积分,纳入考虑。9tx仍然像之前一样使用,但是,积分值在最后帮助机器人移动到正确的方向。它取代上一个部分的最小输出值。你的PID函数可能是这样的:

double integral = 0;
double limelightXPID(double tx){
    double kP = 0.008;
    double deadZone = 0.05;
    double kI = 0.001;
    double IZone = 4.0;
    double ILimit = 1000.0;
    if(abs(tx) < IZone) integral += tx;
    if(abs(integral) > ILimit) integral = 600 * integral/abs(integral);
    double correction = tx * kP + integral * kI;
    if(abs(tx) < deadZone) correction = 0;
    return correction;
}

备注

调试积分会是非常困难的,从我们的经验而言,进阶模式的方法要远比这个方法简单,而且和这个方法有着非常相似的结果

专家模式#

这一个更加复杂的视觉瞄准PID函数会将tx和ty都纳入考虑范围。我们仍然像之前一样使用tx,但是现在,我们用ty计算机器人到得分框的距离。取决于你赛季和你的机器人的样式,你可以有非常多不同的方法来使用ty。我们在此仅仅简短讨论其中一些最常见的方法。

既然ty告诉我们目标离视觉传感器中心的偏移量(用角度的形式呈现),我们可以用这一数值来达成很多奇特的目的。 (为了简化,我们在这一样例中采用伪代码)你的PID瞄准函数可能是这个样子的:

double limelightXPID(double tx){
    double kP = 0.008;
    double correctionMin = 0.003;
    double deadZone = 0.05;
    double correction = tx * kP;
    if(correction < correctionMin) correction = copysignf(correctionMin, correction);
    if(abs(tx) < deadZone) correction = 0;
    return correction;
}
double limelightY PID(double ty){
    double kP = 0.008;
    double correctionMin = 0.003;
    double deadZone = 0.05;
    double correction = ty * kP;
    if(correction < correctionMin) correction = copysignf(correctionMin, correction);
    if(abs(tx) < deadZone) correction = 0;
    return correction;
}

这两个PID组合起来使得你的机器人可以瞄准你的目标并且移动到离目标的指定距离。你可以通过给ty加偏移量(ty - 3)来改变这个指定的距离。

另一个使用ty的好方法是使用测得的距离来增强你的得分能力。举例来说:你可以根据距离来改变shooter的转速或者hood的角度。你也可以根据竖直方向上的偏移量来改变抬升的高度。你甚至可以把得分功能禁用直到机器离得分框足够近。但正因为可能性是如此之多,我们就完全不展示任何的伪代码

以目标为参照系#

引言#

在这一部分中,我们让机器以某一个特定对象作为参照系而非以场地作为参照系(像在先前的篇章中描述的那样)。在2020赛季中,我们以Upper Power Port为参照系。在2019赛季,我们以Cargo Ship,Loading Station和Rocker为参照系,用来放置Hatch。更重要地,你可以瞄准任何场地要素来使得得分更加地迅速以及简易。如果被正确的部署,我们的机器会自然地瞄准目标并围绕它以一个弧线的形式移动。

实现#

如果你只用tx来瞄准目标,那么你的代码可能是像这个样子的:

move(fwd, rot + limelightXPID(tx), str);

要注意tx PID是用来控制机器人旋转的,我们只是希望我们的机器瞄准目标,所以,我们所作的只是转向目标,我们只用Limelight来瞄准,而不是用移动

如果你同时使用tx和ty来瞄准你的目标,那么你的代码可能是像这个样子的:

move(fwd + limelightY PID(ty), rot + limelightXPID(tx), str);

除了tx,要注意ty的PID是用来控制机器人前后移动的,我们希望我们的机器与目标之间维持一个特定的距离。所以我们会在面向目标时前后移动

这些函数必须在每个循环都被调用。你的机器可不能基于旧的数据自动修正不正确的位置