3PID移动到定点算法¶
在拥有了相对精准的全场定位后,如何使用也是一个相对重要的问题。
这是我们代码中的所有底盘自动化的核心算法。我们使用3个 PIDController ,分别控制底盘的X轴移动,Y轴移动,旋转速度。来使得我们的机器可以直线移动到赛场上的任何一个点。这种做法虽然没有直接使用 PathPlanner 的寻路功能要智能,但是其算法高度可控而精准,在赛场上证明了它的可行性。
此外,由于全场定位还是会有相当的误差,我们在实际操作时还会将摇杆输出叠加到目标位点上,为driver保留微调目标位置的空间。
部分代码如下:
public ChassisSpeeds getHybridMoveToPoseSpeeds(Pose2d pose, ImprovedCommandXboxController driverController, double translationAdjustmentRange, double rotationAdjustmentRangeDegs){
Pose2d currentPose = getPose();
//Hybrid Control, read the lines carefully before you tune it
Transform2d adjustment = new Transform2d(
driverController.getLeftY()*translationAdjustmentRange * (DriverStation.getAlliance().get() == Alliance.Blue ? 1. : -1.), //TODO wrong direction
driverController.getLeftX()*translationAdjustmentRange * (DriverStation.getAlliance().get() == Alliance.Blue ? 1. : -1.),
Rotation2d.fromDegrees(-driverController.getRightX()*rotationAdjustmentRangeDegs)
);//获取摇杆输入,并计算微调的数据。
pose = pose.plus(adjustment);//将微调数据叠加到目标点上
m_targetPose2d = pose;
//给三个Controller设置目标点,并获取对应的速度与角速度
m_rotationController.setSetpoint(pose.getRotation().getRadians());
m_translationXController.setSetpoint(pose.getX());
m_translationYController.setSetpoint(pose.getY());
double targetAngularVelocity = m_rotationController.calculate(currentPose.getRotation().getRadians());
double targetTranslationXVelocity = m_translationXController.calculate(currentPose.getX());
double targetTranslationYVelocity = m_translationYController.calculate(currentPose.getY());
//这段非常重要,如果没有deadband的话机器基本上难逃疯狂的自激振荡,由于 swerve 本来就有锁死功能,到达目标点周围后直接输出0反而避免了PID常见的振荡问题,而且比调试D要简单很多
if(isAtTranslation(pose.getTranslation())){
targetTranslationXVelocity = 0.;
targetTranslationYVelocity = 0.;
}
if(isAtRotation(pose.getRotation())) {
targetAngularVelocity = 0.;
}
SmartDashboard.putNumber("targetXVeloUnoptimized", targetTranslationXVelocity);
SmartDashboard.putNumber("targetYVeloUnoptimized", targetTranslationYVelocity);
SmartDashboard.putNumber("targetAngularVeloUnoptimized", targetAngularVelocity);
//这个函数限制了输出的速度和角速度,防止在远离目标点时机器输出一个非常大的数值
return optimizeMoveToSpeeds(
new ChassisSpeeds(targetTranslationXVelocity, targetTranslationYVelocity, targetAngularVelocity)
);
}