Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Comment thread
TheComputer314 marked this conversation as resolved.
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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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`,
Comment thread
TheComputer314 marked this conversation as resolved.
before deleting the `MyAuto.java` file.
Copy-paste the following code in each file,
while replacing `MyOpModeName` with the correct name for each opmode:
Expand All @@ -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:
Expand Down Expand Up @@ -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:
Expand Down
159 changes: 108 additions & 51 deletions src/content/docs/learning-course/stage1/stage1b/command-based-kitbot.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -56,52 +56,90 @@ the robot class' `robotPeriodic()` method.

```

<details class="accordion">
<summary>What does `Scheduler.getDefault().run()` do?</summary>
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.
</details>

### 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`.

<details class="accordion">
<summary>Item 1, Hint 1</summary>
<summary>Hint</summary>
A mechanism is defined as a class with the `implements Mechanism` keyword at the end.
```java #feederDef

```

</details>
<details class="accordion">
<summary>Item 1, Hint 2 (CTRE only)</summary>
For CTRE devices, a `CANBus` object can be created via `CANBus.systemcore(id)`.
</details>
{/* prettier-ignore */}
<details class="accordion">
<summary>Item 1, Hint 3</summary>
Remember that `TalonFX` and `SparkMax` are classes, and that creating objects within another
class is done like so: <br />
{/* 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.
</details>

Then, add the following:

<Tabs syncKey={REV_CTRE_CHOOSER_KEY}>
<TabItem label="CTRE">
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.

<details class="accordion">
<summary>Item 1, Hint 1</summary>
For CTRE devices, a `CANBus` object can be created via
`CANBus.systemcore(id)`.
</details>
{/* prettier-ignore */}
<details class="accordion">
<summary>Item 1, Hint 2</summary>
Remember that `TalonFX` is a class, and that creating objects within another
class is done like so: <br />
{/* 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.
</details>
</TabItem>
<TabItem label="REV">
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.

<details class="accordion">
<summary>Item 1 Hint</summary>
Remember that `SparkMax` is a class, and that creating objects within another
class is done like so: <br />
{/* 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.
</details>
</TabItem>

</Tabs>

<details class="accordion">
<summary>Items 2-4, Hint 1</summary>
Re-read the "Defining Commands" and "Combining Commands and Mechanisms"
Expand All @@ -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?
<Tabs syncKey={REV_CTRE_CHOOSER_KEY}>
<TabItem label="CTRE">
1. A private `TalonFX` motor controller object, named `motor`, with ID 4
on Systemcore bus 0.
</TabItem>
<TabItem label="REV">
1. A private `SparkMax` motor controller object, named `motor`, with ID
4 on Systemcore bus 0.
</TabItem>
</Tabs>
<ol>
<li value={2}>
A `shoot()` command that waits 2 seconds, then sets the throttle of the
motor to 0.9 forever.
</li>
<li>A `intake()` command that sets throttle to 0.8 forever.</li>
<li>A `outtake()` command that sets throttle to -0.8 forever.</li>
<li>
A `idle()` command that sets throttle to 0 forever. Make this the
default command.
</li>
<li>
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?
</li>
</ol>

<details class="accordion">
<summary>Item 2 Hint</summary>
Expand All @@ -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.

</details>

### 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();`
Expand All @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down