
Ghosty
Hello,
Forgive my newby question, but I am attempting to make my robot a little smarter at turning that just turn for x mseconds.
Below is my adaptation of one of the sample scripts, but what I really want to do is if object A is 30 in front turn to a clear side until object A is> 120, then rescan and proceed forward.
What I cant work out is how to give a turn (left or right) command based on a US signal value increasing in value to a designated "ok to proceed" value. I have the which way to turn done, but not turn for how much.
Any Help would be greatly apreciated.
Set the servo left position
$PosL = 90
Set the servo center position
$PosC = 50
Set the servo right position
$PosR = 30
Set the mininum distance
$MinDist = 30 $SlowDist = 100 $RDMin = 50
:Loop
Begin Scanning IO
Middle Stationary US
$PingMid = GetPing(d2, d3)
Scan left
Servo(d7, $PosL) Sleep(500) $PingL = GetPing(d0, d1)
Scan Center
Servo(d7, $PosC) Sleep(500) $PingC = GetPing(d0, d1)
Scan Right
Servo(d7, $PosR) Sleep(500) $PingR = GetPing(d0, d1)
#Begin Move
if ($PingMid $PingL) $Ping1 = $PingR endif If ($Ping1 < $MinDist) Reverse(255, 1000) Elseif ($Ping1 < $PingL) Right (255,1000) Else Left (255,500) Endif forward(20) Return()
:RightBad left(255, 500) sleep(1000) Forward() Return()
Unfortunately my time today is very limited however if you are following my Introduction To Scripting topic the next one will be explaining how to do advanced avoidance much like you have explained. I hope to be able to write that up in the next couple of days
Also, take a look at this topic
Thanks very much and I am sure the community will appreciate your input, especially newbies like me. Ty
Hi Rich,
Thanks for your tutorials, I hadn't seen them I was using the example code in EZ-B software. I wanted to have two different move speeds globally set. ie Slow for tight spaces and Fast for open area's. I tried setting a global of $MF1 = 20 and another of $MF2 = 255, but when ever I used them I would get an error, I think based on your tutorials it was because I didn't use a time value as well. I used Forward($MF1), I omitted the time base. So I will go back and play with this. The challenge I want to address though is the time base value, I want to be able to manipulate this value based on ping signal. I don't want the robot to turn for 300msec, I want it to turn until ping>X stop turning move forward.
I have a Irobot Scooba, and it is completely stupid (read bump logic, for robot direction control, and random floor patterns). I am trying to build a brain for it that will have it map the room and progressively mop the floor moving accross the room (know I am goign to have to hack the main board as the scooba has no plugin). My test bot is the EZ-B components and 5 additional US and 1 IR sensors, mounted on a meccano frame. One thing I have noticed and will have to work out how to code is wheel slip. My robot does an ARC accross the room. I have adjusted the servo speeds to reduce the arc, but it is still not perfectly straight. This is a big project for a newby, hence I am starting off simple with the kit when I have it functioning then I will put it into Scooby, for now he still has floor's to mop.
Thanks for your help, I will tidy up my code with some more Text explanations and keep my declarations together and stated. Keep up the good work this stuff is great fun. Ghosty
Very quickly, and I'll admit I only read half of your post as I need to get a wriggle on and should be in bed (will probably revisit this in 15 minutes though...)
the Forward, Reverse, Left & Right don't need a time. Forward(255) will just go forward at full speed forever (or until something else stops it).
A very quick script, it may not work since this is done entirely from memory with no ARC in sight...
If my scripting knowledge lives up to it's reputation that should turn left, while turning it should check the ping sensor, if under the defined ping will continue checking and turning until it is over the value, then move forwards.
As I said may be the case, revisiting
You said your code had an error when using the $MF1 variable? Errors usually give explanations as to why they are errors. What does it say in the dialogue when it stops on error? It should work provided the variable is an integer.
A common error I get when I am not checking things as I type them is numbers are stored not as integers but as decimals for some calculations i.e. earlier I was writing code to find the center point of a sweeping servo by using max postion - min position / 2. it would calculate a decimal number on occasion and throw an error. To solve, it was just a case of using the $variable = Round($variable,0) command
The other common error on this is I make a mistake on the variable name. For instance putting $varialbe rather than $variable. However on $MF1 I can't see how that would be missed.
While I'm at it, a quick change to the above code...
Just made it a sub routine so it can be called easier and returned from which is how I prefer to script (makes it easier for future modifications) and moved the sleep to a better position. The $x could be part of a different routine, at least I would make it as part of one, then the main script could call the routine to determine $x based on whatever parameters you want, then call the turning routine.
Thanks Rich
Is there a way to increase the scan time or have the EZB performing an action (sub routine) and yet still scan the "loop" section of the program.
I have changed my logic greatly and reduced it to the bare min, but have found I need to go back and add "Estop" lines in through the sub routines as whilst it is performing a sub routine, it appears it is not going through the "Loop" section every X mseconds.
I amused to ladder logic and industrial PLC's that scan the ladder every 20ms regardless of what timers or routines are happening at the same time.
I have put my robot onto a Hbridge based model and this moves significantly faster, so I have changed the PWM setting to 8 to make it slow enough, for the US on the servo to get the three readings and react in time. But what I am finding is if the front bumper, a single Digi in activates, the logic does nothing until it has completed the "goto" it is currently in and then works back through the "loop" section of the logic. Hence I have ended up putting the Estop routine in every goto and the main loop.
Maybe I am missing something and taking the wrong approach?
I also want to look at using a data array that can store the last "change of direction" routine output so if the next routine is the same one we simply make the same outcome again. On occasions my robot will get into a spot and turn left, re-verify its position and turn right back to were it was. I have gotten around this by setting the turn time to two different values so it turns a diffrent amount, still not perfect but it does eventually extract it self. The code you have above for turning until $X should solve the issue I think.
here is my current script, evolved from the first post
Object Avoid Script
Global Defined
$PosL = 75 # Set the servo left position $PosC = 65 # Set the servo center position $PosR = 50 # Set the servo right position $ESTP1 = 0 # Digital in to record a bumper var pressed -preset to 0 $ESTP2 = 0 # Digital in to record a bumper var pressed -preset to 0
Set the mininum distanceces
$MinDist = 30 # Min distance to must do something $SlowDist = 150 # slow down distance - ie tight space $RDMin = 50 # Radar US range that action is required $lastD = "Forward" # want use as an array to hold a value for corner trap
:Loop
Begin Scanning IO
$ESTP1 = GetDigital(D8) # Bumper Front $ESTP2 = GetDigital(D9) # Bumper Top
If ($ESTP1 = 1 or $ESTP2 = 1) # Act imediatly if bumper is pressed $ESTP = 1 Goto(Estop) endif
Scan left
Servo(d0, $PosL) Sleep(500) $PingL = GetPing(d1, d2)
Scan Center
Servo(d0, $PosC) Sleep(500) $PingC = GetPing(d1, d2)
Scan Right
Servo(d0, $PosR) Sleep(500) $PingR = GetPing(d1, d2)
Scan Rear
$PingB = GetPing(d12, d13)
#Begin Move PWM (D15, 8) Forward (8)
If ($ESTP1 = 1 or $ESTP2 = 1) $ESTP = 1 Goto(Estop) endif
check if we can increase speed
If ($PingC > $RDMin) and ($PingC < $SlowDist) PWM (D15, 8) forward(8) Else forward(20) Endif
Check for obstical left
If ($ESTP = 0) and ($PingL < $RDMin) goto (Changedirect) Elseif ($PingL < $SlowDist) PWM (D15, 8) Else Forward(20) Endif
Check for obstical Right
If ($ESTP = 0) and ($PingR < $RDMin) goto (Changedirect) Elseif ($PingR < $SlowDist) PWM (D15, 8) Else Forward() Endif
If ($ESTP1 = 0 and $ESTP2 = 0) $ESTP = 0 Endif
Goto(Loop) # Return to the top and start over
:Changedirect # Find out which direction can be taken ** needs more refining work**
Slects the more clear space left or right and stores it in Place holder
If ($PingR < $PingL) $Ping1 = $PingL Elseif ($PingR > $PingL) $Ping1 = $PingR endif
Checks place holder value against the min dist value and then acts
If ($ESTP = 0) and ($Ping1 < $MinDist) and ($PingB > $MinDist) Reverse(50,500) Elseif ($ESTP = 0) and ($Ping1 = $PingL) Left (10,450) Elseif ($ESTP = 0) Right (10,350) Else Goto (Estop) Endif Return()
:Estop # one of the bumpers is pressed, back away and turn left Reverse(10,1000) Left (10,250) $ESTP1 = GetDigital(D8) $ESTP2 = GetDigital(D9) If ($ESTP1 = 0 and $ESTP2 = 0) $ESTP = 0 Endif Goto (Changedirect) Return()
That's far too much for me to process when I've not long woken up... I'll address this better later.
But, to run more than one routine simultaneously you can write the sub routine as a new script and use a ControlCommand to start and stop it, the script will start the routine but also continue on it's own code too rather than waiting for the sub routine to stop.
This is also an issue that needed addressing in the ping roaming script I was working on with R2D2 (look in the cloud for my ping roam project). We needed to move the robot, sweep the servo and scan the sensors, then avoid etc. so quite a few little things happening at once. It may pay to look at that code to see how it was done. Although ControlCommand is probably the easiest way, especially now we can pause a script too.
Moving based on previous movement is something that I plan to address in the ping roam script too. The previous movements can be stored as $variables or written to file, I prefer variables. But then that can be used when it checks again, and an if put in place to check the previous move against the new move and if they cancel each other out (i.e. a move right is decided when the last move was a move left) it can check again or run in some boxed in code or whatever. (Boxed in is the part I have been working on lately in this script but currently can't test as Melvin doesn't have a sweeping sensor and testbot is being upgraded to wifi)
To have it performing another action at the same time as the scanning loop the best way would be to use
This is why I will be having front, left and right sensors rather than a sweep servo on Melvin, he moves too fast to sweep. Sometimes you need to alter the setup for better results. As for the front bumper not registering due to being in a goto, you could always make the front bumper code a separate script that loops around on it's own constantly, regardless of other scripts and code. You can add in ControlCommands to stop other scripts when the bumper is activated too, and then another to restart it. Or you could use a variable so when the front bumper is activated the other scripts wait for the bumper script to finish;It may need to be called a lot throughout the script though so ControlCommand would be my prefered option.
My updated PingAvoidance uses the turning until $x > $y routine. I've made it public now however be aware it is incomplete and still has some bugs that need working out. But it should prove useful for you to see how I've approached different issues. Download it here