Remote Programming...Again

The students have gotten further then I ever have but they are stuck. If the hit the L Up button it runs the program, however, if something goes wrong it will not allow them to take control until the second bump sensor is hit. Attached is a picture of what they tried to do so that if they hit L Down it would stop all motors and allow driving, however, with this configuration L Down still does nothing (it just keeps trying to run the L Up program).

Thoughts on how I can guide them?



Code looks promising. Your students are definitely thinking! Maybe this will clarify things for you:

If their goal is to have L Down override L Up, then it must be the “parent” and L Up the “child.” This is done with nested if statements.

If L Down
…<code 1>
…If L Up
…<code 2>

In this configuration, with the L Up code as a subset of the L Down code, the program will check L Down first. In other words, the L Up code can only run if L Down is not being pressed. If the order of these two if statements is reversed, or if they are separate blocks of code (and therefore equal), each command will finish executing before checking the other input.

You might show them the brief example above (without the added periods) and ask them to explain to you how the if/else logic works. Which code will the program carry out and when?


It is quite hard to write a good assisted-teleop program in graphical. Mainly because the lack of parallelism and compound conditions. At least the graphical has variables, which makes it doable, if clumsy. I’ll use schematic pseudocode below.

Let’s call the complex autonomous part “a macro”
As the OP correctly observes, the problem is with anything blocking inside the macro. But since the macro needs to perform a sequence of operations, it is bound to block when structured this way. Besides explicit waitUntil blocks, you also have 2x 0.6s moveMotor. This is to say, while the block of code under “if (LUp)” is running, the main control loop is suspended, noone evaluates the joysticks, noone checks the LDown button before the macro finishes. If the drivebase was running at the time LUp was pressed, it would just keep running.

With compound conditions, you could at least fix the waitUntil blocks, such as waitUntil ( originalCondition || LDown ) {…}.
The best (IMHO) solution in current graphical would be to use a state variable (step counter) with purely non-blocking functions. I have never really used variables in graphical much, so I hope your students would be able to replicate the outline below:

[Variable counter = 0]

if (counter == 0) {
   if (getJoystickValue(BtnLUp) == 1) {
     counter  = 1;
     setMotor(middleDrive, -45);
   } else {
     if (getJoystickValue(BtnLDOwn) == 1) {
       counter = 0;
} else if (counter == 1) {
   if (Bump) {
     counter = 2;
     // instead of moveMotor, advance state and use timer
     setMotor(middleDrive, 75)
} else if (counter == 2) {
  if (getTimer(T3) > 300) { // milliseconds?
     setMultipleMotors(75, right, left);
     counter = 3;
} else if (counter == 3) {
   if (bumpFront) {
   stopMultipleMotors(right, left);
   setMultipleMotors(75, arm...)
   counter = 4;
} ...

If they can understand it, they can actually implement it properly.
One thing that is missing above is skipping all armControl and the likes while the macro is running (counter != 0) as that would reset any ongoing parallel motor operation.

In text-based, everything is so much easier, since you have tasks - LUp would start a parallel task that would just perform the sequence, while RUp would just kill that task and stop motors.