Welcome to Synthiam!

Program robots using technologies created from industry experts. ARC is our free-to-use robot programming software that makes features like vision recognition, navigation and artificial intelligence easy.

Get Started
Asked — Edited
Resolved Resolved by WBS00001!

Avoidance Script Help

***edit****
Going to repost later.

AI Support Bot
Related Content
Synthiam
#2  
Thanks Bob, I will have a look. What I'm hoping, when the script is ran and it only needs to go left to avoid an object it goes back to forward without having to run left, reverse etc. or the rest of the script, hope that make sense.
#3  
After going though Rich's post I got it to work only using the below script. However, it always reverses before going left or right. Alarm1 should only reverse if all 3 ping sensors are lower then 45, but if 1(right) or 2 (left) ping sensors get below 45 it reverses then goes right or left depending on which side of the sensor is below 45. I only want it to reverse if all 3 (L,C,R) ping sensors are tripped.

Can someone without taking to much time explain what I am missing? This is just a simple script and I am so it could get pretty involved so I just want a simpleton script. Cheers,

Code:



:sensorcheck
$proxclose =45 # Change for minimum distance
$proxsideclose = 45 #Change for minimum distance

$proxbaseC = GetPing(3.D22,3.D23)
$proxbaseR = GetPing(3.D15,3.D14)
$proxbaseL = GetPing(3.D13,3.D12)
$proxsideL = GetPing(3.D10,3.D11)
$ProxsideR = GetPing(3.D16,3.D17)


# If 3 ping sensor >45 go forward
if($proxbaseC > $proxclose or $proxbaseL > $proxclose or $proxbaseR > $proxclose)
goto(Clear)



#If 3 ping sensors <45 stop and reverse
elseif($proxbaseC < $proxclose or $proxbaseL < $proxclose or $proxbaseR < $proxclose)
goto(Alarm1)


# if 3 front ping sensors Center and left less <45
elseif($proxbaseC < $proxclose or $proxbaseL < $proxclose and $proxbaseR > $proxclose and $proxsideR > $proxsideclose)
goto (AlarmR)



#if 3 front ping sersors center and right < then
elseif($proxbaseC < $proxclose or $proxbaseR < $proxclose and $proxbaseL > $proxclose and $proxsideL > $proxsideclose)
goto (AlarmL)
endif


goto(sensorcheck)

:Alarm1
#if ($pingFR < 40)
Say("Object Detected")
Stop()
Reverse(255,2000)
Sleep(1000)
Return()

:AlarmR
#if ($pingFL < 40)
Say("Object Detected")
Stop()
Right(255,2500)
sleep(2000)
return()

:AlarmL
#if ($pingFL < 40)
Say("Object Detected")
stop()
Left(255,2500)
sleep(2000)
Return()

:Clear
#if ($pingFL > 60)or ($pingFR > 60)
Say("No Object Detected")
Forward()
Sleep(500)
Return()



#Halt()
#4  
Well I tried it one more time and all 3 sensors coved and it did reverse, but then it goes to right and left before going forward again. I don't know what I am doing wrong. *stress*
#5  
Just giving the code a quick once over, I see you have used "or" conditionals when you should have used "and"

For example given the comment:
# If 3 ping sensor >45 go forward
To me this says "Only If ALL of the 3 ping sensors are greater than 45, then go forward." But what you have actually coded currently says "If ANY of the 3 ping sensors are greater than 45, go forward". You need to change the "or" conditionals to "and" The same for the other statements as well. They should all be ands, not ors.

There are some other issues as well, but I won't go into them until we see how these changes work out.
#6  
Sweet! @WBS00001 that worked, thank you.
if all 3 sensors are close it reversed, if right and center sensors are close, it turned like it should:) . I noticed if only the right sensor is close nothing happens and continues forward. So I must need to add more elseif statements, is this correct?

I am now a happier camper:D
You mentioned there are other issues? Thanks again.
#7  
WBS00001 Did solve my issue and thank for your quick reply. Hope you offer more advise. Cheers!
#8  
Very good! Glad that helped. Before I can advise further I will need some information.

Now that I have had time to look at the code more closely, it appears the Ping Sensor configuration is 3 pointing forward on the base (Left, Center, and Right) and there are two sensors on the left and the right for a total of 5. Is this correct?

Assuming it is then I was wrong in telling you to change the "or" conditionals to "and" types in the ElseIf statements. The ElseIf statements should be put back the way they were. However, changing the conditionals to "and" type in the first (If) statement is still correct. You only want to move forward if all 3 front facing sensors are clear.

I see the 4 If-ElseIf statements saying the following:

1) If ALL 3 front Ping Sensors are returning clear (nothing close to them), move forward.
2) ElseIf ANY of the Base Sensors detect something close, stop and reverse.

As I said above, here I can see now that the conditionals in this first ElseIf statement should have been left as they were. Sorry I didn't realize that last night. In fact all the ElseIf statements should be put back to the way they were.

Continuing on with the ElseIfs back to how they were then:
3) ElseIf the Center Base Sensor OR the Left Base Sensor detects something close, AND the Right Base Sensor is clear AND the Right Side Sensor is Clear, then Turn Right.
This is to avoid obstacles ahead towards the Left.

4) ElseIf the Center Base Sensor OR the Right Base Sensor detects something close, AND the Left Base Sensor AND the Left Side Sensor are clear, then turn Left.
This is to avoid obstacles ahead towards the Right.

These states should also take into account if the unit is heading for the right or left wall, but only if it is heading that way at an angle.

Another question I have is what are the variables $pingFL and $pingFR? When are they set to some value?

As it stands now, I think the unit will go in a zig-zag pattern as it avoids obstacles. That is not a bad thing, just that it appears it will go all the way from wall to wall as it avoids things instead of turning from an obstacle and going back straight again. I'll have to give that more thought, however.

There may be an additional problem with the first ElseIf statement. I will need to run some tests to be sure. After I do, I will post again.
#9  
I will have a look to night after work, don't have time right now. Here is the code right now, I cleaned it up a bit so it reflects the correct "if" statements, however, I have not modified it back to the original yet. I wanted to get the basics working before assigning the Side pings Left and Right statements so it will not zig zagging while moving as you pointed out. Thank you.

Code:


:sensorcheck
$proxclose =45 # Change for minimum distance
$proxsideclose = 45 #Change for minimum distance

$proxbaseC = GetPing(3.D22,3.D23)
$proxbaseR = GetPing(3.D15,3.D14)
$proxbaseL = GetPing(3.D13,3.D12)
$proxsideL = GetPing(3.D10,3.D11)
$ProxsideR = GetPing(3.D16,3.D17)


# If 3 ping sensor greater than 45 go forward
if($proxbaseC > $proxclose and $proxbaseL > $proxclose and $proxbaseR > $proxclose)
goto(Forward)



#If 3 ping sensors less than 45 stop and reverse
elseif($proxbaseC < $proxclose and $proxbaseL < $proxclose and $proxbaseR < $proxclose)
goto(Reverse)


# if 3 front ping sensors Center and left less <45
elseif($proxbaseC < $proxclose and $proxbaseL < $proxclose and $proxbaseR > $proxclose and $proxsideR > $proxsideclose)
goto (AlarmR)



#if 3 front ping sersors center and right < then
elseif($proxbaseC < $proxclose and $proxbaseR < $proxclose and $proxbaseL > $proxclose and $proxsideL > $proxsideclose)
goto (AlarmL)
endif


goto(sensorcheck)

:Reverse
#if (all 3 base pings less then 45)
Say("Object Detected")
Stop()
Reverse(255,2000)
Sleep(1000)
Return()

:AlarmR
#if (base pings Left&Center less than 45)
Say("Object Detected")
Stop()
Right(255,2500)
sleep(2000)
return()

:AlarmL
#if (base pings Right&Center less than 45)
Say("Object Detected")
stop()
Left(255,2500)
sleep(2000)
Return()

:Forward
#if (all 3 base pings greater then 45)
Say("No Object Detected")
Forward()
Sleep(500)
Return()



#Halt()
#10  
I have run a few tests and thought about the various conditions in the main If-ElseIf code. Given the last two ElseIf statements, it may be advantageous to use "and" conditionals in the first ElseIf statement after all. This is because it may be best to not stop and reverse if just one of the front facing sensors detects something. Such would be the case if "or" conditionals are used in that first ElseIf instead of "and". Because the next two ElseIf conditions use the condition in which just 1 or two of the base sensors detect something. As I mentioned in my last post, those ElseIf conditions take care of the situation in which there is an obstacle to the right or left of the unit. They cause the robot o turn one way or the other to avoid it. The first ElseIf, however, should probably take care of the situation in which there is a total blockage just ahead of the robot (like a wall). For that to be detected, all 3 Base Sensors should be less than 45. For that to be the case, there should only be "and" conditionals in that first ElseIf statement.

Now here is the problem with the robot's actions in relationship to that first ElseIf. What happens now is the robot simply reverses. I'm assuming it reverses enough so that the Ping reading will be greater than 45. Once it does that, the script will check the Ping State of the sensors and see that it is clear. That will cause the robot to move forward since the first If condition will be met (all 3 Base sensors > 45). And it will move forward until it gets close enough to the obstacle for the readings to go below 45 and the whole thing will repeat again. And again, and again, etc.

So there will need to be more code associated with the :Reverse Goto label lines of code. For instance, it could try to go around or it could turn completely around and go the other way or go 90 degrees and try that, etc. All sorts of possibilities. Depends on what you want it to do in that situation.

Likewise the last 2 ElseIf conditions do nothing but turn. If the 3 Base Sensors are clear after the robot turns, it will go forward from that point; whatever way it is turned. It will not go back to the direction it was going before the turn. For that you will need to add more code to the :AlarmL and :AlarmR goto code lines.

One of the things to keep in mind with If-ElseIf statements is that once one of the conditions is met, none of the rest of the possibilities will be checked. So, even if other possibilities might also be "True" nothing will happen because of that for that execution of the IF-ElseIf code loop.

So in summation, If you want the first ElseIf condition to execute only when all 3 forward pointing Base Sensors detect an obstacle, use "and" conditionals in it, not "or". The last 2 can be like they were originally with a combination of "or" and "and" conditionals. Think about what you want the robot to do for each of the ElseIf conditions. It might also be advantageous to have the robot say something more specific when it speaks. For example, instead of saying just "Object Detected" when it turns right, it could say "Object detected on left, turning right".

Feel free to ask questions.
#11  
@WBS00001,

Been working to many hours lately, tonight I have a few hours so below is what I've changed. It seems to work pretty good. I have not field tested yet and still have a few more things to add. The base is lifted up so the wheels turn but can not move. I plan to use the reverse for the dropoff code, just have not finished this yet. Please have a look and any other suggestion will be much appreciated.

Cheers,

Code:


:sensorcheck
$proxclose =45 # Change for minimum distance
$irclose = 120
#$irclose2 = 45
$UbaseirR = 133
$UbaseirL = 65

$proxsideclose = 45 #Change for minimum distance
$proxbaseC = GetPing(3.D22,3.D23) # frontbase
$proxbaseR = GetPing(3.D15,3.D14) # frontbase
$proxbaseL = GetPing(3.D13,3.D12) # frontbase
$proxsideL = GetPing(3.D10,3.D11) # frontbasesideL
$ProxsideR = GetPing(3.D16,3.D17) # frontbasesideR
$baseir1 = getadc(3.adc1)
$baseir4 = getadc(3.adc4)
$ubaseR = getadc(3.adc0)
$ubaseL = getadc(3.adc7)


#IRbasesensors
$Baseir1 #3.adc1 frontbase
#$Baseir2 #3.adc2 frontbase
#$Baseir3 #3.adc frontbase
$Baseir4 #3.adc4 frontbase
#IRunderFrontBase
$UBaseirR #3.adc0 underfrontbase
$UBaseirL #3.adc7 underfrontbase

# Check sensors if greater than 45 go forward or stop elseif's
if($ubaseR > 135 or $ubaseL > 65)
goto(dropoff)

elseif($proxbaseC > $proxclose and $proxbaseL > $proxclose and $proxbaseR > $proxclose)
goto(Forward)

#If any ping or IR sensors less than 45 stop
elseif($proxbaseC < $proxclose or $proxbaseL < $proxclose or $proxbaseR < $proxclose)
goto(Stop)




#If 3 ping sensors less than 45 stop and reverse #"*"
#elseif($proxbaseC < $proxclose and $proxbaseL < $proxclose and $proxbaseR < $proxclose)
# goto(Reverse)

endif
goto(sensorcheck)

:Forward
#if (all 3 base pings greater then 45)
Say("No Objects Detected continuing forward.")
forward()
Return()

:Dropoff
Stop()
Saywait("Stopping, dropoff in front. Exiting Anti-collision script.")
Halt()

:Stop
stop()
Saywait("Object ahead, stopping to think. Please stand by!")
goto(Turndecision)

:Turndecision
#If baseLR or Baseir1 less than 45 request turn right
if($proxbaseC < $proxclose or $proxbaseL < $proxclose and $proxbaseR)
goto(TurnR)
Return()
elseif($proxbaseC < $proxclose or $proxbaseR < $proxclose and $proxbaseL)
goto(TurnL)
endif
Return()

:Reverse
#if (all 3 base pings less then 45)
#Saywaiat("Object Detected ahead")
#Stop()
#Reverse(255,2000)
#Sleep(1000)
#Return()

:TurnR
#if (base pings Left&Center less than 45)
Saywait("Decision to turn Right, object up ahead")
Right(255,1500)
return()

:TurnL
#if (base pings Right&Center less than 45)
Saywait("Decision to turn Left, object up ahead")
Left(255,1500)
Return()



#Halt()
#12  
Hey merne, did you get it all working OK? Here's my script I use for object avoidance; it is based on the tutorial that Rich did, that I mentioned in post #2.

Code:


:sensorcheck
$proxclose = 30 # Change for minimum distance

$proxsenseC = GetPing(1.d2,1.d1)
$proxsenseR = GetPing(1.d3,1.d4)
$proxsenseL = GetPing(1.D5,1.D6)
$proxsenseW = GetPing(1.D10,1.D11)

if($proxsenseC < $proxclose or $proxsenseW < $proxclose)

Reverse(1,2000)
sleep(1000)
Left (1,1500)

elseif($proxsenseC < $proxclose and $proxsenseW < $proxclose and $proxsenseL < $proxclose)

right(1,1500)
sleep(500)

elseif($proxsenseC < $proxclose and $proxsenseW < $proxclose and $proxsenseR < $proxclose)

left(1,1500)
sleep(500)


Elseif($proxsenseR < $proxclose)

left(1,1500)
sleep(500)


elseif($proxsenseL < $proxclose)

right(1,1500)
sleep(500)

Elseif($proxsenseC and $proxsenseR and $proxsenseL and $proxsenseW < $proxclose)
Reverse( 1,2200)
Sleep(1000)
Left(1,8000)

else

Forward()


endif
sleep(100)
goto(sensorcheck)

#13  
hey bob, I did get it working and it seems to work good, the only thing is the slow response to detect an object. I think the bumper sensors that toymaker and D.cochran are using would be a lot better and faster, but I do not have any info on that. If I knew how to program an Arduino I would use them with the EZB. I have not given up on the Arduino yet. I see that budel0 has made great progress on his navigation program and hope he share with the community when he completes it.

Cheers,
#14  
@merne
I finally got a chance to give the script a look over and it seems to be fine. The only minor error I saw was the spelling of SayWait in the Reverse section. Functionally it looks okay. Hard to say why it is slow responding. It's possible the channel is being flooded and it is missing readings.

The script is going to spend most of it's time reading the sensors. Checking the If-ElseIf section takes practically no time by comparison so it's almost as if it is in a loop, simply going through the sensor checks again and again only. This often leads to channel flooding. Although it seems counter intuitive, adding a bit of a delay in the loop could actually help the situation. Perhaps a sleep statement just before it checks the sensors. Not too much, 100ms maybe to start with. Another way that could be even better is a smaller sleep between each sensor's check, maybe 10 or 20ms each. That should definitely help prevent channel flooding.

In addition to the sensor checks, there is the Forward() command being sent again and again when it is going forward with no obstacles in front of it. It would be best to not send it every time. You could do this with the introduction of another variable to keep track of the motion state. For Instance, something like:

Code:


#In the variable declaration section at the top:
$CurrentMotion ="Stop"

#Then, when the code gets to the Forward Goto Label:
:Forward
if ($CurrentMotion !="Forward") #Do this only if not currently going forward.
$CurrentMotion ="Forward"
#if all 3 base pings greater then 45
Say("No Objects Detected continuing forward.")
forward()
endif

That way it only sends the Forward command once. Of course, if you wish it to say the phrase "No Objects Detected continuing forward" every time through the loop, you would have to move the Say statement outside of the If statement. But, if you do that, having it send the data for that Say statement every time through the loop can also help lead to channel flooding. It may not in this case, however, since "Say" sends the data to the PC and not to the robot.

Finally, in the other Goto sections, set the $CurrentMotion variable to some appropriate state depending on which label the script went to so as to keep track of the units current motion state. Such a variable can be handy for making other decisions as well.

Another possibility is the reliability of the sensor's return echo. But the solution to that could cause unacceptable delay in itself, so I won't go into detail right now. Such a thing would most likely show up in unexpected motions of the robot. Turning or stopping when the way is clear.

Good luck!