Repository navigation
Stage 2 CTRE Solution Code - #175
roboteer5291 wants to merge 37 commits into
Conversation
|
🌐 Preview URL: https://pr-175.frcsoftware.pages.dev |
Daniel1464
left a comment
There was a problem hiding this comment.
I know this is still a draft, but left some preliminary comments since i have time
|
🌐 Preview URL: https://pr-175-frcsoftware.frcsoftware.workers.dev |
|
🌐 Preview URL: https://pr-175.frcsoftware.org Changed pages |
| pivot = new TalonFX(Constants.PIVOT_ID, Constants.BUS); | ||
| rollers = new TalonFX(Constants.ROLLERS_ID, Constants.BUS); |
There was a problem hiding this comment.
why are these here? Instantiate where they're declared
… stage2-ctre-solution
No idea how that was screwed up
| } | ||
|
|
||
| @Override | ||
| public void simulationPeriodic() { |
There was a problem hiding this comment.
I think it's better to put coralSim.periodic() under a RobotBase.isSimulation check inside robotPeriodic instead. (Just my opinion, but I think the dedicated simulationPeriodic method is kind of an anti-pattern)
There was a problem hiding this comment.
Why so? It's an included method. I do agree that the lack of clarity in the docs on the run order isn't great.
| table.log("Applied Voltage", Volts.of(getAppliedVoltage())); | ||
| table.log("Position", Rotations.of(getPosition())); | ||
| table.log("Velocity", RotationsPerSecond.of(getVelocity())); |
There was a problem hiding this comment.
These getters should return Units
There was a problem hiding this comment.
I disagree. We made a conscious decision to not use the units library because of the clunky math. Having getters that we use the value of for logic reasons (ie the position) return a non-unit value, or return a unit value just to unpackage it, doesn't really make sense. So all of the getters should return a non-unit value to be consistent there.
There was a problem hiding this comment.
or return a unit value just to unpackage it
Yet here you're unpacking it just to pack it up again.
There was a problem hiding this comment.
Yeah I don't love the unpack -> repack. Since we (presumably) want to log this data with units, I think it might be better to just get the value (with units) from the status signal directly, rather than having an intermediate helper function? You can keep the helpers that just return doubles
| .a() | ||
| .onTrue( | ||
| Command.noRequirements( | ||
| (coro) -> { |
There was a problem hiding this comment.
Why Coro instead of just co?
There was a problem hiding this comment.
I saw coro used somewhere, and decided to use that. That's it. I do feel like coro is a bit too short since you cut out the entire second part of coroutine (routine)
There was a problem hiding this comment.
Yeah I guess for teaching, anything shorter than coroutine is vague, but I wonder if wpilib examples use a specific name for this.
There was a problem hiding this comment.
I believe the wpilib examples all use coroutine
| .onTrue( | ||
| Command.parallel( | ||
| intake.setState(Intake.State.INTAKING), | ||
| indexer.setVoltage(12), |
There was a problem hiding this comment.
A command for indexing would be better than manually applying the voltage
| public ArmTest(Robot robot) { | ||
| CommandXboxController controller = new CommandXboxController(0); | ||
|
|
||
| controller.a().onTrue(robot.superstructure.setArmPosition(0)); |
There was a problem hiding this comment.
Should this OpMode move the elevator to a safe position?
| public ElevatorTest(Robot robot) { | ||
| CommandXboxController controller = new CommandXboxController(0); | ||
|
|
||
| controller.a().onTrue(robot.superstructure.setElevatorPosition(0)); |
There was a problem hiding this comment.
Likewise should this put the arm up so elevator can move freely
There was a problem hiding this comment.
You run into a catch-22 on these with your other comment to do this on the arm test opmode. I'll change it for the arm test opmode, but on the elevator test, I'm assuming you'd physically constrain the arm up there somehow. If you were bringing up a real robot, you'd only be able to tune one at once, and the same applies here since the arm code won't be written yet at the time of tuning the elevator.
There was a problem hiding this comment.
This isn't a tuning opmode, this is just testing that it goes to different positions. If it doesn't command the arm, then it'll become invalid once the arm is attached.
It should still command the arm, and the arm could have the API, but not actually be connected to anything requiring physical constraints until it does get written
There was a problem hiding this comment.
I definitely think this is a tuning opmode, as the intent is to use it with phoenix tuner or rev hardware client. In the context of the course, I think it's definitely a tuning opmode, since it'll be created immediately after the "Mechanisms" themselves to facilitate testing and tuning them.
There was a problem hiding this comment.
To be clear, I don't think putting it in a safe position is bad here. It's just odd from a sequence of events standpoint in terms of the course. The overall solution code here is the final state of the code, and I'm not sure how to make it so that an intermediate snapshot would work here, considering this code will likely be RLI'd into the course
DylanB5402
left a comment
There was a problem hiding this comment.
partial review - just the thoughts I've had so far, going to keep reading through this offline
|
|
||
| private static class Constants { | ||
| static final int MOTOR_ID = 22; | ||
| static final CANBus BUS = new CANBus(CANPort.CAN_S1); |
There was a problem hiding this comment.
(nitpick) we define the CANBus as its own variable here, but we don't in other subsystems. I don't think we're using the CANBus variable here, so we should probably just construct it inline in the TalonFX constructor. Or maybe define the bus variables somewhere else and pass them around? idk how I feel about that
|
|
||
| public class Arm { | ||
|
|
||
| private static class Constants { |
There was a problem hiding this comment.
Can't remember if I commented on the Constants static class before. I don't love it, probably wouldn't run it with my own team, but if that's a convention we want to use and there's consensus on it, I'm ok with it
There was a problem hiding this comment.
From what I recall there wasn't ever a clear consensus in any direction. I personally like it as a least-bad option. Dedicated constants file being bad, and not liking the constants just scattered among everything else.
| table.log("Applied Voltage", Volts.of(getAppliedVoltage())); | ||
| table.log("Position", Rotations.of(getPosition())); | ||
| table.log("Velocity", RotationsPerSecond.of(getVelocity())); |
There was a problem hiding this comment.
Yeah I don't love the unpack -> repack. Since we (presumably) want to log this data with units, I think it might be better to just get the value (with units) from the status signal directly, rather than having an intermediate helper function? You can keep the helpers that just return doubles
DylanB5402
left a comment
There was a problem hiding this comment.
second round of reviews! Also, can we get an ascope layout for this / maybe double check keybinds too in simgui-ds.json? I was able to drive with WASD once I set the keyboard as a joystick in the simgui, not sure what other buttons were supposed to do.
| new Slot0Configs().withKP(0.3).withKI(0).withKD(0).withKS(0.2).withKV(0.125)) | ||
| // .withDriveMotorGains(new Slot0Configs() | ||
| // .withKP(0.3).withKI(0).withKD(0) | ||
| // .withKS(0.1498).withKV(3.16356)) |
There was a problem hiding this comment.
Should clean up the comment code in this file? unless you have a reason to keep it
| .named("Stop Drive"); | ||
| } | ||
|
|
||
| public static class AutoAlignCommand implements Command { |
There was a problem hiding this comment.
What's the reasoning for making this its own Class? Generally have an aversion to class commands, though I'm not sure how relevant that is for 2026. There also is a lot of logic going on here, +1 to the other comment asking about breaking it out into its own file. I wonder if there's any way we could simplify this or write it in a more functional/imperative way?
Might just be a preference / code style thing going on here: this command looks like it's trying to handle a number of different scenarios, while I think I'd rather build smaller commands that are more specific in purpose. This command feels a little too stateful in a way that I'm not sure we want to encourage students to write their own code
| new Slot0Configs().withKP(0.3).withKI(0).withKD(0).withKS(0.2).withKV(0.125)) | ||
| // .withDriveMotorGains(new Slot0Configs() | ||
| // .withKP(0.3).withKI(0).withKD(0) | ||
| // .withKS(0.1498).withKV(3.16356)) |
There was a problem hiding this comment.
Decent bit of commented out code throughout this file, can we clean it up (or if there's a reason for it to be commented out that's fine)
| } | ||
|
|
||
| private final TalonFX pivot = new TalonFX(Constants.PIVOT_ID, Constants.BUS); | ||
| private final TalonFX rollers = new TalonFX(Constants.ROLLERS_ID, Constants.BUS); |
There was a problem hiding this comment.
Not entirely sure how I feel about the pivot and rollers being in the same Mechanism. I'm personally a fan of splitting them just to get a little bit of separation and looser coupling, but I can see the case for having them as the same mechanism too, not sure if there's been other thought/discussion about this
| table.log("Active Commands", getRunningCommands().toString()); | ||
| } | ||
|
|
||
| public Command setArmVoltage(double voltage) { |
There was a problem hiding this comment.
Doesn't having commands that only run half the subsystem (just arm or just elevator) open up some edge cases where you have a command for the elevator that runs but then gets interrupted by an arm command?
These commands also only look to be called by the opmode, so maybe it's not a big deal? Maybe it's worth having setArm also explicitly set elevator to 0 volts or something
| // .named("Set Position"); | ||
| // } | ||
|
|
||
| public Command setPosition(double elevatorPosition, double armPosition) { |
There was a problem hiding this comment.
Maybe more thought experiment than actual feedback: I wonder how this command changes if you split arm and elevator into separate mechanisms?
I'm thinking that you get to make use of some of the more interesting ways to chain/compose/fork commands if you run them as separate subsystems, but I don't think it matters too much in practice, pretty sure Superstructure being its own mechanism is pretty set in stone at this point.
Creates stage 2 CTRE Solution Code. Still very much a WIP
Claude assisted with some debugging and outlining of the parts of the collision avoidance logic. All code written by hand, in the end.
Todo: