diff --git a/examples/stage1/stage1b/snippets/src/main/java/sources/CommandBasedKitbot.java b/examples/stage1/stage1b/snippets/src/main/java/sources/CommandBasedKitbot.java
index f98703d0..196a2c4f 100644
--- a/examples/stage1/stage1b/snippets/src/main/java/sources/CommandBasedKitbot.java
+++ b/examples/stage1/stage1b/snippets/src/main/java/sources/CommandBasedKitbot.java
@@ -45,9 +45,9 @@ public MyTeleop(Robot robot) {
private final ExampleMotor motor = new ExampleMotor();
// [feederSim]
- private final SingleFlywheelSim sim = new SingleFlywheelSim(motor, "Feeder");
+ private final SingleFlywheelSim sim = new SingleFlywheelSim(motor, "Feeder"); // Create a flywheel simulation
- public void periodic() {
+ public void periodic() { // Update the simulation
sim.periodic();
}
// [/feederSim]
diff --git a/src/content/docs/learning-course/stage1/stage1b/command-based-kitbot-pt2.mdx b/src/content/docs/learning-course/stage1/stage1b/command-based-kitbot-pt2.mdx
index 9ee6afc3..f8eedf95 100644
--- a/src/content/docs/learning-course/stage1/stage1b/command-based-kitbot-pt2.mdx
+++ b/src/content/docs/learning-course/stage1/stage1b/command-based-kitbot-pt2.mdx
@@ -13,7 +13,7 @@ import Aside from '@components/Aside.astro';
In this second part of the kitbot rewrite, you will:
-1. Create a `Drivetrain` mechanism class.
+1. Create a `Drivetrain` mechanism class to allow for control of the drivetrain.
2. Define an `arcadeDrive` command that dynamically reads controller inputs using `DoubleSupplier`s.
3. Bind the default drivetrain command in your teleop OpMode to enable driving.
4. Define some basic autonomous modes.
@@ -68,6 +68,8 @@ To do that, write the following:
### Task 3: Using the Drivetrain
+Now that we have a `Drivetrain` class, we need to set it up to be used in our robot code.
+
1. Create a `Drivetrain` instance in `Robot.java` named `drivetrain`.
It should be a public instead of private.
2. Call `drivetrain.periodic();` in the `robotPeriodic` method.
@@ -101,7 +103,9 @@ To do that, write the following:
### Task 4: Create Auto Mode Files
-Create 2 java files in the `opmode` package, named `DriveStraightAutoMode.java` and `TurnInPlaceAutoMode.java`,
+We need to create two new files to define our autonomous OpModes.
+
+Create 2 Java files in the `opmode` package, named `DriveStraightAutoMode.java` and `TurnInPlaceAutoMode.java`,
before deleting the `MyAuto.java` file.
Copy-paste the following code in each file,
while replacing `MyOpModeName` with the correct name for each opmode:
@@ -112,6 +116,8 @@ while replacing `MyOpModeName` with the correct name for each opmode:
### Task 5: Drive Straight Autonomous
+This auto will drive the robot straight forwards for 4 seconds.
+
In the `start()` method of `DriveStraightAutoMode.java`, schedule
an `arcadeDrive` command with a timeout of 4 seconds.
Then, do the following:
@@ -143,6 +149,8 @@ Then, do the following:
### Task 6: Rotate in Place Command
+This command will rotate the robot a certain number of degrees.
+
Create a new `Command` in `Drivetrain.java`, called `rotateInPlace`,
with the parameters `double angleDegrees` and `DoubleSupplier rotationThrottle`.
It should execute these actions, in order:
diff --git a/src/content/docs/learning-course/stage1/stage1b/command-based-kitbot.mdx b/src/content/docs/learning-course/stage1/stage1b/command-based-kitbot.mdx
index c7a52718..db832232 100644
--- a/src/content/docs/learning-course/stage1/stage1b/command-based-kitbot.mdx
+++ b/src/content/docs/learning-course/stage1/stage1b/command-based-kitbot.mdx
@@ -56,52 +56,90 @@ the robot class' `robotPeriodic()` method.
```
+
+ What does `Scheduler.getDefault().run()` do?
+ The command scheduler is in charge of running all the commands that are
+ active, and handling any mechanism requirements that those commands may
+ have. Calling this method runs the scheduler, and therefore all active
+ commands, for one iteration.
+
+
### Task 2: The Feeder Mechanism
Create a new package named `mechanisms` under the `robot` package.
-Remember that
-packages are folders that contain java files.
-The `mechanisms` package
-will contain the code for our feeder and intake launcher mechanisms.
-
-Then, create a new file in the `mechanisms` package named `Feeder.java`.
-Define a class named `Feeder` that implements `Mechanism`, then add the following:
+Remember that packages are folders that contain java files.
+The `mechanisms` package will contain the code for our feeder and intake launcher mechanisms.
-1. A private `TalonFX` or `SparkMax` motor controller object, named `motor`, with an ID of 5.
- It is connected to a systemcore CANBus with ID 0.
-2. A `feed()` command that sets the throttle of the motor to 0.75 forever.
-3. An `intake()` command that sets the throttle of the motor to -1 forever.
-4. An `outtake()` command that sets the throttle of the motor to 1 forever.
-5. An `idle()` command that sets the throttle of the motor to 0 forever.
- Make this the default command.
-
-The `feed()`, `intake()`, `outtake()` and `idle()` commands should be returned from methods.
+Then, create a new Java class in the `mechanisms` package named `Feeder.java`, which will be used to control the feeder.
+The `Feeder` class should implement `Mechanism`.
- Item 1, Hint 1
+ Hint
A mechanism is defined as a class with the `implements Mechanism` keyword at the end.
```java #feederDef
```
-
- Item 1, Hint 2 (CTRE only)
- For CTRE devices, a `CANBus` object can be created via `CANBus.systemcore(id)`.
-
-{/* prettier-ignore */}
-
- Item 1, Hint 3
- Remember that `TalonFX` and `SparkMax` are classes, and that creating objects within another
- class is done like so:
- {/* rli:ignore */}
- ```java
- private TypeOfClass myMotor = new TypeOfClass();
- ```
- First, figure out what to replace `TypeOfClass` with. Next,
- add the appropriate constructor parameters by hovering over
- the red squiggly line.
-
+
+Then, add the following:
+
+
+
+ 1. A private `TalonFX` motor controller object, named `motor`, with CAN ID 5 on Systemcore CANBus 0.
+ 2. A `feed()` command that sets the throttle of the motor to 0.75 forever.
+ 3. An `intake()` command that sets the throttle of the motor to -1 forever.
+ 4. An `outtake()` command that sets the throttle of the motor to 1 forever.
+ 5. An `idle()` command that sets the throttle of the motor to 0 forever.
+ Make this the default command.
+
+ The `feed()`, `intake()`, `outtake()` and `idle()` commands should be returned from methods.
+
+
+ Item 1, Hint 1
+ For CTRE devices, a `CANBus` object can be created via
+ `CANBus.systemcore(id)`.
+
+ {/* prettier-ignore */}
+
+ Item 1, Hint 2
+ Remember that `TalonFX` is a class, and that creating objects within another
+ class is done like so:
+ {/* rli:ignore */}
+ ```java
+ private TypeOfClass myMotor = new TypeOfClass();
+ ```
+ First, figure out what to replace `TypeOfClass` with. Next,
+ add the appropriate constructor parameters by hovering over
+ the red squiggly line.
+
+
+
+ 1. A private `SparkMax` motor controller object, named `motor`, with CAN ID 5 on Systemcore CANBus 0.
+ 2. A `feed()` command that sets the throttle of the motor to 0.75 forever.
+ 3. An `intake()` command that sets the throttle of the motor to -1 forever.
+ 4. An `outtake()` command that sets the throttle of the motor to 1 forever.
+ 5. An `idle()` command that sets the throttle of the motor to 0 forever.
+ Make this the default command.
+
+ The `feed()`, `intake()`, `outtake()` and `idle()` commands should be returned from methods.
+
+
+ Item 1 Hint
+ Remember that `SparkMax` is a class, and that creating objects within another
+ class is done like so:
+ {/* rli:ignore */}
+ ```java
+ private TypeOfClass myMotor = new TypeOfClass();
+ ```
+ First, figure out what to replace `TypeOfClass` with. Next,
+ add the appropriate constructor parameters by hovering over
+ the red squiggly line.
+
+
+
+
+
Items 2-4, Hint 1
Re-read the "Defining Commands" and "Combining Commands and Mechanisms"
@@ -121,22 +159,40 @@ to allow for simulation to work:
```
+This code creates a `SingleFlywheelSim` object named `sim` that simulates the feeder by representing it as a single spinning flywheel, then updates the simulation in `sim.periodic()`.
+
### Task 3: The IntakeLauncher Mechanism
Create a file named `IntakeLauncher.java` in the `mechanisms` package.
Define a class named `IntakeLauncher` that implements `Mechanism`; then, add the following:
-1. A private `TalonFX` or `SparkMax` motor controller object, named `motor`, with an ID of 4.
- It is connected to a systemcore CANBus with ID 0.
-2. A `shoot()` command that waits 2 seconds, then sets the throttle of the motor to 0.9 forever.
-3. A `intake()` command that sets throttle to 0.8 forever.
-4. A `outtake()` command that sets throttle to -0.8 forever.
-5. A `idle()` command that sets throttle to 0 forever.
- Make this the default command.
-6. The code needed for simulating the intake launcher.
- You haven't officially learned
- how to do this, but task 2's final section gives a hint.
- Can you figure it out?
+
+
+ 1. A private `TalonFX` motor controller object, named `motor`, with ID 4
+ on Systemcore bus 0.
+
+
+ 1. A private `SparkMax` motor controller object, named `motor`, with ID
+ 4 on Systemcore bus 0.
+
+
+
+ -
+ A `shoot()` command that waits 2 seconds, then sets the throttle of the
+ motor to 0.9 forever.
+
+ - A `intake()` command that sets throttle to 0.8 forever.
+ - A `outtake()` command that sets throttle to -0.8 forever.
+ -
+ A `idle()` command that sets throttle to 0 forever. Make this the
+ default command.
+
+ -
+ The code needed for simulating the intake launcher. You haven't
+ officially learned how to do this, but task 2's final section gives a
+ hint. Can you figure it out?
+
+
Item 2 Hint
@@ -148,15 +204,16 @@ Define a class named `IntakeLauncher` that implements `Mechanism`; then, add the
```java #feederSim
```
- Change one thing, and copy-paste the code into `IntakeLauncher.java`.
+ Copy-paste the code into `IntakeLauncher.java`, and change one thing.
### Task 4: Finish the `Robot` class
-Create new instances of the `IntakeLauncher` and `Feeder` classes.
-They should be
-public properties of the `Robot` class, so that they are accessible from opmodes.
+Now that we have the mechanism classes created, we need to instantiate them in the `Robot` class.
+
+Go to the `Robot` class and create new instances of the `IntakeLauncher` and `Feeder` classes.
+They should be public properties of the `Robot` class, so that they are accessible from OpModes.
Name them `intakeLauncher` and `feeder`, respectively.
You also need to call `intakeLauncher.periodic();` and `feeder.periodic();`
@@ -170,10 +227,10 @@ Which method should it be?
### Task 5: Finish the teleop OpMode
-In the constructor of the teleop opmode (it should be in `MyTeleop.java`),
+In the constructor of the teleop OpMode (it should be in `MyTeleop.java`),
create a private `CommandXboxController` instance named `xbox`.
-In your opmode constructor, define the following behavior:
+In your OpMode constructor, define the following behavior:
1. While the `xbox.leftBumper()` trigger is active,
run the `robot.intakeLauncher.intake()` and `robot.feeder.intake()` commands.
diff --git a/src/content/docs/learning-course/stage1/stage1b/spot-the-error.mdx b/src/content/docs/learning-course/stage1/stage1b/spot-the-error.mdx
index abc4eb6f..9ecfc247 100644
--- a/src/content/docs/learning-course/stage1/stage1b/spot-the-error.mdx
+++ b/src/content/docs/learning-course/stage1/stage1b/spot-the-error.mdx
@@ -70,6 +70,9 @@ Can you spot the error?
### Exercise 3
+This fails to compile, with the error shown in the comment.
+It also has a logic error.
+
{/* rli:ignore */}
```java