Skip to content

Commit 3614430

Browse files
committed
feat: create simulated arm pivot component
Signed-off-by: Dasun Abeykoon <[email protected]>
1 parent f89515e commit 3614430

File tree

1 file changed

+78
-0
lines changed

1 file changed

+78
-0
lines changed
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// Copyright (c) 2025 FRC 6423 - Ward Melville Iron Patriots
2+
// https://github.com/wmironpatriots
3+
//
4+
// Open Source Software; you can modify and/or share it under the terms of
5+
// MIT license file in the root directory of this project
6+
7+
package org.frc6423.robot.subsystems.arm;
8+
9+
import static edu.wpi.first.units.Units.Centimeters;
10+
import static edu.wpi.first.units.Units.KilogramSquareMeters;
11+
import static edu.wpi.first.units.Units.Radians;
12+
import static edu.wpi.first.units.Units.RadiansPerSecond;
13+
import static edu.wpi.first.units.Units.RadiansPerSecondPerSecond;
14+
import static edu.wpi.first.units.Units.Seconds;
15+
import static org.frc6423.robot.subsystems.arm.Arm.*;
16+
17+
import edu.wpi.first.math.MathUtil;
18+
import edu.wpi.first.math.controller.ArmFeedforward;
19+
import edu.wpi.first.math.controller.ProfiledPIDController;
20+
import edu.wpi.first.math.system.plant.DCMotor;
21+
import edu.wpi.first.math.trajectory.TrapezoidProfile;
22+
import edu.wpi.first.wpilibj.simulation.SingleJointedArmSim;
23+
import org.frc6423.robot.Constants;
24+
25+
/** Simulated version of the {@link ArmPivotIOReal} class */
26+
public class ArmPivotIOSim implements ArmPivotIO {
27+
private final DCMotor pivotModel = DCMotor.getKrakenX60Foc(1);
28+
private final SingleJointedArmSim pivotSim =
29+
new SingleJointedArmSim(
30+
pivotModel,
31+
GEARING,
32+
MOI.in(KilogramSquareMeters),
33+
LENGTH.in(Centimeters),
34+
MIN_ANGLE.in(Radians),
35+
MAX_ANGLE.in(Radians),
36+
true,
37+
0); // TODO measurement std devs arg
38+
39+
private final ArmFeedforward feedforward = new ArmFeedforward(S, G, V, A);
40+
private final ProfiledPIDController feedback =
41+
new ProfiledPIDController(
42+
P,
43+
I,
44+
D,
45+
new TrapezoidProfile.Constraints(
46+
MAX_VELOCITY.in(RadiansPerSecond), MAX_ACCELERATION.in(RadiansPerSecondPerSecond)));
47+
48+
@Override
49+
public double angle() {
50+
return pivotSim.getAngleRads();
51+
}
52+
53+
@Override
54+
public void setVoltage(double volts) {
55+
// Battery cannot output more than 12.0v
56+
pivotSim.setInputVoltage(MathUtil.clamp(volts, -12.0, 12.0));
57+
pivotSim.update(Constants.Flags.LOOPTIME.in(Seconds));
58+
}
59+
60+
@Override
61+
public void setAngle(double angleRads) {
62+
// Clamp goal angle within range
63+
angleRads = MathUtil.clamp(angleRads, MIN_ANGLE.in(Radians), MAX_ANGLE.in(Radians));
64+
// Get velocity of previous setpoint
65+
double lastVel = feedback.getSetpoint().velocity;
66+
67+
// Calculate new open-loop and closed-loop output
68+
double fbOut = feedback.calculate(angle(), angleRads);
69+
double ffOut =
70+
feedforward.calculateWithVelocities(angleRads, lastVel, feedback.getSetpoint().velocity);
71+
72+
// Sum output
73+
setVoltage(fbOut + ffOut);
74+
}
75+
76+
@Override
77+
public void close() {}
78+
}

0 commit comments

Comments
 (0)