Asked — Edited

Script Control - Looping Functionality Question. A Bug Or Brain Fart?

Situation: I've looked over all the scripts in the cloud and haven't seemed to find anything pertaining to looping. So I wanted to write a short tutorial for the community. So the simple loop example went okay, but as I wrote a loop within a loop. I am finding myself a little confused as the the process flow of the following code...

Here is the script:


#Loop With In Loop
Print("Loop with a loop")
$OuterCounter = 3
$InnerCounter = 2

:OuterLoopStep
  If ($OuterCounter >= 0)
    #Execute Outer Loop Command
    Print(">Outer Loop Value: $OuterCounter)
    $OuterCounter = $OuterCounter - 1

    :InnerLoopStep
      If ($InnerCounter >= 0)
        #Execute Inner Loop Command
        Print("Inner Loop Value: $InnerCounter")
        $InnerCounter = $InnerCounter - 1
        Goto (InnerLoopStep)
      Else 
        Sleep(3000)
        Goto(OuterLoopStep)
        #Wanted to use EndIf for formality, but not nessecary
  Else
    Print("Finished")
  EndIf

Here is the output of the debugger: Start 2: Print("Loop with a loop") Loop with a loop 3: $OuterCounter = 3 4: $InnerCounter = 2 6: :OuterLoopStep 7: If ($OuterCounter >= 0) 9: Print(">Outer Loop Value: $OuterCounter)

Outer Loop Value: 3 10: $OuterCounter = $OuterCounter - 1 12: :InnerLoopStep 13: If ($InnerCounter >= 0) 15: Print("Inner Loop Value: $InnerCounter") Inner Loop Value: 2 16: $InnerCounter = $InnerCounter - 1 17: Goto (InnerLoopStep) 13: If ($InnerCounter >= 0) 15: Print("Inner Loop Value: $InnerCounter") Inner Loop Value: 1 16: $InnerCounter = $InnerCounter - 1 17: Goto (InnerLoopStep) 13: If ($InnerCounter >= 0) 15: Print("Inner Loop Value: $InnerCounter") Inner Loop Value: 0 16: $InnerCounter = $InnerCounter - 1 17: Goto (InnerLoopStep) 13: If ($InnerCounter >= 0) 18: Else 19: Sleep(3000) 20: Goto(OuterLoopStep) 7: If ($OuterCounter >= 0) 9: Print(">Outer Loop Value: $OuterCounter) Outer Loop Value: 2 10: $OuterCounter = $OuterCounter - 1 12: :InnerLoopStep 13: If ($InnerCounter >= 0) 18: Else 19: Sleep(3000) 20: Goto(OuterLoopStep) 7: If ($OuterCounter >= 0) 9: Print(">Outer Loop Value: $OuterCounter) Outer Loop Value: 1 10: $OuterCounter = $OuterCounter - 1 12: :InnerLoopStep 13: If ($InnerCounter >= 0) 18: Else 19: Sleep(3000) 20: Goto(OuterLoopStep) 7: If ($OuterCounter >= 0) 9: Print(">Outer Loop Value: $OuterCounter) >Outer Loop Value: 0 10: $OuterCounter = $OuterCounter - 1 12: :InnerLoopStep 13: If ($InnerCounter >= 0) 18: Else 19: Sleep(3000) 20: Goto(OuterLoopStep) Here's where my confusion starts. Any ideas? Am I missing something obvious? 7: If ($OuterCounter >= 0) 10: $OuterCounter = $OuterCounter - 1 12: :InnerLoopStep 13: If ($InnerCounter >= 0) 18: Else 19: Sleep(3000) 20: Goto(OuterLoopStep) 7: If ($OuterCounter >= 0) 10: $OuterCounter = $OuterCounter - 1 12: :InnerLoopStep 13: If ($InnerCounter >= 0) 18: Else 19: Sleep(3000) 20: Goto(OuterLoopStep) 7: If ($OuterCounter >= 0) 10: $OuterCounter = $OuterCounter - 1 12: :InnerLoopStep 13: If ($InnerCounter >= 0) 18: Else 19: Sleep(3000) 20: Goto(OuterLoopStep)

and on and on the loop executes...


ARC Pro

Upgrade to ARC Pro

Join the ARC Pro community and gain access to a wealth of resources and support, ensuring your robot's success.

#1  

I'll be watching this thread. I'm on the learning curve of script writing and need all the info I can get. This stuff is very important I think and needed. Hopefully there will an area that's easily referenced in the new Wiki pages talked about in other threads for this kind of stuff.

Good luck!

#2  

Honestly, I'm having some issues with more complex scripts. Problem is, I'm not a programmer, but the results are clearly...weird.

I had the scipt working nearly 100%, but then it seemed to "degrade". I know that's not really possible, it's just code, but I'm getting stumped and confused.

I have a script that attempts to solve getting "boxed in". It checks to the left, it checks to the right, it back out, and then checks again.

It's not clean (lord knows I have no idea what clean code even looks like:) ), but it DID work.

So by degrade, I mean, the simple turn left loop was working just fine for example, now he just spins around and doesn't pass (or fail) any of the conditions like he did before. Nothing material has changed in the code. So what's with that!?!?!

I'll upload the code in a few minutes after I finish banging my head a bit more.

#3  

@Cyberdude

Feel free to send it my way. I'll take a look at it, maybe a different set of eyes can provide some insight.

As far as the scripting unpredictability, well ARC is still and work in progress and any concretely described bugs or quirks can only help DJ as he won't have to spend extra time replicating the error...

#4  

Here ya go. The logic works now, but when it does the final call to the backup routine, it seems to fail (Look at the console dump. Seems to call the routine and execute the first couple lines. However, in practice, I never see anything happen. It stops, but thats it.)...

$pingdist = 0
$pingmax = 20
$timer = 0
$maxtimer = 20

Goto(CheckpingLeft)

:BackUp
  Stop()
  Sleep(1000)
  Left(1000)
  Sleep(1000)
  Reverse(2, 1500) 
  Sleep(1500)
    Halt()          

:CheckpingLeft
  Left(2)
  $pingdist = Getping(d10, d11)
    if($pingdist >= $pingmax)
      Say("Ping greater than $pingdist left")
      Stop()
      Halt()
    Else
      $timer = $timer + 1
         If($timer = $maxtimer)
            Stop()
            $timer = 0
            Sleep(500)
            Goto(CheckpingRight)
          Else
            Goto(checkpingLeft)

:CheckpingRight
  Right(2)
  $pingdist = Getping(d10, d11)
    if($pingdist >= $pingmax)
      Say("Ping greater than $pingdist Right")
      Stop()
      Halt()
        Else
          If($timer = ($maxtimer+20))
          Goto(BackUp)
     $timer = $timer + 1
     Goto(checkpingRight)

And here is the console:Console.zip

#5  

OK, fooled around with my backup routine. I was missing a number in my "left" call ; )

Now the script works. Yay.

PRO
Synthiam
#6  

Ah, I see something. It's a little quirk in the stack. Ooops! I'll fix that this weekend:)

It's when the IF is called within the IF... A little logic error in my compiler .

EZ-Script is not actually a script, even though it has that in the name. The code is compiled into OP Codes and handed off to an interpreter. The interpreter has a hook within the ARC host to control stuff with ControlCommand(), and a reference to the EZ_B.DLL for stuff like Servo, GetPing, etc..

That is why EZ-Script is actually very fast

So the compiler parses your human readable code and converts it to an array of commands, which contain OP Codes and parameters - much like you'd see in Assembly (which I spend a lot of time in for the firmware, so I like it). We call the array of commands the "Program Memory"

The compiler assigns "goto" and "failedCondition" to each command pointing to a location within the "Program Memory". So each Command executes its appropriate OPCode and uses the respective parameters. The goto or failed condition memory location is set as the next program memory location to move to.

Within the interpreter, there are a few ways to move through program memory. Every command has a Goto parameter, which specifies the next memory location to move to. This is usually the next memory location, unless the user code explicitly specifies to GOTO() somewhere:)... That is determined during compiling - and Goto() has no bugs.

The "failedCondition" is where the bug is. If the "if" condition fails, the compiler has a bug when determining the stack and goes to the wrong line number:)

PRO
Synthiam
#7  

As for the speed that I claim, I should show you this:)

This is a test with 1 stack and simple math.


$x=0

:start

  $x = $x + 1

  goto(loop1)

  goto(start)

:loop1

  return()

$x will equal 36,563 in 1.01 seconds

If you think of it in execution steps, that's 4 * 36,563 = 146,252 operations per second on my computer.

User-inserted image

The reason I count 4 steps, is because there are really only 4 operations in the counting part of that code.. The only operations are bolded


$x=0

:start

  $x = $x + 1

  goto(loop1)

  goto(start)

:loop1

  return()

You can see only the operations when you run in the Config Debug view...

Quote:

Start 1: $x=0 3: :start 5: $x = $x + 1 <--- 1 7: goto(loop1) <--- 2 13: return() <--- 3 9: goto(start) <--- 4 5: $x = $x + 1 <--- 1 7: goto(loop1) <--- 2 13: return() <--- 3 9: goto(start) <--- 4 5: $x = $x + 1 7: goto(loop1) 13: return() 9: goto(start) 5: $x = $x + 1 7: goto(loop1) 13: return() 9: goto(start) 5: $x = $x + 1 7: goto(loop1) 13: return() 9: goto(start) 5: $x = $x + 1 7: goto(loop1) 13: return() 9: goto(start)

Because this is an actual "compiled" programming language, it's that fast:)

#8  

:CheckpingRight
Print("Checking right...")
  Print("Right(2)")
  $pingdist = Getping(d10, d11)
    if($pingdist >= $pingmax)
      Say("Ping greater than $pingdist Right")
      Print("Stop()")
      Print("Halt()")
    Else
      If($timer = ($maxtimer+20))
        Print("timer = maxtimer + 20")
        Goto(BackUp)
        Print("Does the following code get executed?")
        $timer = $timer + 1
        Goto(checkpingRight)

I think it might be possible the code formatting may be confusing you...