diff --git a/examples/stage1/stage1a/solutions/ctre/src/main/java/first/robot/Robot.java b/examples/stage1/stage1a/solutions/ctre/src/main/java/first/robot/Robot.java index 7695d159..d6f041d7 100644 --- a/examples/stage1/stage1a/solutions/ctre/src/main/java/first/robot/Robot.java +++ b/examples/stage1/stage1a/solutions/ctre/src/main/java/first/robot/Robot.java @@ -12,12 +12,14 @@ import com.ctre.phoenix6.signals.InvertedValue; import com.ctre.phoenix6.signals.MotorAlignmentValue; import first.robot.simulation.DrivetrainSim; +import first.robot.simulation.FuelSim; import first.robot.simulation.SingleFlywheelSim; import org.wpilib.drive.DifferentialDrive; import org.wpilib.framework.OpModeRobot; import org.wpilib.hardware.imu.OnboardIMU; import org.wpilib.hardware.imu.OnboardIMU.MountOrientation; +// [FullRobot] // [RobotWithSimPart1] // [RobotTop] /** @@ -56,12 +58,19 @@ public class Robot extends OpModeRobot { // [/DrivetrainSim] // [/RobotWithSimPart1] + // [AdditionalMotors] public TalonFX intakeLauncher = new TalonFX(4, CANBus.systemcore(0)); public TalonFX feeder = new TalonFX(5, CANBus.systemcore(0)); + // [/AdditionalMotors] + // [IntakeLauncherSim] private SingleFlywheelSim intakeLauncherSim = SingleFlywheelSim.forIntakeLauncher(intakeLauncher); + // [/IntakeLauncherSim] + // [FeederSim] private SingleFlywheelSim feederSim = SingleFlywheelSim.forFeeder(feeder); + // [/FeederSim] + // [RobotWithSimPart2] // [AllConfigs] /** @@ -99,8 +108,15 @@ public Robot() { public void simulationPeriodic() { drivetrainSim.periodic(); // [/DriveSimPeriodic] + // [MotorSimPeriodic] intakeLauncherSim.periodic(); feederSim.periodic(); + // [/MotorSimPeriodic] + + // [FuelSimPeriodic] + FuelSim.periodic(); + // [/FuelSimPeriodic] } // [/RobotWithSimPart2] + // [/FullRobot] } diff --git a/examples/stage1/stage1a/solutions/ctre/src/main/java/first/robot/opmode/MyAuto.java b/examples/stage1/stage1a/solutions/ctre/src/main/java/first/robot/opmode/MyAuto.java index 0e2ce261..cc4573dc 100644 --- a/examples/stage1/stage1a/solutions/ctre/src/main/java/first/robot/opmode/MyAuto.java +++ b/examples/stage1/stage1a/solutions/ctre/src/main/java/first/robot/opmode/MyAuto.java @@ -25,6 +25,7 @@ public void start() { autoTimer.restart(); // Reset the timer to zero at the start of auto } + // [SimpleAutoStart] /* * This method runs periodically, using the same period as the Robot instance. * @@ -35,8 +36,11 @@ public void start() { public void periodic() { if (autoTimer.hasElapsed(4.0)) { // Drive for 4 seconds after the start of auto robot.drivetrain.arcadeDrive(0.0, 0.0); // Stop the drivetrain after 4 seconds + // [/SimpleAutoStart] + // [SimpleAutoEnd] } else { robot.drivetrain.arcadeDrive(0.5, 0.0); // Drive forward at half speed with no rotation } } + // [/SimpleAutoEnd] } diff --git a/examples/stage1/stage1a/solutions/ctre/src/main/java/first/robot/opmode/MyTeleop.java b/examples/stage1/stage1a/solutions/ctre/src/main/java/first/robot/opmode/MyTeleop.java index 29b59bb6..cffbacca 100644 --- a/examples/stage1/stage1a/solutions/ctre/src/main/java/first/robot/opmode/MyTeleop.java +++ b/examples/stage1/stage1a/solutions/ctre/src/main/java/first/robot/opmode/MyTeleop.java @@ -32,25 +32,33 @@ public void periodic() { // [/DriveSimPeriodic] // [/FullDrivetrain] + // [launchFuel] if (xboxController.getRightBumperButton()) { - // shoot + // launch robot.intakeLauncher.setThrottle(0.9); robot.feeder.setThrottle(0.75); + // [/launchFuel] + // [intakeFuel] } else if (xboxController.getLeftBumperButton()) { // intake robot.intakeLauncher.setThrottle(0.8); robot.feeder.setThrottle(-1.0); + // [/intakeFuel] + // [outakeFuel] } else if (xboxController.getAButton()) { // outake robot.intakeLauncher.setThrottle(-0.8); robot.feeder.setThrottle(1.0); + // [/outakeFuel] + // [stopMotors] } else { // stop robot.intakeLauncher.setThrottle(0.0); robot.feeder.setThrottle(0.0); } + // [/stopMotors] } } diff --git a/examples/stage1/stage1a/solutions/ctre/src/main/java/first/robot/simulation/FuelSim.java b/examples/stage1/stage1a/solutions/ctre/src/main/java/first/robot/simulation/FuelSim.java index 60a7b648..daa5096d 100644 --- a/examples/stage1/stage1a/solutions/ctre/src/main/java/first/robot/simulation/FuelSim.java +++ b/examples/stage1/stage1a/solutions/ctre/src/main/java/first/robot/simulation/FuelSim.java @@ -54,7 +54,7 @@ private enum Mode { static Supplier robotPoseSupplier = () -> Pose2d.kZero; /** Updates the fuel sim. */ - public static void update() { + public static void periodic() { updateMode(); updateVisualization(); } diff --git a/examples/stage1/stage1a/solutions/rev/src/main/java/first/robot/Robot.java b/examples/stage1/stage1a/solutions/rev/src/main/java/first/robot/Robot.java index 074ef915..77d03bf3 100644 --- a/examples/stage1/stage1a/solutions/rev/src/main/java/first/robot/Robot.java +++ b/examples/stage1/stage1a/solutions/rev/src/main/java/first/robot/Robot.java @@ -18,6 +18,7 @@ import org.wpilib.hardware.imu.OnboardIMU; import org.wpilib.hardware.imu.OnboardIMU.MountOrientation; +// [FullRobot] // [RobotWithSimPart1] // [RobotTop] /** @@ -53,12 +54,19 @@ public class Robot extends OpModeRobot { // [/DrivetrainSim] // [/RobotWithSimPart1] + // [AdditionalMotors] public SparkMax intakeLauncher = new SparkMax(0, 4, MotorType.kBrushless); public SparkMax feeder = new SparkMax(0, 5, MotorType.kBrushless); + // [/AdditionalMotors] + // [IntakeLauncherSim] private SingleFlywheelSim intakeLauncherSim = SingleFlywheelSim.forIntakeLauncher(intakeLauncher); + // [/IntakeLauncherSim] + // [FeederSim] private SingleFlywheelSim feederSim = SingleFlywheelSim.forFeeder(feeder); + // [/FeederSim] + // [RobotWithSimPart2] // [AllConfigs] /** @@ -101,8 +109,14 @@ public void simulationPeriodic() { drivetrainSim.periodic(); // [/DriveSimPeriodic] intakeLauncherSim.periodic(); + // [MotorSimPeriodic] feederSim.periodic(); - FuelSim.update(); + // [/MotorSimPeriodic] + + // [FuelSimPeriodic] + FuelSim.periodic(); + // [/FuelSimPeriodic] } // [/RobotWithSimPart2] } +// [/FullRobot] diff --git a/examples/stage1/stage1a/solutions/rev/src/main/java/first/robot/opmode/MyAuto.java b/examples/stage1/stage1a/solutions/rev/src/main/java/first/robot/opmode/MyAuto.java index 826a6956..fb0ec75f 100644 --- a/examples/stage1/stage1a/solutions/rev/src/main/java/first/robot/opmode/MyAuto.java +++ b/examples/stage1/stage1a/solutions/rev/src/main/java/first/robot/opmode/MyAuto.java @@ -13,23 +13,34 @@ @Autonomous(name = "My Auto", group = "Group 1") public class MyAuto extends PeriodicOpMode { private final Robot robot; - private Timer timer = new Timer(); + private Timer autoTimer = new Timer(); + /** The Robot instance is passed into the opmode via the constructor. */ public MyAuto(Robot robot) { this.robot = robot; } @Override public void start() { - timer.restart(); + autoTimer.restart(); } + // [SimpleAutoStart] + /* + * This method runs periodically, using the same period as the Robot instance. + * + * Additional periodic methods may be configured with addPeriodic(), + * which can have periods that differ from the main Robot instance. + */ @Override public void periodic() { - if (timer.hasElapsed(4)) { + if (autoTimer.hasElapsed(4)) { robot.drivetrain.arcadeDrive(0.0, 0.0); // Stop the robot after 4 seconds + // [/SimpleAutoStart] + // [SimpleAutoEnd] } else { robot.drivetrain.arcadeDrive(0.5, 0.0); // Drive forward at half speed with no rotation } } + // [/SimpleAutoEnd] } diff --git a/examples/stage1/stage1a/solutions/rev/src/main/java/first/robot/opmode/MyTeleop.java b/examples/stage1/stage1a/solutions/rev/src/main/java/first/robot/opmode/MyTeleop.java index 50e6fa0c..5ae1e5e3 100644 --- a/examples/stage1/stage1a/solutions/rev/src/main/java/first/robot/opmode/MyTeleop.java +++ b/examples/stage1/stage1a/solutions/rev/src/main/java/first/robot/opmode/MyTeleop.java @@ -31,22 +31,33 @@ public void periodic() { // [/DriveSimPeriodic] // [/FullDrivetrain] + // [launchFuel] if (xboxController.getRightBumperButton()) { - // shoot + // launch robot.intakeLauncher.setThrottle(0.9); robot.feeder.setThrottle(0.75); + + // [/launchFuel] + // [intakeFuel] } else if (xboxController.getLeftBumperButton()) { // intake robot.intakeLauncher.setThrottle(0.8); robot.feeder.setThrottle(-1.0); + + // [/intakeFuel] + // [outakeFuel] } else if (xboxController.getAButton()) { // outtake robot.intakeLauncher.setThrottle(-0.8); robot.feeder.setThrottle(1.0); + + // [/outakeFuel] + // [stopMotors] } else { // stop robot.intakeLauncher.setThrottle(0.0); robot.feeder.setThrottle(0.0); } + // [/stopMotors] } } diff --git a/examples/stage1/stage1a/solutions/rev/src/main/java/first/robot/simulation/FuelSim.java b/examples/stage1/stage1a/solutions/rev/src/main/java/first/robot/simulation/FuelSim.java index 60a7b648..daa5096d 100644 --- a/examples/stage1/stage1a/solutions/rev/src/main/java/first/robot/simulation/FuelSim.java +++ b/examples/stage1/stage1a/solutions/rev/src/main/java/first/robot/simulation/FuelSim.java @@ -54,7 +54,7 @@ private enum Mode { static Supplier robotPoseSupplier = () -> Pose2d.kZero; /** Updates the fuel sim. */ - public static void update() { + public static void periodic() { updateMode(); updateVisualization(); } diff --git a/public/learning-course/stage1/stage1a/3dField.webm b/public/learning-course/stage1/stage1a/3dField.webm new file mode 100644 index 00000000..57378205 Binary files /dev/null and b/public/learning-course/stage1/stage1a/3dField.webm differ diff --git a/public/learning-course/stage1/stage1a/LineGraph.webm b/public/learning-course/stage1/stage1a/LineGraph.webm new file mode 100644 index 00000000..6c3cdda7 Binary files /dev/null and b/public/learning-course/stage1/stage1a/LineGraph.webm differ diff --git a/public/learning-course/stage1/stage1a/RunningMyAuto.webm b/public/learning-course/stage1/stage1a/RunningMyAuto.webm new file mode 100644 index 00000000..8244ad88 Binary files /dev/null and b/public/learning-course/stage1/stage1a/RunningMyAuto.webm differ diff --git a/public/learning-course/stage1/stage1a/feederMotor.webp b/public/learning-course/stage1/stage1a/feederMotor.webp new file mode 100644 index 00000000..736b045a Binary files /dev/null and b/public/learning-course/stage1/stage1a/feederMotor.webp differ diff --git a/public/learning-course/stage1/stage1a/intakeLauncher.webp b/public/learning-course/stage1/stage1a/intakeLauncher.webp new file mode 100644 index 00000000..c0d80e53 Binary files /dev/null and b/public/learning-course/stage1/stage1a/intakeLauncher.webp differ diff --git a/src/config/sidebarConfig.ts b/src/config/sidebarConfig.ts index 9c23f986..bd19e93b 100644 --- a/src/config/sidebarConfig.ts +++ b/src/config/sidebarConfig.ts @@ -115,14 +115,14 @@ export const sidebarSections: Record = { label: 'Drivetrain Simulation', slug: 'learning-course/stage1/stage1a/drivetrain-sim', }, - // { - // label: 'TBD', - // slug: 'stage-1a-commands/the-command-body', - // }, - // { - // label: 'TBD', - // slug: 'stage-1a-commands/commands-and-mechanisms', - // }, + { + label: 'Simple Auto', + slug: 'learning-course/stage1/stage1a/simple-auto', + }, + { + label: 'Additional Motors', + slug: 'learning-course/stage1/stage1a/kitbot-additional-motors', + }, ], }, { diff --git a/src/content/docs/learning-course/stage1/stage1a/drivetrain-sim.mdx b/src/content/docs/learning-course/stage1/stage1a/drivetrain-sim.mdx index 725aaf60..80b1ba75 100644 --- a/src/content/docs/learning-course/stage1/stage1a/drivetrain-sim.mdx +++ b/src/content/docs/learning-course/stage1/stage1a/drivetrain-sim.mdx @@ -3,6 +3,9 @@ title: Kitbot Drivetrain Simulation description: Writing the code to simulate the kitbot drivetrain prev: kitbot-drivetrain next: false +codeRegionSources: + ctreRobot: stage1/stage1a/solutions/ctre/src/main/java/first/robot/Robot.java + revRobot: stage1/stage1a/solutions/rev/src/main/java/first/robot/Robot.java --- import { Tabs, TabItem } from '@astrojs/starlight/components'; @@ -28,13 +31,13 @@ The class will then publish the new drivetrain position and additional motor dat - ```java stage1/stage1a/solutions/ctre/src/main/java/first/robot/Robot.java#DrivetrainSim + ```java {ctreRobot}#DrivetrainSim ``` - ```java stage1/stage1a/solutions/rev/src/main/java/first/robot/Robot.java#DrivetrainSim + ```java {revRobot}#DrivetrainSim ``` @@ -55,13 +58,13 @@ To fix this, `DrivetrainSim`'s `periodic()` function should be called inside of - ```java stage1/stage1a/solutions/ctre/src/main/java/first/robot/Robot.java#DriveSimPeriodic + ```java {ctreRobot}#DriveSimPeriodic ``` - ```java stage1/stage1a/solutions/rev/src/main/java/first/robot/Robot.java#DriveSimPeriodic + ```java {revRobot}#DriveSimPeriodic ``` @@ -84,17 +87,17 @@ After adding the simulation code your `Robot.java` file should now look like thi - ```java stage1/stage1a/solutions/ctre/src/main/java/first/robot/Robot.java#RobotWithSimPart1 + ```java {ctreRobot}#RobotWithSimPart1 ``` - ```java stage1/stage1a/solutions/ctre/src/main/java/first/robot/Robot.java#RobotWithSimPart2 + ```java {ctreRobot}#RobotWithSimPart2 ``` - ```java stage1/stage1a/solutions/rev/src/main/java/first/robot/Robot.java#RobotWithSimPart1 + ```java {revRobot}#RobotWithSimPart1 ``` - ```java stage1/stage1a/solutions/rev/src/main/java/first/robot/Robot.java#RobotWithSimPart2 + ```java {revRobot}#RobotWithSimPart2 ``` diff --git a/src/content/docs/learning-course/stage1/stage1a/kitbot-additional-motors.mdx b/src/content/docs/learning-course/stage1/stage1a/kitbot-additional-motors.mdx new file mode 100644 index 00000000..ebec34ce --- /dev/null +++ b/src/content/docs/learning-course/stage1/stage1a/kitbot-additional-motors.mdx @@ -0,0 +1,276 @@ +--- +title: Kitbot Additional Motors +description: Programming the remaining kitbot motors +prev: simple-auto +next: false +codeRegionSources: + ctreRobot: stage1/stage1a/solutions/ctre/src/main/java/first/robot/Robot.java + revRobot: stage1/stage1a/solutions/rev/src/main/java/first/robot/Robot.java + ctreTeleop: stage1/stage1a/solutions/ctre/src/main/java/first/robot/opmode/MyTeleop.java + revTeleop: stage1/stage1a/solutions/rev/src/main/java/first/robot/opmode/MyTeleop.java +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; +import { REV_CTRE_CHOOSER_KEY } from '@data/tabsSyncKeys.ts'; + +# Remaining Motors + +The kitbot has two additional motors that allow it to intake and shoot fuel. + +The IntakeLauncher motor powers the intake roller and the launcher flywheel. + + + +The Feeder motor feeds fuel into the hopper, into the launcher, or out of the intake depending on the direction it spins. + + + +The IntakeLauncher motor will be on CAN Bus 0 with a CAN Id of 4 while the Feeder motor will be on CAN Bus 0 with a CAN Id of 5. + +Inside of the `Robot.java` file create a motor controller instance for the IntakeLauncher and Feeder motors. + + + + + ```java {ctreRobot}#AdditionalMotors + ``` + + + + + ```java {revRobot}#AdditionalMotors + ``` + + + + + +# Simulating Additional Motors + +Like the drivetrain, the `SingleFlywheelSim` class is provided which abstracts much of the simulation code. +The `SingleFlywheelSim` has different static methods for the LauncherFeeder and Intake motors which return instances of `SingleFlywheelSim` with settings for those specific motors. + +Creating the `SingleFlywheelSim` instance for the LauncherFeeder motor will look like this + + + + + ```java {ctreRobot}#IntakeLauncherSim + ``` + + + + + ```java {revRobot}#IntakeLauncherSim + ``` + + + + + +Now try creating the `SingleFlywheelSim` instance for the Intake motor. +This will instead use the `forFeeder()` method. + +
+ Solution + + + + ```java {ctreRobot}#FeederSim + ``` + + + + + ```java {revRobot}#FeederSim + ``` + + + + +
+ +To make the simulated motor controllers update, the `SingleFlywheelSim` instances' `periodic()` functions need to be called inside of `simulationPeriodic()`. + + + + + ```java {ctreRobot}#MotorSimPeriodic + ``` + + + + + ```java {revRobot}#MotorSimPeriodic + ``` + + + + + +# Fuel Sim + +If the code was to be simulated at this point, the motors could be controlled using keyboard inputs and the resulting motor speeds could be viewed with a graph inside of AdvantageScope. +While this is a functional solution, it can be made more interesting by taking advantage of AdvantageScope's 3d tab. +AdvantageScope's 3d tab displays robots and game pieces inside of a game field using data published from the robot code. +The `FuelSim` class provides simulation data for fuel game pieces to be visualized entering and exiting the robot. +References to the IntakeLauncher and Feeder motors are given to the `FuelSim` class when the `SingleFlywheelSim` instances are created. + +To make the `FuelSim` class function, its `periodic()` function needs to be called inside of `simulationPeriodic()`. + + + + + ```java {ctreRobot}#FuelSimPeriodic + ``` + + + + + ```java {revRobot}#FuelSimPeriodic + ``` + + + + + +# Check Up + +The `Robot` class is now completed! +At this point your `Robot` class should look like this + +
+ Robot Solution + + + + ```java {ctreRobot}#FullRobot + ``` + + + + + ```java {revRobot}#FullRobot + ``` + + + + +
+ +# Additional Motors in Teleop + +To control the new motors, the motors need to be commanded inside of the `MyTeleop` OpMode's `periodic()` function. +When the controller's right bumper is pressed, the `IntakeLauncher` motor should have a throttle of 0.9 while the `Feeder` motor should have a throttle of 0.75. +This will launch the fuel. + + + + + ```java {ctreTeleop}#launchFuel + ``` + + + + + ```java {revTeleop}#launchFuel + ``` + + + + + +When the controller's left bumper is pressed the IntakeLauncher motor should have a throttle of 0.8 while the Feeder motor should have a throttle of -1.0. +This will intake the fuel. + + + + + ```java {ctreTeleop}#intakeFuel + ``` + + + + + ```java {revTeleop}#intakeFuel + ``` + + + + + +When the controller's A button is pressed the IntakeLauncher motor should have a throttle of -0.8 while the Feeder motor should have a throttle of 1.0. +This will outake the fuel. + + + + + ```java {ctreTeleop}#outakeFuel + ``` + + + + + ```java {revTeleop}#outakeFuel + ``` + + + + + +When none of the previous button are pressed the IntakeLauncher should have a throttle of 0.0 while the Feeder motor should have a throttle of 0.0. +This will stop the motors. + + + + + ```java {ctreTeleop}#stopMotors + ``` + + + + + ```java {revTeleop}#stopMotors + ``` + + + + + +# Line Graph + +The process for testing the new motors in teleop is very similar to the process used to test the drivetrain. +Holding the "E" key will cause the robot to intake, "Q" will cause the robot to launch. +and "R" will cause the robot to outake. +Instead of looking at the 2D Field tab in Advantage Scope, use the Line Graph tab to view data from the motors. +The voltage applied from the motor controllers to their motors can be viewed on the left axis while the right axis shows the motors' velocities. + +Video showing line 2d graph running goes here. + + + +The 3D Field tab will show a 3D rendering of the kitbot, fuel, and game field. +As the robot preforms different actions the fuel should appear or disappear to show these actions. +You should also still be able to move using the WASD keys. + + + +# Additional Practice + +Try improving upon previously created autos by adding robot actions to them. diff --git a/src/content/docs/learning-course/stage1/stage1a/kitbot-drivetrain.mdx b/src/content/docs/learning-course/stage1/stage1a/kitbot-drivetrain.mdx index 1d8f0530..f87db588 100644 --- a/src/content/docs/learning-course/stage1/stage1a/kitbot-drivetrain.mdx +++ b/src/content/docs/learning-course/stage1/stage1a/kitbot-drivetrain.mdx @@ -3,6 +3,11 @@ title: Kitbot Drivetrain description: Programming the kitbot drivetrain prev: stage-overview next: drivetrain-sim +codeRegionSources: + ctreRobot: stage1/stage1a/solutions/ctre/src/main/java/first/robot/Robot.java + revRobot: stage1/stage1a/solutions/rev/src/main/java/first/robot/Robot.java + ctreTeleop: stage1/stage1a/solutions/ctre/src/main/java/first/robot/opmode/MyTeleop.java + revTeleop: stage1/stage1a/solutions/rev/src/main/java/first/robot/opmode/MyTeleop.java --- import { Tabs, TabItem } from '@astrojs/starlight/components'; @@ -48,7 +53,7 @@ This is how the motor controller objects for the left motors will look. - ```java stage1/stage1a/solutions/ctre/src/main/java/first/robot/Robot.java#DriveMotorsLeft + ```java {ctreRobot}#DriveMotorsLeft ``` For the CTRE code, the CAN ID of the leader motors are stored as a variable since they will be used later on to tell the follower which motor controller to follow. @@ -57,7 +62,7 @@ Additionally, CTRE uses a CANBus object to store the CANBus instead of just an i - ```java stage1/stage1a/solutions/rev/src/main/java/first/robot/Robot.java#DriveMotorsLeft + ```java {revRobot}#DriveMotorsLeft ``` Since the Spark Max can control both brushed and brushless motors it's necessary to specify the type as `MotorType.kBrushless` for motors like a NEO and `MotorType.kBrushed` for motors like a CIM. @@ -75,13 +80,13 @@ Now try creating the right motor controllers on your own. - ```java stage1/stage1a/solutions/ctre/src/main/java/first/robot/Robot.java#DriveMotorsRight + ```java {ctreRobot}#DriveMotorsRight ``` - ```java stage1/stage1a/solutions/rev/src/main/java/first/robot/Robot.java#DriveMotorsRight + ```java {revRobot}#DriveMotorsRight ``` @@ -127,13 +132,13 @@ This object stores the configuration so it can be changed and shared across diff - ```java stage1/stage1a/solutions/ctre/src/main/java/first/robot/Robot.java#MotorConfigCreationLeft + ```java {ctreRobot}#MotorConfigCreationLeft ``` - ```java stage1/stage1a/solutions/rev/src/main/java/first/robot/Robot.java#MotorConfigCreationLeft + ```java {revRobot}#MotorConfigCreationLeft ``` @@ -149,13 +154,13 @@ Instead they should be configured with an invert setting of `false` or `Counter_ - ```java stage1/stage1a/solutions/ctre/src/main/java/first/robot/Robot.java#MotorConfigSetLeft + ```java {ctreRobot}#MotorConfigSetLeft ``` - ```java stage1/stage1a/solutions/rev/src/main/java/first/robot/Robot.java#MotorConfigSetLeft + ```java {revRobot}#MotorConfigSetLeft ``` @@ -169,7 +174,7 @@ It's important to remember that settings only get changed when the configuration For CTRE Motor Controllers, becoming a follower is a `ControlRequest` instead of a configuration. - ```java stage1/stage1a/solutions/ctre/src/main/java/first/robot/Robot.java#MotorConfigLeft + ```java {ctreRobot}#MotorConfigLeft ``` @@ -180,7 +185,7 @@ It's important to remember that settings only get changed when the configuration This prevents old configurations from being left on the controller. `PersistMode.kPersistParameters` is used so the configuration gets saved on the motor control so it persists even after power is removed. - ```java stage1/stage1a/solutions/rev/src/main/java/first/robot/Robot.java#MotorConfigLeft + ```java {revRobot}#MotorConfigLeft ``` @@ -195,13 +200,13 @@ Remember that some of the configurations may be different. - ```java stage1/stage1a/solutions/ctre/src/main/java/first/robot/Robot.java#MotorConfig + ```java {ctreRobot}#MotorConfig ``` - ```java stage1/stage1a/solutions/rev/src/main/java/first/robot/Robot.java#MotorConfig + ```java {revRobot}#MotorConfig ``` @@ -226,13 +231,13 @@ An instance of `DifferentialDrive` should be created under where the motor contr - ```java stage1/stage1a/solutions/ctre/src/main/java/first/robot/Robot.java#DrivetrainInstance + ```java {ctreRobot}#DrivetrainInstance ``` - ```java stage1/stage1a/solutions/rev/src/main/java/first/robot/Robot.java#DrivetrainInstance + ```java {revRobot}#DrivetrainInstance ``` @@ -261,13 +266,13 @@ An instance of Systemcore's IMU should be created beneath the `differentialDrive - ```java stage1/stage1a/solutions/ctre/src/main/java/first/robot/Robot.java#IMU + ```java {ctreRobot}#IMU ``` - ```java stage1/stage1a/solutions/rev/src/main/java/first/robot/Robot.java#IMU + ```java {revRobot}#IMU ``` @@ -290,17 +295,17 @@ By now your `Robot` class in `Robot.java` should look like this and VS code shou - ```java stage1/stage1a/solutions/ctre/src/main/java/first/robot/Robot.java#RobotTop + ```java {ctreRobot}#RobotTop ``` - ```java stage1/stage1a/solutions/ctre/src/main/java/first/robot/Robot.java#AllConfigs + ```java {ctreRobot}#AllConfigs ``` - ```java stage1/stage1a/solutions/rev/src/main/java/first/robot/Robot.java#RobotTop + ```java {revRobot}#RobotTop ``` - ```java stage1/stage1a/solutions/rev/src/main/java/first/robot/Robot.java#AllConfigs + ```java {revRobot}#AllConfigs ``` @@ -332,13 +337,13 @@ The index provided in the constructor tells the `NiDsXboxController`which slot t - ```java stage1/stage1a/solutions/ctre/src/main/java/first/robot/opmode/MyTeleop.java#Controller + ```java {ctreTeleop}#Controller ``` - ```java stage1/stage1a/solutions/rev/src/main/java/first/robot/opmode/MyTeleop.java#Controller + ```java {revTeleop}#Controller ``` @@ -358,13 +363,13 @@ This allows the Opmode to access the methods and fields of the`Robot` class. - ```java stage1/stage1a/solutions/ctre/src/main/java/first/robot/opmode/MyTeleop.java#DriveSimPeriodic + ```java {ctreTeleop}#DriveSimPeriodic ``` - ```java stage1/stage1a/solutions/rev/src/main/java/first/robot/opmode/MyTeleop.java#DriveSimPeriodic + ```java {revTeleop}#DriveSimPeriodic ``` @@ -378,13 +383,13 @@ At this point `MyTeleop.java` should look like this - ```java stage1/stage1a/solutions/ctre/src/main/java/first/robot/opmode/MyTeleop.java#FullDrivetrain + ```java {ctreTeleop}#FullDrivetrain ``` - ```java stage1/stage1a/solutions/rev/src/main/java/first/robot/opmode/MyTeleop.java#FullDrivetrain + ```java {revTeleop}#FullDrivetrain ``` diff --git a/src/content/docs/learning-course/stage1/stage1a/simple-auto.mdx b/src/content/docs/learning-course/stage1/stage1a/simple-auto.mdx new file mode 100644 index 00000000..8e22c46d --- /dev/null +++ b/src/content/docs/learning-course/stage1/stage1a/simple-auto.mdx @@ -0,0 +1,84 @@ +--- +title: Simple Auto +description: Programming a time based autonomous +prev: drivetrain-sim +next: kitbot-additional-motors +codeRegionSources: + ctreAuto: stage1/stage1a/solutions/ctre/src/main/java/first/robot/opmode/MyAuto.java + revAuto: stage1/stage1a/solutions/rev/src/main/java/first/robot/opmode/MyAuto.java +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; +import { REV_CTRE_CHOOSER_KEY } from '@data/tabsSyncKeys.ts'; + +# Autonomous OpMode + +Now that the kitbot can move in teleop mode, it is time to make it move during the autonomous mode. +The autonomous mode is typically the first 15 seconds of the match but the exact length may vary from year to year. +An effective auto can be a very valuable addition to a robot for a variety of reasons. +Point values are typically increased during auto and sometimes ranking points associated with completing tasks during auto. +Additionally both game pieces and your robot are in a known position allowing for consistent points. +You also need to coordinate your autonomous routine with your alliance partners so it is important to have multiple routines and the ability to adjust them. + +An autonomous routine is simply an OpMode that gets run during the autonomous portion of the match. +When writing an OpMode that will be run during the autonomous mode, there is an `@Autonomous` annotation that is added above the class definition. +This annotation tells the driverstation to place the OpMode under the autonomous selector. +This OpMode will use a `Timer` to base its behavior off of the time elapsed from the beginning of the autonomous period. +Time-based autos trade off simplicity for reliability, since slight variations in starting configuration could cause your robot to take more or less time to perform different actions + +The code for the auto will be added to the `MyAuto.java` file inside the opmode folder. +The goal of the auto is to drive forward at half speed for four seconds then stop. +The `Timer` class has the `hasElapsed(double seconds)` function which returns true if the specified amount of time has passed. +This function can be periodically checked as the condition to an if statement to stop the robot after four seconds + + + + + ```java {ctreAuto}#SimpleAutoStart + ``` + + + + + ```java {revAuto}#SimpleAutoStart + ``` + + + + + +If `hasElapsed(4)` instead returns false, then less than four seconds must have elapsed so the drivetrain should be told to drive forward at half speed. + + + + + ```java {ctreAuto}#SimpleAutoEnd + ``` + + + + + ```java {revAuto}#SimpleAutoEnd + ``` + + + + + +# Running Your Auto + +To test the auto routine, start the simulation, and connect Advantage Scope. +Then, select autonomous mode and `MyAuto` OpMode in the Sim GUI. +Now when the robot is enabled the auto should run. + + + +# Practice + +Try adding on to this auto yourself. +For example, the robot could drive forward at half speed for four seconds, turn counter clockwise for two seconds, then drive forward at full speed for three seconds. +You could also try creating additional autonomous OpModes so you can select between the different autos you have created.