Skip to content

Commit 5b855f1

Browse files
committed
Subsystem and IO class for double jointed arm
1 parent 32f378b commit 5b855f1

File tree

2 files changed

+128
-0
lines changed

2 files changed

+128
-0
lines changed
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package com.stuypulse.robot.subsystems.double_jointed_arm;
2+
3+
import com.stuypulse.robot.Robot;
4+
import com.stuypulse.robot.constants.Constants;
5+
import com.stuypulse.stuylib.math.SLMath;
6+
7+
import edu.wpi.first.math.Matrix;
8+
import edu.wpi.first.math.geometry.Rotation2d;
9+
import edu.wpi.first.math.geometry.Translation2d;
10+
import edu.wpi.first.math.numbers.N1;
11+
import edu.wpi.first.math.numbers.N2;
12+
import edu.wpi.first.wpilibj2.command.SubsystemBase;
13+
14+
public class DoubleJointedArm extends SubsystemBase {
15+
16+
private static DoubleJointedArm instance;
17+
18+
private DoubleJointedArmIO io;
19+
private DoubleJointedArmIOInputsAutoLogged inputs = new DoubleJointedArmIOInputsAutoLogged();
20+
21+
public enum DoubleJointedArmState {
22+
STOW(Rotation2d.fromDegrees(10), Rotation2d.fromDegrees(10));
23+
24+
private Rotation2d shoulderTargetAngle;
25+
private Rotation2d elbowTargetAngle;
26+
27+
private DoubleJointedArmState(Rotation2d shoulderTargetAngle, Rotation2d elbowTargetAngle){
28+
this.shoulderTargetAngle = Rotation2d.fromDegrees(
29+
SLMath.clamp(shoulderTargetAngle.getDegrees(),
30+
Constants.DoubleJointedArm.Shoulder.MIN_ANGLE.getDegrees(),
31+
Constants.DoubleJointedArm.Shoulder.MAX_ANGLE.getDegrees()));
32+
this.elbowTargetAngle = Rotation2d.fromDegrees(
33+
SLMath.clamp(elbowTargetAngle.getDegrees(),
34+
Constants.DoubleJointedArm.Elbow.MIN_ANGLE.getDegrees(),
35+
Constants.DoubleJointedArm.Elbow.MAX_ANGLE.getDegrees()));
36+
}
37+
38+
public Rotation2d getShoulderTargetAngle(){
39+
return this.shoulderTargetAngle;
40+
}
41+
42+
public Rotation2d getElbowTargetAngle(){
43+
return this.elbowTargetAngle;
44+
}
45+
46+
private DoubleJointedArmState state;
47+
48+
public DoubleJointedArmState getState(){
49+
return this.state;
50+
}
51+
}
52+
53+
@Override
54+
public void periodic() {
55+
// PUT ALL CALLS TO CONTROL METHODS HERE
56+
}
57+
58+
/* LOGIC for controlling the double jointed arm: */
59+
60+
// 0. Measure system: angle, angular velocity, angular acceleration
61+
62+
// 1. Find M, C, G (mass inertia matrix, centrifugal + coriolis matrix, gravity torque matrix)
63+
64+
// 2. Given a current position (x, y) for the end effector on the double jointed arm, pathfind to a target position (x, y) and calculate the required angular position, velocity, and acceleration
65+
66+
// 3. Feed the current angular states and target angular states into the PID controllers for each joint
67+
68+
// 4. Calculate the three matrices using the angular states, which outputs a toruqe input
69+
70+
// 5. Using torque current control on the motor, feed the torque input into the motor
71+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package com.stuypulse.robot.subsystems.double_jointed_arm;
2+
3+
import org.littletonrobotics.junction.AutoLog;
4+
5+
import edu.wpi.first.math.Matrix;
6+
import edu.wpi.first.math.geometry.Rotation2d;
7+
import edu.wpi.first.math.geometry.Translation2d;
8+
import edu.wpi.first.math.numbers.N1;
9+
import edu.wpi.first.math.numbers.N2;
10+
11+
public interface DoubleJointedArmIO {
12+
@AutoLog
13+
public class DoubleJointedArmIOInputs {
14+
public DoubleJointedArmIOData data =
15+
new DoubleJointedArmIOData(false, false, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
16+
}
17+
18+
record DoubleJointedArmIOData(
19+
boolean shoulderMotorConnected,
20+
boolean elbowMotorConnected,
21+
22+
double shoulderAngle,
23+
double shoulderAngularVel,
24+
double shoulderAngularAccel,
25+
double shoulderAppliedVolts,
26+
double shoulderCurrentAmps,
27+
28+
double elbowAngle,
29+
double elbowAngularAccel,
30+
double elbowAngularVel,
31+
double elbowAppliedVolts,
32+
double elbowCurrentAmps) {}
33+
34+
// STATES
35+
public abstract void updateInputs(DoubleJointedArmIOInputs inputs);
36+
37+
// CONTROL
38+
public abstract void runTorqueCurrentShoulder(double torqueCurrentAmps);
39+
public abstract void runTorqueCurrentElbow(double torqueCurrentAmps);
40+
public abstract void runVolts(double volts); // ONLY voltage override
41+
public abstract void setTargetAngles(Rotation2d shoulderAngle, Rotation2d elbowAngle);
42+
public abstract void setPID(double kP, double kI, double kD);
43+
44+
// BOOLEANS
45+
public abstract boolean isShoulderAtTarget();
46+
public abstract boolean isElbowAtTarget();
47+
public abstract boolean isArmAtTarget();
48+
49+
// MATH
50+
public abstract Matrix<N2, N2> calculateMMatrix(); // Mass Inertia Matrix
51+
public abstract Matrix<N2, N2> calculateCMatrix(); // Centrifugal + Coriolis Matrix
52+
public abstract Matrix<N2, N1> calculateGMatrix(); // Torque due to Gravity Matrix
53+
public abstract Translation2d getEndPosition();
54+
55+
56+
57+
}

0 commit comments

Comments
 (0)