Shop OBEX P1 Docs P2 Docs Learn Events
Matrix in spin for navigation — Parallax Forums

Matrix in spin for navigation

BotdocterBotdocter Posts: 271
edited 2010-05-05 19:50 in Propeller 1
I need to make a matrix or grid in my robot code. I want to use it for navigation.
Does anyone know how to do this?

For example:

if location =(x6,y11) and Scanrange_ping < 20cm
Location(x6,y11)= 0
else
Location(x6,y11=1 '' remember this location with blocked or unblocked
Goto next sector ( x + 1 ) or ( y + 1 )

when the location is '1' the path is free and the robot can continue its way.
If it reachws the location again it has to use the old values again unless there is no object anymore.

Any help is welcome!!

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
1 Parallax Propeller Robot Control Board
1 Memsic MX2125 accelerometer/ tilt
1 Parallax Ping))) ultrasonic sensor

a few motors and a whole lot of chaos!

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2010-04-08 19:08
    The command line Spin compiler called HomeSpun does support matrices, but it's not as convenient to use as the Propeller Tool or BST. People generally implement matrices by doing the subscripting themselves. For a 10 by 10 array, you'd declare:

    VAR long Location[noparse][[/noparse] 10 * 10 ]

    Then you'd access elements at x:y by using:

    Location[noparse][[/noparse] x*10 + y ]

    Remember that subscripts are zero-based.
  • MagIO2MagIO2 Posts: 2,243
    edited 2010-04-08 22:07
    How big is the matrix?

    If you only have the values 0 and 1 it's a waste of memory to use a byte matrix. In other words, if you use bits instead, you can reduce the needed memory to 1/8th of the memory you need if using bytes.
  • BotdocterBotdocter Posts: 271
    edited 2010-04-08 22:50
    It has to be about 50 square (5x10) meters / 30cm per section. So that would be 450 sections. That should be codable by the robot. Ofcourse walls and non moving objects will be filled in the map (0) by hand.

    other options will be

    0- non moving obstacle
    1- free
    2- obstacle detected by sensor
    3- camera detection obstacle
    G- goal
    R- current position

    I have put this together for now. I had the wave front tutorial as point of reference. I don't know if it makes any sense or be helpfull at all. As i read, the sectors must be read from beginning to end so lookupz would be good for that right?

    Here's the code:
    PUB ShowList |
    
    Index Print(GetIndex(25))
    Print(GetIndex(Y=0,X=0),(Y=0,X=1),(Y=0,X=2),(Y=0,X=3),(Y=0,X=4),(Y=0,X=5),(Y=0,X=6),(Y=0,X=7),(Y=0,X=8),(Y=0,X=9),(Y=0,X=10),(Y=0,X=11),(Y=0,X=12),(Y=0,X=13),(Y=0,X=14))
    Print(GetIndex(Y=1,X=0),(Y=1,X=1),(Y=1,X=2),(Y=1,X=3),(Y=1,X=4),(Y=1,X=5),(Y=1,X=6),(Y=1,X=7),(Y=1,X=8),(Y=1,X=9),(Y=1,X=10),(Y=1,X=11),(Y=1,X=12),(Y=1,X=13),(Y=1,X=14)))
    Print(GetIndex(Y=2,X=0),(Y=2,X=1),(Y=2,X=2),(Y=2,X=3),(Y=2,X=4),(Y=2,X=5),(Y=2,X=6),(Y=2,X=7),(Y=2,X=8),(Y=2,X=9),(Y=2,X=10),(Y=2,X=11),(Y=2,X=12),(Y=2,X=13),(Y=2,X=14)))
    Print(GetIndex(Y=3,X=0),(Y=3,X=1),(Y=3,X=2),(Y=3,X=3),(Y=3,X=4),(Y=3,X=5),(Y=3,X=6),(Y=3,X=7),(Y=3,X=8),(Y=3,X=9),(Y=3,X=10),(Y=3,X=11),(Y=3,X=12),(Y=3,X=13),(Y=3,X=14)))
    Print(GetIndex(Y=4,X=0),(Y=4,X=1),(Y=4,X=2),(Y=4,X=3),(Y=4,X=4),(Y=4,X=5),(Y=4,X=6),(Y=4,X=7),(Y=4,X=8),(Y=4,X=9),(Y=4,X=10),(Y=4,X=11),(Y=4,X=12),(Y=4,X=13),(Y=4,X=14)))
    Print(GetIndex(Y=5,X=0),(Y=5,X=1),(Y=5,X=2),(Y=5,X=3),(Y=5,X=4),(Y=5,X=5),(Y=5,X=6),(Y=5,X=7),(Y=5,X=8),(Y=5,X=9),(Y=5,X=10),(Y=5,X=11),(Y=5,X=12),(Y=5,X=13),(Y=5,X=14)))
    
    PUB GetIndex(Value): Index Index := lookdown(Value: [noparse][[/noparse](Y=0,X=0)]..[noparse][[/noparse](Y=5,X=14)])
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    1 Parallax Propeller Robot Control Board
    1 Memsic MX2125 accelerometer/ tilt
    1 Parallax Ping))) ultrasonic sensor

    a few motors and a whole lot of chaos!

    Post Edited (Botdocter) : 4/9/2010 12:15:05 AM GMT
  • MagIO2MagIO2 Posts: 2,243
    edited 2010-04-09 15:04
    Ok ... let's start with good programming style:
    Instead of using hardcodes to limit the number of x and y, we define those values on top of the program as constants and always use these constants in the code. This way you keep the code flexible and when you find out that 5x10 is to small, you can easily change it:
    CON
      _CLKMODE      = XTAL1 + PLL16X                        
      _XINFREQ      = 5_000_000
      
      ' here we have the meters in x and in y direction
      ' by changing these values the field size can be changed
      X_MAX = 5
      Y_MAX = 10
      
      ' for each meter we want 3 sections ( =33,3... cm )
      ' by changing the *3 the number of sections can be changed
      X_IDX = X_MAX * 3
      Y_IDX = Y_MAX * 3
    

    Ok, now we need the array:
    DAT
      field  byte 0[noparse][[/noparse] X_IDX * Y_IDX ]
    


    Of course you can define an array in a var-section as well, but you said you want to predefine the walls of the room. So it makes more sense to have the field in a DAT section. I'll show you later how to predefine values. Currently all array-entries are set to 0. In fact I think that 0 makes more sense to represent a free field.

    And now the code to show the field and some little helpers which allow easy access to the array:
    pub main
      ShowField
     
      ' So far nothing better to do
      repeat
     
    pub ShowField | x, y
      repeat y from 0 to Y_IDX
        repeat x from 0 to X_IDX
          Print( GetField( x, y ) )
        ' here it makes sense to Print a linefeed
     
    pub GetField( x, y )
      return field[noparse][[/noparse]y*X_IDX + x]
     
    pub SetField( x, y, val )
      field[noparse][[/noparse]y*X_IDX + x]:=val
     
     
    

    Whatever your Print is. Do you want to output the map to a TV or to a terminal program?

    And here is the way to predefine the walls:

    DAT
      field byte 1[noparse][[/noparse]X_MAX]
            byte 1, 0[noparse][[/noparse] X_MAX-2 ], 1
            ' repeat the previous line Y_MAX-2 times
            ....
            byte 1[noparse][[/noparse]X_MAX]
    

    This would give you a square room with no other obstacles and walls.
    Oh ... ok ... I see ... using conatants was a good idea, but as you want to predefine the map it does not help to much with this because the number of rows which is defined by Y_MAX can't be used here. The only way to do it automatically is to do the job half at compiletime and half at runtime.

    Of course you can define each byte of the array itself, which gives you the possibility to predefine a map containing obstacles:

    DAT
     
    field byte 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
          byte 1,0,0,0,0,0,0,0,0,0,0,0,0,0,1
          byte 1,0,0,0,0,0,0,0,0,0,0,0,0,0,1
          byte 1,1,0,1,1,0,0,0,0,0,0,0,0,0,1 ' here we have sofa and table on the right
          byte 1,1,0,1,1,0,0,0,0,0,0,0,0,1,1 ' and here additionally the cupboard on the left
          byte .....
     
    



    Post Edited (MagIO2) : 4/9/2010 3:22:45 PM GMT
  • BotdocterBotdocter Posts: 271
    edited 2010-04-09 19:05
    Wow, thank you so much! Im gonna work on it tonight!

    Woohoo!

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    1 Parallax Propeller Robot Control Board
    1 Memsic MX2125 accelerometer/ tilt
    1 Parallax Ping))) ultrasonic sensor

    a few motors and a whole lot of chaos!
  • BotdocterBotdocter Posts: 271
    edited 2010-04-10 02:08
    Can you please explain me what you mean with the linefeed? do you mean a linefeed like ',(10)' or something else?

    And can you explain me how i should program the map now? is it as easy as it seems?

    If sensor < 30
    val == 1

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    1 Parallax Propeller Robot Control Board
    1 Memsic MX2125 accelerometer/ tilt
    1 Parallax Ping))) ultrasonic sensor

    a few motors and a whole lot of chaos!

    Post Edited (Botdocter) : 4/10/2010 3:39:34 AM GMT
  • MagIO2MagIO2 Posts: 2,243
    edited 2010-04-10 18:10
    Linefeed:
    My understanding of Print is that it only prints one character per call, which is the current value of the matrix. The outer repeat loop goes down line by line, the inner one goes from left to right. So, if the inner loop is finished it makes sense to print a newline-character, also called linefeed to go to the next line of the display.

    How to program the map:
    I don't know ... I already gave you an idea on how to access the map. You have GetField and SetField functions. Somehow your bot needs to know where it currently is. So, if it walks and you want to add the position to the map, you can say:

    ' robot moved, so
    ' first delete the old position marker
    SetField( x_old, y_old, 0 )
    ' and set a mark for the new position
    SetField( x_new, y_new, "R" )
    ' and remember this position for the next movement
    x_old:=x_new
    y_old:=y_new
    

    For the rest you did not give enough information. How exact does the bot know it's position? How exact can it know the direction the sensor heads to?

    If it's in the middle of a field and looks north and the sensor detects an obstacle with a distance of 15-45cm you can use something like

    SetField( x_pos, y_pos - 1, 2 )

    If the obstacle is south of the robot you do

    SetField( x_pos, y_pos + 1, 2)

    And for west and east youd say

    SetField( x_pos - 1, y_pos, 2 )
    SetField( x_pos + 1, y_pos, 2 )

    If your robot is not straight north, south, east or west and/or you also want to enter far distance obstacles into the map, things get more difficult.

    What I really don't know is how you want to use a camera? How do you want to find out the distance of an object the camera can see?
  • BotdocterBotdocter Posts: 271
    edited 2010-04-10 19:39
    Thanx that helps a lot!

    As for the camera: the cmucam seems to measure the distance. How, i dont know.
    An other option is using a ping sensor mounted next to the cam.

    For the positioning i will use wheel encoders or a mouse that wil turn in opposite direction in lineair, so it wil always point the same way and measures x and y

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    1 Parallax Propeller Robot Control Board
    1 Memsic MX2125 accelerometer/ tilt
    1 Parallax Ping))) ultrasonic sensor

    a few motors and a whole lot of chaos!
  • BotdocterBotdocter Posts: 271
    edited 2010-04-18 00:32
    The propellertool doesn't recognize the 'print' function. Do i miss something?

    pub ShowField | x, y
      repeat y from 0 to Y_IDX
        repeat x from 0 to X_IDX
          Print( GetField( x, y ) )
        ' here it makes sense to Print a linefeed
    
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    1 Parallax Propeller Robot Control Board
    1 Memsic MX2125 accelerometer/ tilt
    1 Parallax Ping))) ultrasonic sensor

    a few motors and a whole lot of chaos!
  • Mike GreenMike Green Posts: 23,101
    edited 2010-04-18 00:50
    There is no built-in print function. Most display drivers have a set of display functions, usually OUT, DEC, HEX, and BIN. OUT is for outputting a single character. DEC is for outputting a decimal value. HEX is for hexadecimal and BIN is for binary format. For example, if you use the TV_TEXT object and declare it as 'OBJ tv : "TV_TEXT"', you'd use DEC() the way you're using Print().
  • BotdocterBotdocter Posts: 271
    edited 2010-04-18 02:07
    Euhm...

    Could you help me a bit further? I need to print an array like this:

    DAT
     
    field byte 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
          byte 1,0,0,0,0,0,0,0,0,0,0,0,0,0,1
          byte 1,0,0,0,0,0,0,0,0,0,0,0,0,0,1
          byte 1,1,0,1,1,0,0,0,0,0,0,0,0,0,1 ' here we have sofa and table on the right
          byte 1,1,0,1,1,0,0,0,0,0,0,0,0,1,1 ' and here additionally the cupboard on the left
          byte .....
     
    
    



    this field/ map is updated constantly. And needs to be printed in the terminal.
    It can be the entire field at once and then updated every refreshment?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    1 Parallax Propeller Robot Control Board
    1 Memsic MX2125 accelerometer/ tilt
    1 Parallax Ping))) ultrasonic sensor

    a few motors and a whole lot of chaos!
  • BotdocterBotdocter Posts: 271
    edited 2010-04-18 21:15
    Or in other words. I want the map 19x30 (x,y) sectors to be printed in whole. Just the new values by the bot will be updated.
    And ofcourse should be visible in terminal.

    i tried this:
    PUB Print | Term
            Term.byte( GetField( x, y ), 10 )
    
    



    There is something wrong with 'Term.byte'. i tried it with DEC too but same thing.
    I attached the Main file so a reference is present.

    if any more info is needed, please let me know!

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    1 Parallax Propeller Robot Control Board
    1 Memsic MX2125 accelerometer/ tilt
    1 Parallax Ping))) ultrasonic sensor

    a few motors and a whole lot of chaos!

    Post Edited (Botdocter) : 4/18/2010 9:42:38 PM GMT
  • BotdocterBotdocter Posts: 271
    edited 2010-04-28 23:38
    Can anyone please help me out? I really don't know how to output these arrays!!

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    1 Parallax Propeller Robot Control Board
    1 Memsic MX2125 accelerometer/ tilt
    1 Parallax Ping))) ultrasonic sensor

    a few motors and a whole lot of chaos!
  • MagIO2MagIO2 Posts: 2,243
    edited 2010-04-29 21:17
    You should use other bytes. For example " " (space) for a free field "#" for a wall, and "*" for other obstacles .....
    Then you extend the array by one byte in it's width, which has to be 0 and is never changed.
    What you now have is an array of strings (each line is now a string) and can be printed easily.
    To output each line you can do

    repeat y from 0 to Y_IDX
    tv.str( @field + y* (X_IDX + 1) )

    In getField you have to take care that one line is now one byte longer.



    PS: I·did not have a look into your code yet, but I hope what I said helps.
  • VIRANDVIRAND Posts: 656
    edited 2010-05-05 09:12
    This may be of interest later regarding robot maps, when you are ready to consider
    programming this way:

    IF the terrain is mostly unnavigable AND your robot can accurately determine
    its position
    , then it can have more intelligence about the terrain by storing not a
    matrix, but only info about where it has gone or become aware of. This mostly
    involves recording the direction it was going when it moved into a new square (a
    place that would otherwise be a byte in the matrix) or when it failed to enter a new
    square. That results in a string of moves and obstacles, which gives this
    intelligence:
    1.Everywhere its been so far.
    2.Everywhere it could not go.
    3.By absence of a record, it knows if it has not been somewhere.
    4.How to go back home.
    5.A map can be made from this information which would otherwise require
    more memory than the information itself, as long as the robot cannot cover most
    of its territory. It will not use any memory for things it does not nor cannot learn.

    Remember... It only remembers places it went or failed to go by what direction
    it was traveling at the time it crossed a "grid square"
    (virtual map pixel), and it
    is potentially more intelligent with that information. Intelligent enough so that it can
    explore a very complicated maze, and be called home, and go back the quickest
    way. If not called back, and doesn't run out of memory, it can go everywhere that
    is not completely obstructed and collect enough information to get a complete map
    of where it was able to go. The map will look just like the maze, or, a miniature golf
    hole region, or the room it was left in, after the motion directions are used to draw
    that map. The robot can go home the quickest way by finding the shortest path of
    reverse directions between where it is and where it started, although it may have
    to figure out the unstored positions each move represents, which is the hardest
    thing it will have to do with the information. Its almost as simple as starting from
    the beginning of the string and following its original moves while counting its coordinates
    until it finds the arrows that point to where the robot is on its return trip, and either
    decide to choose one to backtrack, or decide if it can just go toward home (which
    is usually not the best choice in a complex maze).

    I am describing an AI that I designed a long time ago while trying to guess how drawing
    programs can fill complex shapes. One more problem involved is reassigning direction to
    a grid square already visited while on a mission to explore unvisited squares, because
    if that is not done, then the string will duplicate many revisited grid squares and waste
    very much more memory than a whole map. I hope that this idea is interesting or useful
    to you at some point, and that you may compare it to "fill shape" algorithms, to determine
    if it is more or less efficient if you (or other robot builders) may have any use for it.

    Maybe try an experiment: Use a drawing program to draw a complex maze, and then
    use the fill color feature to fill the maze with a different color. Isn't it amazing that
    the fill (or "paint") algorithm finds every single pixel inside the walls of the maze?
  • BotdocterBotdocter Posts: 271
    edited 2010-05-05 13:20
    That sounds like wave front mapping.

    See this[noparse]:http:[/noparse]//www.societyofrobots.com/programming_wavefront.shtml

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    1 Parallax Propeller Robot Control Board
    1 Memsic MX2125 accelerometer/ tilt
    1 Parallax Ping))) ultrasonic sensor

    a few motors and a whole lot of chaos!
  • MagIO2MagIO2 Posts: 2,243
    edited 2010-05-05 14:24
    No, I don't think that it sounds like wavefront. Wavefront is what you can do with the matrix (as you can see in the code examples on the webpage you mentioned).

    What virand is talking about (I suppose) is storing the path the robot went in a string like a written description on how to find the treasure:
    from X go ten steps forward turn left 90 degrees go 5 steps .....

    Just a little shorter and maybe with some additional information like the free view the robot had on a location to all directions. In the matrix you always need the memory for the matrix. In the string-case the memory usage grows as long as the robot is exploring new terrain. So, depending on the task the robot has, the one can use less memory or the other.
  • VIRANDVIRAND Posts: 656
    edited 2010-05-05 19:50
    MagIO2 got it exactly in very concise language. cool.gif
Sign In or Register to comment.