climber limelight 0306

This commit is contained in:
Alyssum-chenyiyi
2026-03-06 19:40:10 +08:00
parent f8fc037959
commit 6fe9613b67
5 changed files with 140 additions and 68 deletions
+22 -3
View File
@@ -80,9 +80,28 @@ public final class Constants {
public static final Boolean UsingMetaTag2 = true; public static final Boolean UsingMetaTag2 = true;
public static final int climbPipelineIndex = 8; public static final int climbPipelineIndex = 8;
public static final int locatePipelineIndex = 0; public static final int locatePipelineIndex = 0;
public static final double AutoClimbAlignSpeed = 0.5;//等查资料
public static final double AutoClimbAlignTolerance = 0.1;//? // 误差死区 / 对齐判定
public static final double AutoClimbmaxAngularVelocity = 0.5;//等查资料 public static final double AutoClimbToleranceTX = 1.5; // deg
public static final double AutoClimbToleranceTZ = 0.10; // m
public static final double AutoClimbToleranceRY = 2.0; // deg
// P 控制系数
public static final double AutoClimbKpTX = 0.020; // deg -> rad/s
public static final double AutoClimbKpTZ = 0.90; // m -> m/s
public static final double AutoClimbKpRY = 0.015; // deg -> rad/s
// 最小输出(防止快到目标时推不动)
public static final double AutoClimbMinVX = 0.18; // m/s
public static final double AutoClimbMinOmega = 0.10; // rad/s
// 最大输出(防止冲太猛)
public static final double AutoClimbMaxVX = 1.20; // m/s
public static final double AutoClimbMaxOmega = 0.60; // rad/s
// 远距离 / 大角度时额外限速,可后续微调
public static final double AutoClimbFastTurnThresholdTX = 15.0; // deg
public static final double AutoClimbFastTurnOmega = 0.45; // rad/s
} }
public class Field { public class Field {
@@ -135,10 +135,12 @@ public class DriveControls {
vomega = 0; vomega = 0;
break; break;
case PassingBall: case PassingBall:
LimelightSupplier.setPipeline(Constants.Limelight.locatePipelineIndex);
vomega = calculateRotationSpeedFromRotationAngle(calculateDistanceAndRotationToPassBall()[1]); vomega = calculateRotationSpeedFromRotationAngle(calculateDistanceAndRotationToPassBall()[1]);
autoControlNetworkTable.getEntry("autoRotationRate").setDouble(vomega); autoControlNetworkTable.getEntry("autoRotationRate").setDouble(vomega);
break; break;
case AutoAimming: case AutoAimming:
LimelightSupplier.setPipeline(Constants.Limelight.locatePipelineIndex);
vomega = calculateRotationSpeedFromRotationAngle(distanceAndRotation[1]); vomega = calculateRotationSpeedFromRotationAngle(distanceAndRotation[1]);
autoControlNetworkTable.getEntry("autoRotationRate").setDouble(vomega); autoControlNetworkTable.getEntry("autoRotationRate").setDouble(vomega);
break; break;
@@ -27,6 +27,7 @@ import edu.wpi.first.wpilibj2.command.Command;
import edu.wpi.first.wpilibj2.command.Subsystem; import edu.wpi.first.wpilibj2.command.Subsystem;
import frc.robot.Constants.DriveMode; import frc.robot.Constants.DriveMode;
import frc.robot.generated.TunerConstants.TunerSwerveDrivetrain; import frc.robot.generated.TunerConstants.TunerSwerveDrivetrain;
import frc.robot.subsystems.LimelightHelpers.RawFiducial;
import frc.robot.Constants; import frc.robot.Constants;
import edu.wpi.first.networktables.*; import edu.wpi.first.networktables.*;
@@ -269,81 +270,131 @@ public class CommandSwerveDrivetrain extends TunerSwerveDrivetrain implements Su
// 2) 转太快:拒绝(角速度你可以从 Pigeon2 或 drivetrain state 拿) // 2) 转太快:拒绝(角速度你可以从 Pigeon2 或 drivetrain state 拿)
double omegaDegPerSec = getPigeon2().getAngularVelocityZWorld().getValueAsDouble(); // 若你有这个信号 double omegaDegPerSec = getPigeon2().getAngularVelocityZWorld().getValueAsDouble(); // 若你有这个信号
if (Math.abs(omegaDegPerSec) > kMaxOmegaDegPerSec) { if (Math.abs(omegaDegPerSec) > kMaxOmegaDegPerSec) {
System.out.println("NoUsingMetaTag2ForTooFastRotationSpeed"); //System.out.println("NoUsingMetaTag2ForTooFastRotationSpeed");
return false; return false;
} }
// 3) 跳变太大:拒绝(Phoenix6 推荐的稳定策略) // 3) 跳变太大:拒绝(Phoenix6 推荐的稳定策略)
//Pose2d current = getState().Pose; //Pose2d current = getState().Pose;
if (currentPose.getTranslation().getDistance(mt2.pose.getTranslation()) > kMaxVisionJumpMeters) { if (currentPose.getTranslation().getDistance(mt2.pose.getTranslation()) > kMaxVisionJumpMeters) {
System.out.println("NoUsingMetaTag2ForTooChangingPose"); //System.out.println("NoUsingMetaTag2ForTooChangingPose");
return false; return false;
} }
return true; return true;
} }
public String driveToAprilTag(){ private double clamp(double value, double min, double max) {
//Rotation2d targetHeading = getPose().getRotation(); return Math.max(min, Math.min(max, value));
if(!LimelightSupplier.isTargetVisible() ){ }
public String driveToAprilTag() {
System.out.println("Pipeline = " + LimelightHelpers.getCurrentPipelineIndex(Constants.Limelight.LIMELIGHT_NAME_Intaker));
System.out.println("TV = " + LimelightSupplier.isTargetVisible());
if (!LimelightSupplier.isTargetVisible()) {
isAlignedToAprilTag = false;
//stop();
return "No Target"; return "No Target";
} }
boolean ifRightTag = false;
int trueId = LimelightSupplier.getAprilTagID(); RawFiducial[] fiducials =
for(int id : new int[]{16,32}){ LimelightHelpers.getRawFiducials(Constants.Limelight.LIMELIGHT_NAME_Intaker);
if(id == trueId){
ifRightTag = true; boolean foundDesiredTag = false;
System.out.println("Target get."); for (RawFiducial fiducial : fiducials) {
if (fiducial.id == 16 || fiducial.id == 32) {
foundDesiredTag = true;
break; break;
} }
} }
if(!ifRightTag){
System.out.println("No Target.");
return "No Target";
}
double tx = LimelightSupplier.getTX() ;
double targetTz = -LimelightSupplier.getTargetTZ();
double ry = LimelightSupplier.getTargetRotationY();
double multiply = Constants.Limelight.AutoClimbAlignSpeed; if (!foundDesiredTag) {
if(Math.abs(tx)<Constants.Limelight.AutoClimbAlignTolerance){ isAlignedToAprilTag = false;
tx = 0; stop();
} return "No Desired Tag";
else{
tx *= multiply ;
} }
if(Math.abs(targetTz)<Constants.Limelight.AutoClimbAlignTolerance){ // ===== 读取原始误差 =====
targetTz = 0; double tx = LimelightSupplier.getTX(); // deg
} double tz = -LimelightSupplier.getTargetTZ(); // m,方向按你当前经验保留负号
else{ double ry = LimelightSupplier.getTargetRotationY(); // deg
targetTz*= multiply ;
targetTz*= 5; // ===== 用原始误差判断是否已对齐 =====
isAlignedToAprilTag =
Math.abs(tx) < Constants.Limelight.AutoClimbToleranceTX &&
Math.abs(tz) < Constants.Limelight.AutoClimbToleranceTZ &&
Math.abs(ry) < Constants.Limelight.AutoClimbToleranceRY;
if (isAlignedToAprilTag) {
stop();
return "Aligned";
} }
if(Math.abs(ry)<Constants.Limelight.AutoClimbAlignTolerance){ // ===== 计算输出 =====
ry = 0; double vx = 0.0;
double vy = 0.0;
double omega = 0.0;
// 1) 前后控制:根据 tz 前进/后退
if (Math.abs(tz) > Constants.Limelight.AutoClimbToleranceTZ) {
vx = tz * Constants.Limelight.AutoClimbKpTZ;
// 最小输出,避免快到目标时不动
if (Math.abs(vx) < Constants.Limelight.AutoClimbMinVX) {
vx = Math.copySign(Constants.Limelight.AutoClimbMinVX, vx);
} }
else{
ry/=10; // 最大输出限幅
ry = Math.min(ry, Constants.Limelight.AutoClimbmaxAngularVelocity); vx = clamp(vx,
ry = Math.max(ry, -Constants.Limelight.AutoClimbmaxAngularVelocity); -Constants.Limelight.AutoClimbMaxVX,
Constants.Limelight.AutoClimbMaxVX);
} }
isAlignedToAprilTag = Math.abs(tx) < Constants.Limelight.AutoClimbAlignTolerance && Math.abs(targetTz) < Constants.Limelight.AutoClimbAlignTolerance && Math.abs(ry) < Constants.Limelight.AutoClimbAlignTolerance;
ChassisSpeeds scaled = new ChassisSpeeds( // 2) 旋转控制:tx 为主,ry 为辅
tx, // X 不变 // tx 负责“镜头中心对准 tag”
targetTz, // Y 不变 // ry 负责“机器人姿态微调”
ry double omegaFromTx = 0.0;
); double omegaFromRy = 0.0;
driveRobotRelative(scaled);
// drive( if (Math.abs(tx) > Constants.Limelight.AutoClimbToleranceTX) {
// new Translation2d(tx, targetTz), omegaFromTx = -tx * Constants.Limelight.AutoClimbKpTX;
// ry, }
// false,
// false if (Math.abs(ry) > Constants.Limelight.AutoClimbToleranceRY) {
// ); omegaFromRy = ry * Constants.Limelight.AutoClimbKpRY;
}
omega = omegaFromTx + omegaFromRy;
// 大偏角时直接给较明显的转速,先把朝向拉回来
if (Math.abs(tx) > Constants.Limelight.AutoClimbFastTurnThresholdTX) {
omega = Math.copySign(Constants.Limelight.AutoClimbFastTurnOmega, omega);
}
// 最小输出,避免转不动
if (Math.abs(omega) > 1e-6 && Math.abs(omega) < Constants.Limelight.AutoClimbMinOmega) {
omega = Math.copySign(Constants.Limelight.AutoClimbMinOmega, omega);
}
// 最大输出限幅
omega = clamp(omega,
-Constants.Limelight.AutoClimbMaxOmega,
Constants.Limelight.AutoClimbMaxOmega);
// ===== 调试输出 =====
driveNetworkTable.getEntry("ClimbTX").setDouble(tx);
driveNetworkTable.getEntry("ClimbTZ").setDouble(tz);
driveNetworkTable.getEntry("ClimbRY").setDouble(ry);
driveNetworkTable.getEntry("ClimbVXCmd").setDouble(vx);
driveNetworkTable.getEntry("ClimbOmegaCmd").setDouble(omega);
driveNetworkTable.getEntry("ClimbAligned").setBoolean(isAlignedToAprilTag);
// ===== 下发到底盘 =====
driveRobotRelative(new ChassisSpeeds(vx, vy, omega));
return "Driving to AprilTag"; return "Driving to AprilTag";
} }
public boolean isAlignedToAprilTag(){ public boolean isAlignedToAprilTag(){
return isAlignedToAprilTag; return isAlignedToAprilTag;
} }
@@ -17,7 +17,7 @@ import frc.robot.subsystems.LimelightHelpers.RawFiducial;
public class LimelightSupplier extends SubsystemBase { public class LimelightSupplier extends SubsystemBase {
public LimelightSupplier() { public LimelightSupplier() {
setPipeline(1); setPipeline(8);
} }
public static double getTX() { public static double getTX() {