Is there a way to delay or temporarily disable distance sensors?

I am currently writing out a code for a 3rd party competition, it is a full autonomous game therefore i need multiple sensors to map out a route and if the robot surpasses a limit it will back up and avoid that section to its best ability. However i am having some issues trying to find a command that can “disable” other distance sensors while a sensor is detecting a object that is closer than all other sensor or is that a non-existent command.

Btw the claws don’t serve a purpose yet, they are there as a placeholder for when we plan to use them

Ports:

Drivetrain - Port 7, 1
Claw1 - Claw #1 - Port 2
Claw2 - Claw #2 - Port 3
Distance1_DSR - Distance #1 Down Side Right - Port 4
Distance2_DSL - Distance #2 Down Side Left - Port 5
Distance3_DF - Distance #3 Down Front - Port 6
Distance4_DR - Distance #4 Down Rear - Port 8
Distance5_OSR - Distance #5 Outwards Side Right - Port 9
Distance6_OSL - Distance #6 Outwards Side Left - Port 10
Distance7_OF - Distance #7 Outwards Front - Port 11
Distance8_OR - Distance #8 Outwards Rear - Port 12

Code:

[Comp C1 B1.iqblocks|attachment](upload://qRylFMpXZBOQxJBvaH1Y4GwC1rT.iqblocks) (23.4 KwB)


float myVariable, FKJ;

float FK[4];

event O2P9 = event();
event D1P1 = event();
event opui = event();
event bvnb = event();

// "when started" hat block
int whenStarted1() {
  Drivetrain.setDriveVelocity(100.0, percent);
  Drivetrain.setTurnVelocity(100.0, percent);
  while (true) {
    if (Distance3_OS.objectDistance(inches) <= 30.0) {
      while (Distance3_OS.isObjectDetected()) {
        O2P9.broadcast();
      wait(20, msec);
      }
    }
    if (Distance4_OSL.objectDistance(inches) <= 30.0) {
      while (Distance4_OSL.isObjectDetected()) {
        D1P1.broadcast();
      wait(20, msec);
      }
    }
    if (Distance7_OF.objectDistance(inches) <= 30.0) {
      while (Distance7_OF.isObjectDetected()) {
        opui.broadcast();
      wait(20, msec);
      }
    }
    if (Distance8_OB.objectDistance(inches) <= 30.0) {
      while (Distance8_OB.isObjectDetected()) {
        bvnb.broadcast();
      wait(20, msec);
      }
    }
  wait(20, msec);
  }
  return 0;
}

// "when started" hat block
int whenStarted2() {
  while (true) {
    if (Distance1_DS.objectDistance(mm) <= 1.0) {
      Drivetrain.stop();
      Drivetrain.drive(reverse);
    }
  wait(20, msec);
  }
  return 0;
}

// "when started" hat block
int whenStarted3() {
  while (true) {
    if (Distance2_DSL.objectDistance(mm) <= 1.0) {
      Drivetrain.stop();
      Drivetrain.drive(forward);
    }
  wait(20, msec);
  }
  return 0;
}

// "when started" hat block
int whenStarted4() {
  while (true) {
    if (Distance9_DF.objectDistance(mm) <= 1.0) {
      Drivetrain.stop();
      Drivetrain.turnFor(right, 180.0, degrees, true);
      Drivetrain.drive(reverse);
    }
  wait(20, msec);
  }
  return 0;
}

// "when started" hat block
int whenStarted5() {
  while (true) {
    if (Distance11_DB.objectDistance(mm) <= 1.0) {
      Drivetrain.stop();
      Drivetrain.turnFor(left, 180.0, degrees, true);
      Drivetrain.drive(reverse);
    }
  wait(20, msec);
  }
  return 0;
}

// "when I receive O2P9" hat block
void onevent_O2P9_0() {
  while (true) {
    if (Distance3_OS.objectDistance(inches) > Distance7_OF.objectDistance(inches) > Distance4_OSL.objectDistance(inches)) {
      if (Distance3_OS.objectDistance(inches) > Distance8_OB.objectDistance(inches)) {
        Drivetrain.driveFor(forward, Distance2_DSL.objectDistance(inches), inches, true);
      }
    }
  wait(20, msec);
  }
}

// "when I receive D1P1" hat block
void onevent_D1P1_0() {
  while (true) {
    if (Distance4_OSL.objectDistance(inches) > Distance7_OF.objectDistance(inches) > Distance3_OS.objectDistance(inches)) {
      if (Distance4_OSL.objectDistance(inches) > Distance8_OB.objectDistance(inches)) {
        Drivetrain.driveFor(forward, Distance2_DSL.objectDistance(inches), inches, true);
      }
    }
  wait(20, msec);
  }
}

// "when I receive opui" hat block
void onevent_opui_0() {
  while (true) {
    if (Distance7_OF.objectDistance(inches) > Distance3_OS.objectDistance(inches) > Distance4_OSL.objectDistance(inches)) {
      if (Distance7_OF.objectDistance(inches) > Distance8_OB.objectDistance(inches)) {
        Drivetrain.driveFor(forward, Distance2_DSL.objectDistance(inches), inches, true);
      }
    }
  wait(20, msec);
  }
}

// "when I receive bvnb" hat block
void onevent_bvnb_0() {
  while (true) {
    if (Distance8_OB.objectDistance(inches) > Distance7_OF.objectDistance(inches) > Distance3_OS.objectDistance(inches)) {
      if (Distance8_OB.objectDistance(inches) > Distance4_OSL.objectDistance(inches)) {
        Drivetrain.driveFor(forward, Distance2_DSL.objectDistance(inches), inches, true);
      }
    }
  wait(20, msec);
  }
}


int main() {
  // Initializing Robot Configuration. DO NOT REMOVE!
  vexcodeInit();

  // register event handlers
  O2P9(onevent_O2P9_0);
  D1P1(onevent_D1P1_0);
  opui(onevent_opui_0);
  bvnb(onevent_bvnb_0);

  wait(15, msec);
  vex::task ws1(whenStarted2);
  vex::task ws2(whenStarted3);
  vex::task ws3(whenStarted4);
  vex::task ws4(whenStarted5);
  whenStarted1();
}

You could use a variable that constantly is set to the lowest distance.

Where you have:

if (Distance3_OS.objectDistance(inches) <= 30.0)

You could replace the 30.0 with the variable and also add some code that if the distance value is less than the variable’s value that it would set the variable to that detected distance value.

I’ve tried that before but that didn’t help. When the robot detects a object it would go to it but if another object is detected then it would spin forever.

That could mean your code never has the lowest distance value reset, meaning that once an object was detected, your robot would always be “detecting” the object.

One solution for this issue is a timeout on the turning where if it has been turning for some amount of time the variable for closest object detected goes back to some high number, effectively telling the robot that it doesn’t see the object anymore. Now, I’d recommend actually making this timeout in terms of rotation rather than time itself, so that the robot won’t override detection when there is still an object there.

Another option is using a while loop inside of the if, so you’d have something like the following:

if (Distance3_OS.objectDistance(inches) <= 30.0){

    while (Distance3_OS.objectDistance(inches) <= 30.0){

        (Turning code)

    }

}

And then setting the detection variable to the closest distance detection (or a high number if there is nothing detected). This way, the robot will turn until the sensor which detected an object no longer detects it. This would unfortunately cause jerky motion because the robot would temporarily stop turning every moment that the distance value fluctuates or when the robot turns a bit and the turn causes the sensor to be slightly further from the object. However, this effect can be decreased with a tolerance on the distance in the while loop, where adding some number, like 2, to the 30.0 would allow the robot to keep turning smoothly until the distance reading is bigger by at least 2.

what do you mean by this? explain. I can make this in block code.

I’m slightly confused. So instead of doing

if (Distance4_OSL.objectDistance(inches) <= 30.0) {
while (Distance4_OSL.isObjectDetected()) {
D1P1.broadcast();
wait(20, msec);
}
}

i would have to do something like

if (Distance4_OSL.objectDistance(inches) <= 30.0) {
while (Distance4_OSL.isObjectDetected()) {

(D1P1.broadcast(); )

  wait(20, msec);
  }
}

? Never knew that parathesis could be so important in a while function.

I’m trying to figure out how to like of use a ignore or disable like command/function so for example if Distance5_OSR detects something 5 inches away i want it to send a signal to “disable” Distance 6-8 until the object being detected in Distance 5 goes out if the sensor FOV hopefully meaning that the object has been pushed of the table in my case. Afterward when the object isnt detected by Distance 5 anymore and cant recover the object view then it will send a signal to “re-enable” Distance sensors 6-8 then if needed it will turn until another object is found. I also do have sensors on the side of the robot but because we dont have a “H” drivetrain then it is coded so it will turn to face either Distance sensor 7 or 8 so as in the example i provided i mentioned distance sensor 5 detecting a object, Now that sensor has the ending “OSR” meaning “Outwards Side Right” and with the previous mention of not having a “H” drivetrain i need to have it coded to turn to either Distance7_OF (Outwards Front) or Distance8_OR (Outwards Rear). After it is confirmed that either the OR or OF sensors have detected the object it will “disable” all other sensors except for the downward facing sensors (1-4) which can override the program and take defensive movements if the robot detects it is going over the edge then it will try to regain sight of the object if it has been lost and go on with the code as usual.

Are you sure your code matched your ports?

Sorry about that, I should have clarified the parentheses were there to show that “Turning code” was not the code itself, this was meant as a placeholder.

This information is very helpful, I was assuming a maze-navigation robot. Now that I know the job of the sensors in your robot is to detect if an object has been pushed off of a table, you can ignore my suggestions of having the robot turn until the object is no longer the closest.

Instead, try having D1P1 only broadcast once, but then in the part of your code that reacts to D1P1, replace the while true with while (Distance4_OSL.isObjectDetected())

This would theoretically have the broadcast only happen once when the object is detected but, when the broadcast is received, the robot will continue pushing the object until it is no longer detected.

It should be because I pulled the port numbers directly from the vexiq code site but I am not sure about the physical robot because I haven’t had access to is since the 12th and the next expected time I can access it is the 24th but I think they are because it was functioning properly it’s just as it is moving to the targeted object it detects other things and goes out of control there usually spins in circles until the code is manually ended. Yesterday I made a few changes to the code so I would still have to test it but the changes made have to do with another part with the code and I am still trying to make a “stop” or “disable” code that can allow the robot to do and target one object at a time

Sorry for not clarifying the purpose of the bot, fyi I am competing in Robofest BottleSumo if you want to look into that for more clarification. I am not following with what you mean replace. Am i deleting

void onevent_D5OSR_0() {
while (true) {
if (Distance5_OSR.objectDistance(inches) > Distance7_OF.objectDistance(inches) > Distance6_OSL.objectDistance(inches)) {
if (Distance5_OSR.objectDistance(inches) > Distance8_OR.objectDistance(inches)) {
Drivetrain.driveFor(forward, Distance2_DSL.objectDistance(inches), inches, true);
}
}
wait(20, msec);
}
}

and replacing it with

void onevent_D5OSR_0() {
while (true) {
if (Distance5_OSR.objectDistance(inches) > Distance7_OF.objectDistance(inches) > Distance6_OSL.objectDistance(inches)) {
if (Distance5_OSR.objectDistance(inches) > Distance8_OR.objectDistance(inches)) {
(Distance4_OSL.isObjectDetected())
}
}
wait(20, msec);
}
}

I have also changed the broadcast names so

O2P9 => D5OSR
D1P1 => D6OSL
opui => D7OF
bvnb => D8OR

Close, but what I meant is try using a while loop to continuously gave the robot drive forward until the sensor no longer detects the object.

This would look more like a combination of the two variants you provided (the ones I quoted above). Here is the second variant with modifications bolded:

void onevent_D5OSR_0() {
while (true) {
if (Distance5_OSR.objectDistance(inches) > Distance7_OF.objectDistance(inches) > Distance6_OSL.objectDistance(inches)) {
if (Distance5_OSR.objectDistance(inches) > Distance8_OR.objectDistance(inches)) {

while(Distance4_OSL.isObjectDetected()){
Drivetrain.drive(forward);
}
Drivetrain.stop();
}
}
wait(20, msec);
}
}

This should have it so that if that distance value is the smallest, it triggers a condition that, while that sensor detects the bottle, the drivetrain will go forward. Only after this while loop ends (when the bottle is pushed off the table and is no longer detected by that sensor) does the code reach a command that tells the drivetrain to momentarily stop driving and let the rest of the code continue.

Note: Double-check that my suggested drivetrain commands work for you, because I haven’t coded with them in a while.

Ah, I think I’m starting to get it. Where you mention

while (Distance5_OSL.isObjectDetected()){
Drivetrain.drive(forward);
}
Drivetrain.stop();
}

just means if Distance sensor 5 detects something then it will target that object but outside the while its just saying that if the object is lost then it will stop the drivetrain and look for other objects to target, right?

Also the code seems to fit my robot with the exception that because i don’t have a “H” drive on the robot so i would have to add in a turn command so it could function correctly.

Yes, exactly.

There are multiple ways to make a custom turn command, but the way I’d recommend going about it is having a broadcast-based system so that you don’t have to copy-paste the individual motor commands each time. You already implemented this idea successfully in your code, so I’ll forego a redundant explanation for now.

Good luck!

Thanks! However I wondering will this “override” all other outward facing sensors or is that something i still have to work on. I was looking for a way to try and delay the response times of sensors 6-8 in this scenario so the object can be pushed off without any interruptions. Is there some type of disregard command that in can insert or is that more on the difficult side of things?

So, I did some digging and apparently broadcast doesn’t pause the main code while the event triggered is going on.

If you wanted the main code to pause while the robot is driving the object off of the table, one way is to have a variable, let’s call it stillDriving. The code that would trigger as a result of the broadcast would have its first line be to set stillDriving to 1 and its last line, after any loops, to set still Driving to 0. In the main code, there would be something like wait for 20 milliseconds, then a while stillDriving == 1 with nothing inside the loop.

This way, the main code would be “stuck” inside the while loop (doing nothing) while the broadcast-receiving code would have the robot drive the cup off the table, then the main code would be allowed to resume again.

In the scenario that you neeed some part of the main code still running while the robot drives the object off of the table, such as perhaps a sensor looking down to stop your robot from driving off itself, you could simply put that inside of the while loop instead of leaving it blank.

use broadcastAndWait to block the calling thread

but why the OP is using events here at all I’m not sure, if you want that code to be blocking it should just be a function that’s called. The broadcast/event programming pattern is a remnant of the limitations that the initial blocks implementation had, there are certain situations where it can help in C++ code but those are rare and just about all code can be written without need to use broadcast at all.

Thanks! I’ve just implemented the idea into my code however the next time i can test it is tomorrow i think so ill be back then to report what happened.

What is the point of broadcast and wait? Wouldn’t that just be the same thing as running a function?