# 020 lesson: read the sticks :::{figure} ../_static/figures/fig-l020-live.png :name: fig-l020-live ::: Push the gamepad's sticks and watch the numbers they send, live on the laptop. Nothing on the robot moves yet. A video shows every step of this lesson: {video}`l020`. ::::{only} mentor **Before you start.** - [B010](b010.md) is done: Android Studio has the project open. - [H017](h017.md) is done: the student can open, close and resize Android Studio's panes. - AdvantageScope is installed on the same laptop. - A gamepad is plugged into the laptop. - No robot is needed. The student writes in one folder, `mytry`, inside `TeamCode/java/org.firstinspires.ftc.teamcode`. It holds no lesson until step L020S010 copies a starter into it. The `lessons` folder beside it holds the starting files. :::: ## the steps ### L020S010: copy the starter into mytry The `lessons` folder holds the starters: the file each lesson begins from. You copy one into your own folder, `mytry`, and change the copy. **Copy.** {.steps} - Open `TeamCode/java/org.firstinspires.ftc.teamcode/lessons`. - Click `L020SticksOpMode` once, and copy it: ⌘C on a Mac, Ctrl+C on Windows. - Click the `mytry` folder once, and paste. - A box called **Copy Class** opens with **Destination package** already ending in `mytry`. Click **OK**. - If Android Studio asks whether to add the file to Git, click **Add**. :::{figure} ../_static/figures/fig-l020-copy-class.png :name: fig-l020-copy-class ::: **Check.** - `mytry` holds `L020SticksOpMode`, the file is open, and its first line reads `package org.firstinspires.ftc.teamcode.mytry;`. :::{figure} ../_static/figures/fig-l020-copied.png :name: fig-l020-copied ::: ::::{only} mentor **If it didn't**, and the copy landed in `lessons` beside the starter, `lessons` was the folder clicked before pasting, so Destination package ended in `lessons`. Delete the copy, click `mytry`, and paste again. :::: ### L020S020: switch your copy on **Change.** Find the line `@Disabled`, just under the comment that names this step. Click on it and delete the whole line: ⌘Delete on a Mac, Ctrl+Y on Windows and Ubuntu. The first time on Windows, Android Studio asks whether Ctrl+Y should Redo or Delete Line: click **Delete Line**. `@Disabled` hides an OpMode from the robot's list. The starter in `lessons` keeps it, so the robot only ever lists your copy. **Check.** - Under the step's comment, the next lines read `// 'public' so the robot can run this OpMode. 'public' allows access from any code.` and `public class L020SticksOpMode`. ### L020S030: read the left stick The file is an **OpMode**: one program the robot can run. Pressing INIT runs its `init()` once. Pressing PLAY runs its `start()` once, and `start()` hands `readTheSticks()` to the **scheduler**. From then until STOP, the scheduler runs `readTheSticks()` over and over, many times a second. The simulator presses all three for you. **Change.** {.steps} - Scroll down to `readTheSticks()` and find the comment that names this step. - Click at the end of its last line and press Enter. Type this much: ```java double leftStickY = gamepad1. ``` - A list opens with everything a gamepad has. Type `left_st` and the list shrinks to the left stick. - `left_stick_y` is already highlighted. Press Tab. If it isn't, move the highlight to it with the arrow keys first. - Type `;` to end the line. :::{figure} ../_static/figures/fig-l020-complete.png :name: fig-l020-complete ::: ```{code-block} java :emphasize-lines: 4 // When on L020S030, see // https://msb-stitt.github.io/ftc31459-26-27-biobuzz/guide/tasks/l020.html#l020s030 // for what to do here. double leftStickY = gamepad1.left_stick_y; ``` `double` is Java's word for a number with a decimal point, like 0.5 or -1.0. `leftStickY` is a name you chose for one. The list said `float`, which is a smaller kind of decimal number. A `double` holds any `float`. Now hold the pointer still over `left_stick_y`. A box opens and says what it is: *left analog stick vertical axis*. You can do this with any name you are not sure about. :::{figure} ../_static/figures/fig-l020-hover.png :name: fig-l020-hover ::: **Check.** - The line has no red underline. ::::{only} mentor **If it didn't**, and the line reads `left_stick_x`, the highlight was on the wrong name when Tab was pressed. Change the letter by hand. :::: ### L020S040: write the left stick down **Change.** Under the comment that names this step, type `Track`. The list shows more than one `Tracker`. Pick the one from `org.firstinspires.ftc.teamcode.base` and press Tab. Then finish the line: ```{code-block} java :emphasize-lines: 4 // When on L020S040, see // https://msb-stitt.github.io/ftc31459-26-27-biobuzz/guide/tasks/l020.html#l020s040 // for what to do here. Tracker.publish("stick/leftY", leftStickY); ``` :::{figure} ../_static/figures/fig-l020-tracker.png :name: fig-l020-tracker ::: `Tracker.publish` takes a name and a value. It sends both to AdvantageScope while the code runs, and writes them in the flight log. Android Studio added an `import` line for `Tracker` near the top of the file. **Check.** - `Tracker` is not red, and there is an `import org.firstinspires.ftc.teamcode.base.Tracker;` line near the top. The simulator is a robot that exists only in the laptop. It runs your OpMode just as the real robot would. **Simulator.** Click the **Terminal** button near the bottom of the left edge. Type this and press Enter: ``` ./gradlew :TeamCode:simRun --args="mytry.L020SticksOpMode --pad" ``` **Check.** - It lists any connected gamepads. - Then it prints `Flight log:` and a folder, then `mytry.L020SticksOpMode running.`, and stays running. - The folder is the project's top folder, the one that holds `README.md`. If more than one gamepad is plugged in, hold Start and press A on yours, so it becomes `gamepad1`. AdvantageScope draws the numbers your code publishes, as they change. **AdvantageScope.** {.steps} - Open AdvantageScope. It is an app of its own, not a part of Android Studio. - Open **File > Connect to Simulator > NetworkTables 4**. The item marked **Default** works the same. Then click **Line Graph**. - Type `stick` in the search box at the top left, and click `NT:/stick/leftY`. - Drag `leftY` from the `stick` folder down into **Left Axis**. Before you push the stick, guess. When you push the left stick all the way away from you, will the line go to 1.0 or to -1.0? Now push it and see! **Check.** - The line moves when you push. - All the way forward it reads -1.0, and all the way back it reads 1.0. Forward is -1.0 on gamepads. That is how most gamepads are made, not a mistake in your code. :::{figure} ../_static/figures/fig-gamepad-sticks.png :name: fig-gamepad-sticks ::: ::::{only} mentor The list in AdvantageScope has two `stick` folders. The one inside `sim` is the gamepad as the simulator read it; the one on its own is what the student's code published. In L020 they read the same, because the code passes the stick on unchanged. :::{figure} ../_static/figures/fig-advantagescope-sim.png :name: fig-advantagescope-sim ::: The simulator also sends where the robot is and the four wheel powers, as above. They stay still in L020, since nothing drives the wheels. :::: ### L020S050: the right stick too **Change.** Click in the Terminal and press Ctrl+C to stop the simulator. That is Ctrl+C on a Mac too, not ⌘C. Under the comment that names this step, read and write down the right stick the same way: ```{code-block} java :emphasize-lines: 4-5 // When on L020S050, see // https://msb-stitt.github.io/ftc31459-26-27-biobuzz/guide/tasks/l020.html#l020s050 // for what to do here. double rightStickY = gamepad1.right_stick_y; Tracker.publish("stick/rightY", rightStickY); ``` **Simulator.** Run the same command again. **AdvantageScope.** Drag `rightY` from the `stick` folder into **Left Axis** beside `leftY`. **Check.** - Each line follows its own stick. - Push each stick all the way both ways. The numbers never go past 1.0 or below -1.0, and forward is -1.0 on both. **Log.** {.steps} - Press Ctrl+C in the Terminal to stop the simulator. - In AdvantageScope, open **File > Open Log(s)…**. Go to the project's top folder, and click **Date Modified** so the newest file is on top. Open the top file whose name starts `L020SticksOpMode`. - Drag `leftY` and `rightY` from `stick` into **Left Axis**. :::{figure} ../_static/figures/fig-l020-log.png :name: fig-l020-log ::: **Check.** - The lines show what the sticks did during the run. - It is the same `stick/leftY` and `stick/rightY` you watched live, kept in a file you can open again later. **What's happening.** [E021](e021.md) shows what your two lines do inside the computer. ::::{only} mentor **What you just did.** `readTheSticks` runs over and over, from PLAY until STOP, and each pass is one look at the gamepad. The code read both sticks into `double`s and wrote each one down under a name. AdvantageScope showed the values live, and the flight log kept them to look at after the run. **The scheduler.** `start()` makes `readTheSticks` into a command that never finishes, with `Commands.infinite`, and schedules it. The scheduler runs every scheduled command once a loop, inside `loopAfter()`. Every lesson's code runs this way; L170 is the first to schedule a second command, on a button. **The stick's axes.** A stick reads from -1.0 to +1.0 on each axis. +x is pushed to the driver's right, and +y is pulled back toward the driver, so forward on the stick is -y. From L030 on, a stick asks the robot for a velocity: the farther the push, the faster. **Pedro's axes.** Pedro Pathing measures the robot along its own axes: +x is forward, out the nose, +y is to the robot's left, and a counter-clockwise turn, seen from above, is positive. `follower.twist()` gives the velocity on these axes: `vx` forward, `vy` left, `omega` counter-clockwise. :::{figure} ../_static/figures/fig-stick-to-robot.png :name: fig-stick-to-robot ::: On the field, Pedro puts (0, 0) in a corner, with x and y each running 0 in to 144 in. Heading 0 points along the field's +x and π/2, 90°, along its +y; the code keeps it in radians. `follower.velocity()` gives the velocity along the field's x and y. Pedro's [Coordinates](https://pedropathing.com/docs/pathing/reference/coordinates) page draws its field. :::{figure} ../_static/figures/fig-pedro-field.png :name: fig-pedro-field ::: **Field-relative driving.** The red drive team stands at the field's left edge, x = 0 in, and the blue drive team at its right edge, x = 144 in. In field-relative driving, a red driver wants a push away on the left stick, the stick's -y, to drive the robot along the field's +x. A blue driver wants the same push to drive it along the field's -x. L140's push away drives along +x, as the red driver wants. **Turning a stick into a velocity changes axes.** Forward is `-left_stick_y`, a slide to the left is `-left_stick_x`, and a counter-clockwise turn is `-right_stick_x`. The stick's axes are a mirror image of the robot's, so no turn of the gamepad lines them up, and each needs its minus sign. L030 makes the first, `-leftStickY`; L080 adds the turn and L090 the slide. L140 adds a second change, from the field's axes to the robot's. **Where next.** [L030](l030.md) turns each stick into a speed, where forward is positive. ::::