Skip to content

Commit 14dd548

Browse files
committed
added driveWithAlignment
1 parent b87692e commit 14dd548

File tree

6 files changed

+125
-65
lines changed

6 files changed

+125
-65
lines changed

src/main/java/frc/robot/Constants.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ public static final class DriveConstants {
7272
// public static final double kDriveMaxSpeed = 3.0; // 3 meters per second
7373
public static final double kDriveMaxSpeed = 5.0; // 5 meters per second
7474
public static final double kDriveMinSpeed = .3; // .3 meters per second // TODO: find a good value
75-
public static final double kTurnMaxAngularSpeed = Math.PI; // 1/2 rotation per second
75+
public static final double kTurnMaxAngularSpeed = Math.toRadians(180); // 1/2 rotation per second
76+
public static final double kTurnMinAngularSpeed = Math.toRadians(5); // 5 degrees per second
7677
public static final double kDriveMaxVoltage = 12;
7778

7879
public static final double kDriveGearRatio = 6.12;

src/main/java/frc/robot/Robot.java

Lines changed: 13 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,22 @@
66

77
import static edu.wpi.first.wpilibj2.command.Commands.*;
88
import static frc.robot.Constants.*;
9-
import static frc.robot.Constants.DriveConstants.*;
109
import static frc.robot.Constants.RobotConstants.*;
1110
import static frc.robot.subsystems.PoseEstimationSubsystem.*;
1211

1312
import java.util.Arrays;
1413
import java.util.LinkedList;
1514
import java.util.List;
1615
import java.util.Map;
16+
import java.util.function.DoubleSupplier;
1717

1818
import org.littletonrobotics.urcl.URCL;
1919
import org.photonvision.PhotonCamera;
2020

21-
import edu.wpi.first.math.MathUtil;
22-
import edu.wpi.first.math.controller.PIDController;
2321
import edu.wpi.first.math.geometry.Pose2d;
2422
import edu.wpi.first.math.geometry.Rotation2d;
2523
import edu.wpi.first.math.geometry.Transform2d;
26-
import edu.wpi.first.math.geometry.Translation2d;
24+
import edu.wpi.first.math.kinematics.ChassisSpeeds;
2725
import edu.wpi.first.wpilibj.DataLogManager;
2826
import edu.wpi.first.wpilibj.DriverStation;
2927
import edu.wpi.first.wpilibj.PowerDistribution;
@@ -113,7 +111,11 @@ public void bindDriveControls() {
113111

114112
m_driverController.button(Button.kLeftBumper)
115113
.whileTrue(
116-
driveToClosestTag(new Transform2d(0.5, 0, Rotation2d.fromDegrees(180)), 2));
114+
driveWithAlignmentCommand(
115+
() -> -m_driverController.getLeftY(),
116+
() -> -m_driverController.getLeftX(),
117+
() -> m_driverController.getR2Axis() - m_driverController.getL2Axis(),
118+
new Transform2d(0.5, 0, Rotation2d.fromDegrees(180)), 2));
117119

118120
// m_driverController.button(Button.kLeftBumper)
119121
// .whileTrue(
@@ -144,45 +146,14 @@ public void bindDriveControls() {
144146
// robotToTarget, 12, 15, 14, 16, 17, 18, 19, 20, 21, 22));
145147
}
146148

147-
Command driveToClosestTag(Transform2d robotToTarget, double distanceThresholdInMeters) {
148-
@SuppressWarnings("resource")
149-
PIDController controllerXY = new PIDController(kDriveP, kDriveI, kDriveD);
150-
controllerXY.setSetpoint(0);
151-
152-
@SuppressWarnings("resource")
153-
PIDController controllerYaw = new PIDController(kTurnP, kTurnI, kTurnD);
154-
controllerYaw.enableContinuousInput(-180, 180);
155-
controllerYaw.setSetpoint(0);
149+
Command driveWithAlignmentCommand(DoubleSupplier forwardSpeed, DoubleSupplier strafeSpeed,
150+
DoubleSupplier rotation, Transform2d robotToTarget, double distanceThresholdInMeters) {
156151

157152
return run(() -> {
158-
159-
double fwdSpeed = MathUtil
160-
.applyDeadband(-m_driverController.getLeftY(), ControllerConstants.kDeadzone);
161-
fwdSpeed = Math.signum(fwdSpeed) * Math.pow(fwdSpeed, 2) * kDriveMaxSpeed;
162-
163-
double strSpeed = MathUtil
164-
.applyDeadband(-m_driverController.getLeftX(), ControllerConstants.kDeadzone);
165-
strSpeed = Math.signum(strSpeed) * Math.pow(strSpeed, 2) * kDriveMaxSpeed;
166-
167-
double rotSpeed = MathUtil.applyDeadband(
168-
m_driverController.getR2Axis() - m_driverController.getL2Axis(), ControllerConstants.kDeadzone);
169-
rotSpeed = Math.signum(rotSpeed) * Math.pow(rotSpeed, 2) * kTurnMaxAngularSpeed;
170-
171-
var pose = m_poseEstimationSubystem.getEstimatedPose();
172-
173-
var targetPose = m_poseEstimationSubystem
174-
.closestTagPose(180, distanceThresholdInMeters);
175-
if (targetPose != null) {
176-
targetPose = targetPose.plus(robotToTarget);
177-
Translation2d t = targetPose.getTranslation().minus(pose.getTranslation());
178-
double speed = controllerXY.calculate(t.getNorm());
179-
t = t.getNorm() > 0 ? t.times(-speed / t.getNorm()) : t; // translation toward target
180-
fwdSpeed += t.getX();
181-
strSpeed += t.getY();
182-
rotSpeed += -controllerYaw
183-
.calculate(targetPose.getRotation().minus(pose.getRotation()).getDegrees());
184-
}
185-
m_driveSubsystem.drive(fwdSpeed, strSpeed, rotSpeed, true);
153+
ChassisSpeeds speeds = DriveSubsystem.chassisSpeeds(forwardSpeed, strafeSpeed, rotation);
154+
speeds = speeds
155+
.plus(m_poseEstimationSubystem.chassisSpeedsToClosestTag(robotToTarget, distanceThresholdInMeters));
156+
m_driveSubsystem.drive(speeds.plus(speeds), true);
186157
});
187158
}
188159

src/main/java/frc/robot/commands/DriveCommand.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,19 +44,22 @@ public class DriveCommand extends Command {
4444

4545
/**
4646
* The {@code ProfiledPIDController} for controlling the robot in the x
47-
* dimension in meters.
47+
* dimension in meters (input: error in meters, output: velocity in meters per
48+
* second).
4849
*/
4950
private ProfiledPIDController m_controllerX;
5051

5152
/**
5253
* The {@code ProfiledPIDController} for controlling the robot in the y
53-
* dimension in meters.
54+
* dimension in meters (input: error in meters, output: velocity in meters per
55+
* second).
5456
*/
5557
private ProfiledPIDController m_controllerY;
5658

5759
/**
5860
* The {@code ProfiledPIDController} for controlling the robot in the yaw
59-
* dimension in angles.
61+
* dimension in degrees (input: error in degrees, output: velocity in radians
62+
* per second).
6063
*/
6164
private ProfiledPIDController m_controllerYaw;
6265

src/main/java/frc/robot/commands/DriveCommand2.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,15 @@ public class DriveCommand2 extends Command {
4545

4646
/**
4747
* The {@code ProfiledPIDController} for controlling the robot in the x and y
48-
* dimensions in meters.
48+
* dimensions in meters (input: error in meters, output: velocity in meters per
49+
* second).
4950
*/
5051
protected ProfiledPIDController m_controllerXY;
5152

5253
/**
5354
* The {@code ProfiledPIDController} for controlling the robot in the yaw
54-
* dimension in angles.
55+
* dimension in degrees (input: error in degrees, output: velocity in radians
56+
* per second).
5557
*/
5658
protected ProfiledPIDController m_controllerYaw;
5759

@@ -195,6 +197,7 @@ public void execute() {
195197
double speedYaw = m_controllerYaw.calculate(pose.getRotation().getDegrees());
196198
speedX = applyThreshold(speedX, kDriveMinSpeed);
197199
speedY = applyThreshold(speedY, kDriveMinSpeed);
200+
speedYaw = applyThreshold(speedYaw, kTurnMinAngularSpeed);
198201
m_driveSubsystem.drive(speedX, speedY, speedYaw, true);
199202
}
200203

src/main/java/frc/robot/subsystems/DriveSubsystem.java

Lines changed: 51 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -174,16 +174,61 @@ private void setModuleStates(SwerveModuleState[] states) {
174174
m_backRight.setModuleState(states[3]);
175175
}
176176

177+
/**
178+
* Creates a {@code chassisSpeeds} from the joystick input.
179+
*
180+
* @param forwardSpeed Forward speed supplier. Positive values make the robot
181+
* go forward (+X direction).
182+
* @param strafeSpeed Strafe speed supplier. Positive values make the robot
183+
* go to the left (+Y direction).
184+
* @param rotation Rotation speed supplier. Positive values make the
185+
* robot rotate CCW.
186+
* @param isFieldRelative Supplier for determining if driving should be field
187+
* relative.
188+
* @return {@code chassisSpeeds} from the joystick input
189+
*/
190+
public static ChassisSpeeds chassisSpeeds(DoubleSupplier forwardSpeed, DoubleSupplier strafeSpeed,
191+
DoubleSupplier rotation) {
192+
// Get the forward, strafe, and rotation speed, using a deadband on the joystick
193+
// input so slight movements don't move the robot
194+
double vxMetersPerSecond = MathUtil.applyDeadband(forwardSpeed.getAsDouble(), ControllerConstants.kDeadzone);
195+
vxMetersPerSecond = Math.signum(vxMetersPerSecond) * Math.pow(vxMetersPerSecond, 2) * kDriveMaxSpeed;
196+
197+
double vyMetersPerSecond = MathUtil.applyDeadband(strafeSpeed.getAsDouble(), ControllerConstants.kDeadzone);
198+
vyMetersPerSecond = Math.signum(vyMetersPerSecond) * Math.pow(vyMetersPerSecond, 2) * kDriveMaxSpeed;
199+
200+
double omegaRadiansPerSecond = MathUtil.applyDeadband(rotation.getAsDouble(), ControllerConstants.kDeadzone);
201+
omegaRadiansPerSecond = Math.signum(omegaRadiansPerSecond) * Math.pow(omegaRadiansPerSecond, 2)
202+
* kTurnMaxAngularSpeed;
203+
204+
return new ChassisSpeeds(vxMetersPerSecond, vyMetersPerSecond, omegaRadiansPerSecond);
205+
}
206+
207+
/**
208+
* Drives the robot.
209+
*
210+
* @param vxMetersPerSecond forward velocity in meters per second
211+
* @param vyMetersPerSecond sideways velocity in meters per second
212+
* @param omegaRadiansPerSecond angular velocityin radians per second
213+
* @param isFieldRelative a boolean value indicating whether or not the
214+
* veloicities are relative to the field
215+
*/
216+
public void drive(double vxMetersPerSecond, double vyMetersPerSecond, double omegaRadiansPerSecond,
217+
boolean isFieldRelative) {
218+
setModuleStates(
219+
calculateModuleStates(
220+
new ChassisSpeeds(vxMetersPerSecond, vyMetersPerSecond, omegaRadiansPerSecond),
221+
isFieldRelative));
222+
}
223+
177224
/**
178225
* Drives the robot.
179226
*
180-
* @param speedFwd The forward speed in meters per second
181-
* @param speedSide The sideways speed in meters per second
182-
* @param speedRot The rotation speed in radians per second
227+
* @param chassisSpeeds the {@code ChassisSpeeds} for the robot
183228
* @param isFieldRelative Whether or not the speeds are relative to the field
184229
*/
185-
public void drive(double speedFwd, double speedSide, double speedRot, boolean isFieldRelative) {
186-
setModuleStates(calculateModuleStates(new ChassisSpeeds(speedFwd, speedSide, speedRot), isFieldRelative));
230+
public void drive(ChassisSpeeds chassisSpeeds, boolean isFieldRelative) {
231+
setModuleStates(calculateModuleStates(chassisSpeeds, isFieldRelative));
187232
}
188233

189234
/**
@@ -218,18 +263,7 @@ public void periodic() {
218263
public Command driveCommand(DoubleSupplier forwardSpeed, DoubleSupplier strafeSpeed,
219264
DoubleSupplier rotation, BooleanSupplier isFieldRelative) {
220265
return run(() -> {
221-
// Get the forward, strafe, and rotation speed, using a deadband on the joystick
222-
// input so slight movements don't move the robot
223-
double fwdSpeed = MathUtil.applyDeadband(forwardSpeed.getAsDouble(), ControllerConstants.kDeadzone);
224-
fwdSpeed = Math.signum(fwdSpeed) * Math.pow(fwdSpeed, 2) * kDriveMaxSpeed;
225-
226-
double strSpeed = MathUtil.applyDeadband(strafeSpeed.getAsDouble(), ControllerConstants.kDeadzone);
227-
strSpeed = Math.signum(strSpeed) * Math.pow(strSpeed, 2) * kDriveMaxSpeed;
228-
229-
double rotSpeed = MathUtil.applyDeadband(rotation.getAsDouble(), ControllerConstants.kDeadzone);
230-
rotSpeed = Math.signum(rotSpeed) * Math.pow(rotSpeed, 2) * kTurnMaxAngularSpeed;
231-
232-
drive(fwdSpeed, strSpeed, rotSpeed, isFieldRelative.getAsBoolean());
266+
drive(chassisSpeeds(forwardSpeed, strafeSpeed, rotation), isFieldRelative.getAsBoolean());
233267
}).withName("DefaultDriveCommand");
234268
}
235269

src/main/java/frc/robot/subsystems/PoseEstimationSubsystem.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package frc.robot.subsystems;
22

33
import static frc.robot.Constants.*;
4+
import static frc.robot.Constants.DriveConstants.*;
45

56
import java.util.HashMap;
67
import java.util.Map;
@@ -14,12 +15,14 @@
1415

1516
import edu.wpi.first.math.VecBuilder;
1617
import edu.wpi.first.math.Vector;
18+
import edu.wpi.first.math.controller.PIDController;
1719
import edu.wpi.first.math.estimator.SwerveDrivePoseEstimator;
1820
import edu.wpi.first.math.geometry.Pose2d;
1921
import edu.wpi.first.math.geometry.Rotation2d;
2022
import edu.wpi.first.math.geometry.Transform2d;
2123
import edu.wpi.first.math.geometry.Transform3d;
2224
import edu.wpi.first.math.geometry.Translation2d;
25+
import edu.wpi.first.math.kinematics.ChassisSpeeds;
2326
import edu.wpi.first.math.numbers.N3;
2427
import edu.wpi.first.math.util.Units;
2528
import edu.wpi.first.networktables.NetworkTableInstance;
@@ -75,6 +78,20 @@ public class PoseEstimationSubsystem extends SubsystemBase {
7578
*/
7679
private final StructPublisher<Pose2d> m_estimatedPosePublisher;
7780

81+
/**
82+
* The {@code ProfiledPIDController} for controlling the robot in the x and y
83+
* dimensions in meters (input: error in meters, output: velocity in meters per
84+
* second).
85+
*/
86+
private PIDController m_controllerXY;
87+
88+
/**
89+
* The {@code ProfiledPIDController} for controlling the robot in the yaw
90+
* dimension in degrees (input: error in degrees, output: velocity in radians
91+
* per second).
92+
*/
93+
private PIDController m_controllerYaw;
94+
7895
/**
7996
* Constructs a {@code PoseEstimationSubsystem}.
8097
*
@@ -96,6 +113,12 @@ public PoseEstimationSubsystem(DriveSubsystem driveSubsystem) {
96113
m_estimatedPosePublisher = NetworkTableInstance.getDefault()
97114
.getStructTopic("/SmartDashboard/Pose@PoseEstimationSubsystem", Pose2d.struct)
98115
.publish();
116+
m_controllerXY = new PIDController(kDriveP, kDriveI, kDriveD);
117+
m_controllerXY.setSetpoint(0);
118+
119+
m_controllerYaw = new PIDController(kTurnP, kTurnI, kTurnD);
120+
m_controllerYaw.enableContinuousInput(-180, 180);
121+
m_controllerYaw.setSetpoint(0);
99122
}
100123

101124
/**
@@ -148,6 +171,31 @@ public Pose2d getEstimatedPose() {
148171
return m_poseEstimator.getEstimatedPosition();
149172
}
150173

174+
/**
175+
* Calculates the {@code ChassisSpeeds} for moving to the closest
176+
* {@code AprilTag}.
177+
*
178+
* @param robotToTarget the {@code Tranform2d} representing the pose of the
179+
* target relative to the robot
180+
* @param distanceThresholdInMeters the maximum distance (in meters) within
181+
* which {@code AprilTag}s are considered
182+
* @return the calculated {@code ChassisSpeeds} for moving to the closest
183+
* {@code AprilTag}
184+
*/
185+
public ChassisSpeeds chassisSpeedsToClosestTag(Transform2d robotToTarget, double distanceThresholdInMeters) {
186+
var pose = getEstimatedPose();
187+
var targetPose = closestTagPose(180, distanceThresholdInMeters);
188+
if (targetPose != null) {
189+
targetPose = targetPose.plus(robotToTarget);
190+
Translation2d t = targetPose.getTranslation().minus(pose.getTranslation());
191+
double speed = m_controllerXY.calculate(t.getNorm());
192+
t = t.getNorm() > 0 ? t.times(-speed / t.getNorm()) : t;
193+
return new ChassisSpeeds(t.getX(), t.getY(), -m_controllerYaw
194+
.calculate(targetPose.getRotation().minus(pose.getRotation()).getDegrees()));
195+
}
196+
return new ChassisSpeeds();
197+
}
198+
151199
/**
152200
* Finds the {@code Pose2d} of the {@code AprilTag} that is closest (in terms of
153201
* angular displacement) to the robot when the specified {@code Translation2d}

0 commit comments

Comments
 (0)