跳到主要内容

使用视觉伺服进行瞄准

  1. 您可以仅使用 Limelight 和驱动系统就能准确快速地瞄准您的机器人。
  2. 这一切可以在不到1小时内完成。

利用高帧率的视觉跟踪,现在可以直接将视觉管道作为 PID 控制回路中的"传感器"来引导您的机器人或炮塔。为了测试这个想法,我们在 2017 年的 FRC 机器人上添加了一个 Limelight,并使其仅使用驱动系统和 Limelight 报告的网络表数据来瞄准视觉目标。

在这个例子中,我们的测试对象是一个 2017 年的 FRC 机器人,它使用带有 Colson 轮的 6 轮驱动系统。这里有一张我们在机器人上添加 Limelight 以进行此测试的图片。

CS_aim_limelight_mounted

接下来,我们在机器人上添加了一些代码,这些代码会在驾驶员按住操纵杆上的按钮时运行。这个机器人使用"坦克"式驱动,所以 OperatorControl 函数生成 'left_command' 值和 'right_command' 值来控制驱动系统的左右两侧。在正常控制代码之后,我们添加了这样一块代码:

float Kp = -0.1f;  // 比例控制常数

std::shared_ptr<NetworkTable> table = NetworkTable::GetTable("limelight");
float tx = table->GetNumber("tx");

if (joystick->GetRawButton(9))
{
float heading_error = tx;
steering_adjust = Kp * tx;

left_command+=steering_adjust;
right_command-=steering_adjust;
}

一开始,这基本上就能工作了。只要你按住按钮,机器人就会自动转向目标。如果你移动目标,机器人会转动以跟随目标。然而,通过仪表板上的实时视频反馈,我们可以看到一个大问题:机器人并不总是能完全对准目标。在一些有小目标的比赛中(如 2016 年和 2017 年),这还不够好。

我们目前实现的是一个简单的比例控制回路。我们计算了航向误差并将其乘以一个常数,从而产生一个与误差成比例的电机命令。当误差趋近于零时,我们的命令也会趋近于零。问题是当机器人试图转向时,会涉及很大的摩擦。非常小的命令根本不会使机器人转动。在小角度时,命令可能变得太小而无法实际移动机器人。你可能会发现,当你从一个大的目标误差开始时,你的机器人能很好地达到目标,但如果你一开始就非常接近目标,它就根本无法瞄准。

有几种方法可以解决这个问题,但这里有一个非常简单的解决方案。我们使用了"最小命令"的概念。如果误差大于某个阈值,只需在电机命令中加上一个常数,这个常数大致代表了机器人实际移动所需的最小功率(实际上你想使用比这稍小一点的值)。新的代码看起来像这样:

float Kp = -0.1f;
float min_command = 0.05f;

std::shared_ptr<NetworkTable> table = NetworkTable::GetTable("limelight");
float tx = table->GetNumber("tx");

if (joystick->GetRawButton(9))
{
float heading_error = -tx;
float steering_adjust = 0.0f;
if (Math.abs(heading_error) > 1.0)
{
if (heading_error < 0)
{
steering_adjust = Kp*heading_error + min_command;
}
else
{
steering_adjust = Kp*heading_error - min_command;
}
}
left_command += steering_adjust;
right_command -= steering_adjust;
}

注意,如果你将 Kp 或 min_command 设置得太高,你的机器人可能会变得不稳定,并在超过目标时来回振荡:

CS_aim_bad

经过一些对 Kp 和 min_command 的调整后,应该能让你的机器人非常准确和快速地直接瞄准目标。

CS_aim_good