Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
2b55554
Only "works" for talonfx but I need to commit to test
Strflightmight09 May 10, 2025
3b0f64d
Better prob
Strflightmight09 May 10, 2025
0393268
Oops
Strflightmight09 May 10, 2025
b99cc94
Trying smth
Strflightmight09 May 10, 2025
c4c8b1a
Oops
Strflightmight09 May 10, 2025
e8db114
Testing
Strflightmight09 May 10, 2025
e0b76dd
Remove testing (that part works)
Strflightmight09 May 10, 2025
ef1488b
More testing
Strflightmight09 May 10, 2025
75c3b8b
Omg I'm so stupid
Strflightmight09 May 10, 2025
49a3515
nvm
Strflightmight09 May 10, 2025
88e48ef
Wrong, but not _the_ problem
Strflightmight09 May 10, 2025
b416895
Test
Strflightmight09 May 11, 2025
4cf4d18
I should prob do this
Strflightmight09 May 11, 2025
c43315a
SImplify
Strflightmight09 May 11, 2025
68ecc92
_
Strflightmight09 May 11, 2025
a80bf39
Oops
Strflightmight09 May 11, 2025
efaf9fc
Better logging
Strflightmight09 May 11, 2025
a40296f
Fix
Strflightmight09 May 11, 2025
723cd44
Fix
Strflightmight09 May 11, 2025
948089f
Added arm even tho it doesn't work
Strflightmight09 May 14, 2025
395f300
Merge branch 'main' into subsystem-wrapper
Strflightmight09 Jul 1, 2025
e71735a
@ShmayaR - Have fun :)
Strflightmight09 Jul 1, 2025
0d053c8
fixed up the simpleMotorSubsystem (still missing simulation)
ShmayaR Jul 3, 2025
612c1a7
added logging stuff
ShmayaR Jul 3, 2025
17c777e
added option for setting target state with velocity
ShmayaR Jul 4, 2025
9be9ce1
@noamgreen12 CODEEEEEEEEEEEEEEEEEEEE
Strflightmight09 Jul 15, 2025
b9f1289
Added visualization offset @noamgreen12...
Strflightmight09 Jul 19, 2025
2340eac
Update SimpleMotorSubsystem.java
ShmayaR Jul 21, 2025
853e295
angular velocity gets logged instead of linear and set target velocit…
ShmayaR Jul 22, 2025
fd7a890
updated target state first
ShmayaR Jul 24, 2025
b933b18
set mechanism to update based on control mode
ShmayaR Jul 24, 2025
41fb35b
Update SimpleMotorSubsystem.java
ShmayaR Jul 24, 2025
1eab762
added position (in degrees) to the update log
ShmayaR Jul 24, 2025
a4f05cc
update name
ShmayaR Jul 24, 2025
8977f6d
put position on top
ShmayaR Jul 24, 2025
630e5b4
updated at target state to work with voltage control mode
ShmayaR Jul 24, 2025
91a72ee
added tolerances to at target state function
ShmayaR Jul 27, 2025
abc0f01
contol mode is now set when subsystem is created
ShmayaR Jul 27, 2025
62c0da4
Update SimpleMotorSubsystem.java
ShmayaR Jul 27, 2025
0316909
removed voltage tolerance and put things that belong in the config in…
ShmayaR Jul 27, 2025
c23b57d
at target state no longer checks the voltage but just if it has one
ShmayaR Jul 27, 2025
f03aecc
update name
ShmayaR Jul 28, 2025
c767967
Update SimpleMotorSubsystem.java
ShmayaR Jul 28, 2025
aef47a2
blahdwewed
ShmayaR Jul 28, 2025
49c96d7
fixed if statemennt
ShmayaR Jul 28, 2025
f420000
removed new line
ShmayaR Jul 28, 2025
081cabd
added java docs to flywheel
ShmayaR Aug 7, 2025
395e402
added docs for the rest of the configs
ShmayaR Aug 7, 2025
1e2ae32
changed interface to only have 1 thing difh
ShmayaR Aug 7, 2025
8b89049
added java docs for the interfaces
ShmayaR Aug 7, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package org.trigon.hardware.subsystems.arm;

import edu.wpi.first.math.geometry.Rotation2d;
import edu.wpi.first.math.system.plant.DCMotor;
import edu.wpi.first.wpilibj.util.Color;

public class ArmConfiguration {
public String name = "";

/**
* Length of the arm in meters.
*/
public double lengthMeters = 1;

/**
* Maximum velocity of the motor.
*/
public double maximumVelocity = 1;

/**
* Maximum acceleration of the motor.
*/
public double maximumAcceleration = 1;

/**
* Maximum jerk of the motor.
*/
public double maximumJerk = 1;
Comment on lines +15 to +28
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Units?


/**
* Ramp rate used in system identification.
* See <a href="https://docs.wpilib.org/en/stable/docs/software/advanced-controls/system-identification/introduction.html">
* WPILib System Identification Introduction</a>.
*/
public double sysIDRampRate = 1;

/**
* Step voltage used in system identification.
* See <a href="https://docs.wpilib.org/en/stable/docs/software/advanced-controls/system-identification/introduction.html">
* WPILib System Identification Introduction</a>.
*/
public double sysIDStepVoltage = 1;

public double gearRatio = 1;

/**
* Mass of the arm in kilograms.
*/
public double massKilograms = 1;

/**
* Visual offset for display in Mechanism2D.
*/
public double visualizationOffset = 1;
Comment on lines +51 to +54
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs more than just a rewording, this needs an explanation


/**
* Maximum angle of the arm.
*/
public Rotation2d maximumAngle = Rotation2d.kZero;

/**
* Minimum angle of the arm.
*/
public Rotation2d minimumAngle = Rotation2d.kZero;

/**
* Acceptable angular tolerance for reaching the target.
*/
public Rotation2d angleTolerance = Rotation2d.kZero;
Comment on lines +66 to +69
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for reaching the target isn't precise enough


public boolean focEnabled = true;

public boolean shouldSimulateGravity = true;

public Color mechanismColor = Color.kBlue;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public Color mechanismColor = Color.kBlue;
public Color mechanism2DColor = Color.kBlue;

Rn it sounds like the physical colour of the mechanism


/**
* The type and number of motors used in the simulation.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* The type and number of motors used in the simulation.
* The type and number of motors used for the simulation.

*/
public DCMotor gearbox = DCMotor.getKrakenX60Foc(1);
}
165 changes: 165 additions & 0 deletions src/main/java/org/trigon/hardware/subsystems/arm/ArmSubsystem.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
package org.trigon.hardware.subsystems.arm;

import com.ctre.phoenix6.controls.ControlRequest;
import com.ctre.phoenix6.controls.DynamicMotionMagicVoltage;
import com.ctre.phoenix6.controls.VoltageOut;
import edu.wpi.first.math.geometry.*;
import edu.wpi.first.units.Units;
import edu.wpi.first.wpilibj.sysid.SysIdRoutineLog;
import edu.wpi.first.wpilibj2.command.sysid.SysIdRoutine;
import org.littletonrobotics.junction.Logger;
import org.trigon.hardware.RobotHardwareStats;
import org.trigon.hardware.phoenix6.talonfx.TalonFXMotor;
import org.trigon.hardware.phoenix6.talonfx.TalonFXSignal;
import org.trigon.hardware.simulation.SingleJointedArmSimulation;
import org.trigon.utilities.mechanisms.SingleJointedArmMechanism2d;

public class ArmSubsystem {
private final TalonFXMotor motor;
private final Pose3d originPoint;
private final String name;
private final double
maximumVelocity,
maximumAcceleration,
maximumJerk,
visualizationOffsetFromGravityOffset;
private final Rotation2d angleTolerance;
private final VoltageOut voltageRequest;
private final DynamicMotionMagicVoltage positionRequest;
private final SingleJointedArmMechanism2d mechanism;
private final SysIdRoutine.Config sysIDConfig;
private ArmState targetState;

public ArmSubsystem(TalonFXMotor motor, ArmConfiguration config, Pose3d originPoint) {
this.motor = motor;
this.originPoint = originPoint;

name = config.name;
maximumVelocity = config.maximumVelocity;
maximumAcceleration = config.maximumAcceleration;
maximumJerk = config.maximumJerk;
angleTolerance = config.angleTolerance;
visualizationOffsetFromGravityOffset = config.visualizationOffset;
mechanism = new SingleJointedArmMechanism2d(name + "Mechanism", config.lengthMeters, config.mechanismColor);
voltageRequest = new VoltageOut(0).withEnableFOC(config.focEnabled);
positionRequest = new DynamicMotionMagicVoltage(0, maximumVelocity, maximumAcceleration, maximumJerk).withEnableFOC(config.focEnabled);
sysIDConfig = new SysIdRoutine.Config(
Units.Volts.of(config.sysIDRampRate).per(Units.Seconds),
Units.Volts.of(config.sysIDStepVoltage),
Units.Second.of(1000)
);
motor.setPhysicsSimulation(
new SingleJointedArmSimulation(
config.gearbox,
config.gearRatio,
config.massKilograms,
config.lengthMeters,
config.minimumAngle,
config.maximumAngle,
config.shouldSimulateGravity
));
}

public String getName() {
return name;
}

public SysIdRoutine.Config getSysIdConfig() {
return sysIDConfig;
}

public void setBrake(boolean brake) {
motor.setBrake(brake);
}

public void stop() {
motor.stopMotor();
}

public void updateLog(SysIdRoutineLog log) {
log.motor(name)
.angularPosition(Units.Rotations.of(motor.getSignal(TalonFXSignal.POSITION)))
.angularVelocity(Units.RotationsPerSecond.of(motor.getSignal(TalonFXSignal.VELOCITY)))
.voltage(Units.Volts.of(motor.getSignal(TalonFXSignal.MOTOR_VOLTAGE)));
}

public void updateMechanism() {
logComponentPose();

mechanism.update(
getAngle(),
Rotation2d.fromRotations(motor.getSignal(TalonFXSignal.CLOSED_LOOP_REFERENCE) + (RobotHardwareStats.isSimulation() ? 0 : visualizationOffsetFromGravityOffset))
);
}

public void updatePeriodically() {
motor.update();
Logger.recordOutput(name + "/CurrentAngle", getAngle());
}

public void sysIDDrive(double targetVoltage) {
motor.setControl(voltageRequest.withOutput(targetVoltage));
}

public boolean atState(ArmState targetState) {
return this.targetState == targetState && atTargetState();
}

public boolean atTargetState() {
if (targetState == null)
return false;
final double currentToTargetStateDifferenceDegrees = Math.abs(targetState.getTargetAngle().minus(getAngle()).getDegrees());
return currentToTargetStateDifferenceDegrees < angleTolerance.getDegrees();
}

public Rotation2d getAngle() {
return Rotation2d.fromRotations(motor.getSignal(TalonFXSignal.POSITION) + (RobotHardwareStats.isSimulation() ? 0 : visualizationOffsetFromGravityOffset));
}

public void setTargetState(ArmState targetState) {
this.targetState = targetState;
setTargetState(targetState.getTargetAngle(), targetState.getSpeedScalar());
}

public void setTargetState(Rotation2d targetAngle, double speedScalar) {
scalePositionRequestSpeed(speedScalar);
setTargetAngle(targetAngle);
}

public void setControl(ControlRequest request) {
motor.setControl(request);
}

private void scalePositionRequestSpeed(double speedScalar) {
positionRequest.Velocity = maximumVelocity * speedScalar;
positionRequest.Acceleration = maximumAcceleration * speedScalar;
positionRequest.Jerk = maximumJerk * speedScalar;
}

private void setTargetAngle(Rotation2d targetAngle) {
setControl(positionRequest.withPosition(targetAngle.getRotations() - (RobotHardwareStats.isSimulation() ? 0 : visualizationOffsetFromGravityOffset)));
}

private void logComponentPose() {
Logger.recordOutput("Poses/Components/" + name + "Pose", calculateComponentPose());
}

private Pose3d calculateComponentPose() {
final Transform3d armTransform = new Transform3d(
new Translation3d(),
new Rotation3d(0, getAngle().getRadians(), 0)
);
return originPoint.transformBy(armTransform);
}

/**
* An interface for an arm state.
* getTargetAngle represents the target angle of the state.
* getSpeedScalar represents the speed scalar of the state.
*/
public interface ArmState {
Comment on lines +155 to +160
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You still don't explain what it's for

Rotation2d getTargetAngle();

double getSpeedScalar();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package org.trigon.hardware.subsystems.elevator;

import edu.wpi.first.math.system.plant.DCMotor;
import edu.wpi.first.wpilibj.util.Color;

public class ElevatorConfiguration {
public String name = "";
/**
* Acceptable position error in meters.
*/
public double positionToleranceMeters = 1;
Comment on lines +8 to +11
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't consistent with how you described the arm one


/**
* Radius of the elevator drum in meters.
*/
public double drumRadiusMeters = 1;

/**
* Minimum elevator height in meters.
*/
public double minimumHeight = 1;

/**
* Maximum elevator height in meters.
*/
public double maximumHeight = 1;

/**
* Maximum velocity of the elevator in meters per second.
*/
public double maximumVelocity = 1;

/**
* Maximum acceleration of the elevator in meters per second squared.
*/
public double maximumAcceleration = 1;

/**
* Maximum jerk of the elevator in meters per second cubed.
*/
public double maximumJerk = 1;

/**
* Ramp rate used in system identification.
* See <a href="https://docs.wpilib.org/en/stable/docs/software/advanced-controls/system-identification/introduction.html">
* WPILib System Identification Introduction</a>.
*/
public double sysIDRampRate = 1;

/**
* Step voltage used in system identification.
* See <a href="https://docs.wpilib.org/en/stable/docs/software/advanced-controls/system-identification/introduction.html">
* WPILib System Identification Introduction</a>.
*/
public double sysIDStepVoltage = 1;

public double gearRatio = 1;
/**
* Mass of the Elevator in kg.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kilograms

*/
public double massKilograms = 1;

public boolean focEnabled = true;

public boolean shouldSimulateGravity = true;

public Color mechanismColor = Color.kBlue;

/**
* The type and number of motors used in the simulation.
*/
public DCMotor gearbox = DCMotor.getKrakenX60Foc(1);
}
Loading
Loading