Shop OBEX P1 Docs P2 Docs Learn Events
It's a lot harder than it looks — Parallax Forums

It's a lot harder than it looks

lardomlardom Posts: 1,659
edited 2013-03-30 18:26 in Robotics
This is just a comment but I suspect I'm not the only one to experience this problem. I've spent several weeks trying to come up with instructions for my
'cobbled together' robot to avoid walls and objects. The behavior is still unpredictable and 'goofy'. All I want it to do is move in the direction that is most open. A few examples are; "If you get within 26 cm, 'back up' :". If you get within 45 cm and right side is longer than 80 cm, turn right 45° ". "If you get within 45 cm and right side is less than 81 cm, turn left". In this situation it could move forward then backward indefinitely. And then again, it might turn right and maybe left.
I'm not out of ideas but I do have to put it down after tinkering with it for awhile.

Comments

  • garyggaryg Posts: 420
    edited 2013-03-26 10:58
    Hi
    I'm working on a similar roaming program.
    My platform is set up with Servo mounted Ping sensor and two Sharp IR sensors.
    I use a BS2 Homework board for control.
    Here's where I run into trouble.
    My Ping sensor sometimes does not see some objects, like my sweater.
    Panning with the servo is pretty fast, but what I've noticed is that sometimes, I'm looking in the wrong direction
    to see objects in time to stop or correct the steering direciton.
    The Sharp IR sensors help in that when the platform gets within about 8" or so of an object, the platform will stop, pan again
    and decide where to go.
    I'm patiently awaiting the snow melting, so I can take it outside and do a thorough test.

    I'm hoping these comments help you out.
  • ratronicratronic Posts: 1,451
    edited 2013-03-26 14:02
    Larry you should post your latest code you tried.
  • GordonMcCombGordonMcComb Posts: 3,366
    edited 2013-03-26 17:02
    A specific program structure can often help with combinational logic for handling multiple sensor events. Review what some of the others have done and see if there's a format you like best. Apart from just forming an order and priority for the combinations, it can be a hassle to maintain them all in clean code. Ideally the format and approach should work equally well for whatever you want to do -- steer toward the open area, toward the dark spot, away from the loudest noise, toward the biggest bot within a 1 meter radius, whatever.

    In the latest SERVO Magazine Dennis Clark re-introduces the idea of behavior-based robotics, which is made to handle this sort of thing. The Propeller especially makes this form of robot control quite doable. I think Dennis demonstrates the concept using a simple Arduino procedural code structure, but with eight cores going independently in a Prop you can feed their outputs to a central routine that can make a determination of what to do given the variety and priority of the triggered events.

    -- Gordon
  • lardomlardom Posts: 1,659
    edited 2013-03-27 09:36
    Quote by garyg
    Panning with the servo is pretty fast, but what I've noticed is that sometimes, I'm looking in the wrong direction
    to see objects in time to stop or correct the steering direciton.
    I have a similar setup and my servo takes 1.9 seconds to pan 180°. I slowed the robot down but the problem is still there. My basic logic is flawed.

    @ratronic, This code sits between the motors and a Ping sensor. It calls the Ping, tests the returns and copies the result to a variable. The left and right motor objects use that variable for motor control.
    OBJ
        Pas : "PasServoParameterDemoV2"   'saves ping values to five variables         
    
    VAR
        long  LefSide, Ahead, RiteSide, stack[150], LS, RS, motorVariableL, motorVariableR, NW, NE   
        word  cogC
     
    PUB Start  : success  
        
        Pas.Start   
        Stop
        success := cogC := cognew(main, @stack) +1
    
    PUB Stop                                                   
                                                                   
        If cogC 
          cogstop(cogC~ - 1) 
    
    PUB main    
    
        repeat
          LefSide  :=  Pas.West
          NW       :=  Pas.North_West
          Ahead    :=  Pas.North
          NE       :=  Pas.North_East
          RiteSide :=  Pas.East
          if Ahead < 26
            motorVariableL := motorVariableR := 1    'back up
          elseif Ahead < 41 and RiteSide > 80
            motorVariableL := motorVariableR := 2    'turn right
          elseif Ahead < 41 and RiteSide < 81
            motorVariableL := motorVariableR := 3    'turn left
          elseif NW < 38
            motorVariableL := motorVariableR := 4    'Pivot_Left
          elseif NE < 38
            motorVariableL := motorVariableR := 5    'Pivot_Right
          elseif Ahead > 40 and RiteSide < 28
            motorVariableL := motorVariableR := 6    'arc left
          elseif Ahead > 40 and LefSide < 23
            motorVariableL := motorVariableR := 7    'arc right
          elseif Ahead < 60
            motorVariableL := motorVariableR := 8    'go slow       
          else
            motorVariableL := motorVariableR := 9    'go straight 
    
    {PUB Test_Values | i
    
        repeat i from 1 to 9
          motorVariableL := motorVariableR :=(i)
          waitcnt(clkfreq*3+cnt)            
                                     }
    PUB ForLeft  : result
    
        LS := motorVariableL
        result := LS          
    
    PUB ForRight : result 
    
        RS := motorVariableR
        result := RS      
    
    @GordonMcComb, I went to the bookstore but I was only able to get a copy of ROBOT mag. I'll get a copy of SERVO
  • rjo__rjo__ Posts: 2,114
    edited 2013-03-27 12:06
    Larry,

    You aren't the only one having the problem. Everyone else is too shy to ask:)

    In your original post, you say that what you are trying to do is get your bot to go in the direction that is most open. But your code isn't looking for the direction that is most open.

    Why don't you find the largest value returned by the ping sensors, turn a little in that direction. Check again, etc. Remembering the greatest value found. When your bot is done looking, go back to that direction and proceed forward.


    Rich
  • rjo__rjo__ Posts: 2,114
    edited 2013-03-27 12:13
    Of course... then you have to decide when to stop traveling in that direction... continue finding the maximum value and when that value corresponds to a different direction. Stop and do it all again.

    Rich
  • ratronicratronic Posts: 1,451
    edited 2013-03-27 12:47
    Larry looking at your code it looks as if you use a single Ping (on a servo?) and two continuous rotation servos. Here is some code I had started with the robot in my avatar that is supposed to go forward until it comes across something less than 27 centimeters then backs up and stops, then looks right and left then turns toward the direction with the greater distance and goes forward again. You would need to change the I/O port#'s in the CON section for your setup. Also you would need to fine tune the servo speed and pause amounts for your robot. If you have any questions about anything here just ask.
    Con                                                         
                                                             
      _CLKMODE = XTAL1 + PLL16X                              
      _XINFREQ = 5_000_000
      
      PINGPIN = 17     ''ping sensor
      SRVPINR = 18     ''right wheel servo
      SRVPINL = 19     ''left wheel servo
      PNGSRV  = 16     ''ping sensor servo
      STOP    = 1500   ''servo stop and center value
                 
    Var
      long dst[2]
         
    Obj                                                      
        
      echo : "ping" 
       srv : "servo32v7"
        
    Pub Main 
      srv.set(PNGSRV, STOP)            'ping looking forward
      srv.set(SRVPINL, STOP)           'wheels stop
      srv.set(SRVPINR, STOP)           '
      srv.start                        'start servo object
      waitcnt(clkfreq + cnt)           'wait one second
      
      repeat
        dst := echo.centimeters(PINGPIN)
        if dst < 27
          reverse
          pause(400)
          stop_wheels 
          sonar      
        forward
                         
    Pub Forward
      srv.set(SRVPINL, 1600)
      srv.set(SRVPINR, 1400)
    Pub Pause(milliseconds)
      milliseconds *= (clkfreq/1000)
      waitcnt(milliseconds + cnt)
       
    Pub Reverse
      srv.set(SRVPINL, 1400)
      srv.set(SRVPINR, 1600)  
    Pub Stop_Wheels
      srv.set(SRVPINL, STOP)
      srv.set(SRVPINR, STOP)
        
    Pub Turn_Left
      srv.set(SRVPINL, 1400)
      srv.set(SRVPINR, 1400)
    Pub Turn_Right
      srv.set(SRVPINL, 1600)   
      srv.set(SRVPINR, 1600)   
                         
    Pub Sonar
        
      srv.set(PNGSRV, 1000)       'right side in dst[0]
      waitcnt(clkfreq + cnt)  
      dst[0] := echo.centimeters(PINGPIN)
      srv.set(PNGSRV, 2000)       'left side in dst[1]
      waitcnt(clkfreq + cnt)    
      dst[1] := echo.centimeters(PINGPIN)   
      srv.set(PNGSRV, 1500)       'set ping back to center
      if dst[0] > dst[1]
        turn_right
        pause(400)
        stop_wheels
      else
        turn_left
        pause(400)
        stop_wheels
      waitcnt(clkfreq + cnt)
    
  • lardomlardom Posts: 1,659
    edited 2013-03-27 22:52
    I really appreciate the forum reaching out to me. I was scratching my head over this problem. I'll post again as soon as I eliminate the bugs.
  • ercoerco Posts: 20,256
    edited 2013-03-28 08:54
    @lardom: With robotics, "simple" tasks are challenging. BTW, have you tried the figure 8 yet? Once again, harder than it sounds.

    You have received many excellent suggestions already. Hope you find your solution quickly.

    The humble start of one of my many unfinished navigation experiments is shown at http://www.youtube.com/watch?v=Z_YUsDeuT-c , a BoeBot doing S-turns. The L/R turn durations are balanced 50/50 to move overall in a straight line. There is a front-mounted, stationary PING or Sharp IR ranging module measuring distance constantly. My intent is to use the sensor info to achieve graceful continuous motion instead of the more typical herky-jerky stop & start motion. As the robot does S-turns, it will sense and avoid the closest obstacle by modifying the S-turn to turn more left or right.

    I'll have to jump back on this now that I've disclosed my top secret plans before Duane or Martin_H beat me to it!
  • lardomlardom Posts: 1,659
    edited 2013-03-28 11:07
    @erco, figure eight? No, I'll be in the stands watching along with some of the others in the audience. But if there's a contest for robots that have 'hiccups' I'm in...
    BTW I know you can't reveal how you managed an S turn. It certainly looks like differential steering to me. Good work.
  • photomankcphotomankc Posts: 943
    edited 2013-03-29 06:24
    I will second the notion of behavior-based programming. It is simply a way to structure the robot's activity in a way that make the program less of a 'flying spaghetti monster' as the task gets more complicated. I would recommend the book "Robot Programming: a Practical Guide to Behavior-Based Robotics". Reading through that gave me a lot of ideas and the Propeller made many of those ideas much easier to implement as it was simple (relatively) to separate the sensing activity from the decision activity and not have one obfuscate the other.

    I know not everyone agrees with me on this but I think there is great merit in 'sub-contracting'. Offload the care and feeding of sensors to sub-processors and just query them for sensor values when needed. That way the main code is all about the priority and response to events, not bogged down in critical timing on measuring some pulse duration. In my bot, I am currently working to make the brain a RaspberryPi as it has gobs of RAM and processor speed and math capacity to run the decision logic and handle gyros, accelerometers, ect. I'll move the Propeller to the role of managing the sensors, aggregating data and pre-processing what it can. I'm also not above throwing a PICAXE at some sensor that I don't want to waste a 32bit Propeller cog to manage.

    You are correct though. Nothing about it is 'easy'. Things that you get the bot to do that will impress you to no end will be met by shoulder shrugs from the family and others. "Yeah, so... it doesn't run into the walls, big deal?". "Well, it's not SUPPOSED to fall down the stairs though right?". "I can drive my R/C car in a circle too!"
  • lardomlardom Posts: 1,659
    edited 2013-03-29 08:11
    Quote by photomankc
    ...Things that you get the bot to do that will impress you to no end will be met by shoulder shrugs from the family and others. "Yeah, so... it doesn't run into the walls, big deal?". "Well, it's not SUPPOSED to fall down the stairs though right?". "I can drive my R/C car in a circle too!"
    I'm absolutely glad this forum exists. The average person I speak to does not share my amazement at this technology. Little successes make my day.
  • kwinnkwinn Posts: 8,697
    edited 2013-03-29 11:04
    rjo__ wrote: »
    Of course... then you have to decide when to stop traveling in that direction... continue finding the maximum value and when that value corresponds to a different direction. Stop and do it all again.

    Rich

    And then you have the situation where the value in front of you becomes smaller than the value behind you, and all the side values are smaller to deal with. IOW, how do you prevent the robot going back and forth in a loop.
  • lardomlardom Posts: 1,659
    edited 2013-03-29 13:18
    Quote by kwinn
    ...how do you prevent the robot going back and forth in a loop.
    That idea is a great idea that JonnyMac helped me with. I had a bug problem with that also because the robot would overshoot the longest direction. I have to take another try at it.
    The logic is straightforward; I had the robot rotate 360° calling Ping every 30°.
    SomeVariable := 0
    
    repeat i from 1 to 12
       A := Ping 
       If A > SomeVariable
         SomeVariable := A
         LongestDirection := i
    
    If "LongestDirection" was "7", for example, I would use that as a multiplier which, in theory, should have worked. It would always exit the loop after twelve iterations but the robot often went past the correct direction. If I can make it work this time I will post it. I would like to come up with something that a few others find useful.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-03-29 18:23
    I found this video while exploring Let's Make Robots.

    He explains pretty well the benefit of having simple rules that build on each other to perform complex tasks.

    I learned a lot in the video.
  • John AbshierJohn Abshier Posts: 1,116
    edited 2013-03-29 18:34
    I've seen Dr. Anderson's (video in post #16) in person and they were impressive. Not many people are able to have both good hardware and good software.

    John Abshier
  • lardomlardom Posts: 1,659
    edited 2013-03-30 10:44
    @Duane Degn, Thanks. Exceptional tutorial.
  • garyggaryg Posts: 420
    edited 2013-03-30 18:26
    I just finished watching the Video.
    Excellent and exactly what I'm attempting to do.
    This confirms my latest platform strategy, which is differential drive.
    However, I'm now more concerned about how it will behave outside in the lawn but,
    I'll cross that bridge when I get to it.

    Thanks Lardom for starting this thread!
Sign In or Register to comment.