180 lesson: one OpMode a driver could take to a match

../_images/fig-l180-aiming.png

One teleop with all of it in. The sticks drive field relative and hold the heading they were left at. The right bumper means the robot’s own directions. A points the robot at 45 degrees while the driver drives. Y sends the robot to its spot until a stick moves. And your own localizer from L120 runs beside the robot’s.

Before you start.

  • L170 is done, and so is L120, whose L120EncoderLocalizer this runs.

  • AdvantageScope is installed on the same laptop. No gamepad is needed until the last step.

  • The robot, the Driver Station, a gamepad, and about 3 m by 3 m of clear floor for the last step.

the steps

L180S010: copy the starter into mytry

Copy. In lessons, click L180CombinedOpMode once and copy it. Click mytry once and paste. In the Copy Class box, click OK. If Android Studio asks whether to add the file to Git, click Add.

Check.

  • mytry holds L180CombinedOpMode, and the new file is open.

L180S020: switch your copy on

Change. Delete the line @Disabled, under the comment that names this step.

Check.

  • Under the step’s comment, the next line reads // 'public' so the robot can run this OpMode. 'public' allows access from any code.

L180S030: run your localizer again

Change. Find shadowLocalizers() and the comment that names this step. Under it, type the same two lines as in L120:

        // When on L180S030, see
        // https://msb-stitt.github.io/ftc31459-26-27-biobuzz/guide/tasks/l180.html#l180s030
        // for what to do here.
        shadowLocalizers.add("driveWheelEncoders",
                new L120EncoderLocalizer(new HardwareWheelSource(hardware)));

HardwareWheelSource turns red. Click it and press Option+Enter, as in L120. L120EncoderLocalizer does not turn red. It is your own, from L120, and it sits in mytry too.

Keep the name driveWheelEncoders. AdvantageScope shows each localizer under its name, so a run of this OpMode and a run of L120 line up.

Check.

  • Nothing in the file is red.

L180S040: read what you are about to drive

Nothing else in the starter is new. Read loop(), driveFromTheSticks() and the methods of the drive to the target, and find the lesson each part came from.

  • Both drive sticks go through deadband and then squared, from L060.

  • forward and strafe are turned through the heading so they mean the field, from L140.

  • The right bumper picks the robot’s own directions, from L150.

  • hold.turn keeps the heading the turn stick was left at, from L160.

  • Y schedules the drive to target, and any stick takes it back, from L170.

A is the one part that is new here, and it is HeadingHold again. A press of A schedules aimAtFortyFive, a command that runs aimAtFortyFiveDegrees() once. It cancels any drive to the target, and hold.aimAt gives the hold a heading the driver did not leave, 45 degrees. The hold turns the robot there, and the left stick still drives. Push the turn stick and the driver has the turn back.

When a stick takes the robot back from Y, hold.release() in giveTheDriverTheWheels() forgets the heading the hold had before Y. Read the code without it: the hold would turn the robot back to that old heading.

Simulator. In the Terminal, run this. It holds A and pushes the left stick a little forward:

./gradlew :TeamCode:simRun --args="mytry.L180CombinedOpMode --a=true --left_stick_y=-0.3"

AdvantageScope. Connect to the simulator as in L020, and click 2D Field. Open the heading folder. Then open Localizer and both folders in it.

Check.

  • target_deg reads 45.

  • The robot turns until its arrow points up and to the right, and pinPoint/heading_deg comes to about 45.

  • All the while it drives to the right, and pinPoint/x_in climbs.

  • driveWheelEncoders is there, and it follows pinPoint: the same heading, and x and y within a tenth of an inch.

L180S050: drive all four

Robot. Stop the simulator. Send the code, and run L180 Combined from the Driver Station.

Check.

  • Try them in this order: field relative, the bumper held, A, and Y.

  • Each one does what its own lesson did, and switching between them needs nothing but a thumb.

  • On the robot, driveWheelEncoders follows pinPoint as the robot drives.

No gamepad. The run above needs none. With --pad, a driver can try all four in turn.

If it didn’t, and LessonsTest.l180_everythingTogether fails with the shadow localizer is still running, nothing was published under Localizer/driveWheelEncoders/. The two lines are missing, or the name is spelled differently. With the name typed as encoders, this was the message, and the other two tests passed.

If it didn’t, and one of the four misbehaves on its own, go back to that lesson’s page. This page adds no arithmetic, so a fault here is a fault there.

The other two tests, l180_aPointsAt45DegreesWhileTheDriverKeepsDriving and l180_theTurnStickTakesAimingBack, check the given A code. They pass on the starter.

What you just did. You wrote two lines and got a competition teleop. Every part lives in one place, so putting them together is choosing an order rather than writing code.

The order is the design. The driver’s turn stick beats A’s aim, and A’s aim takes the place of the held heading. The follower drives only when nobody else has asked. The driver beats everything, and the robot fills in what the driver leaves.

Where next. L190 stops asking the wheels for power and starts asking them for a speed.