Matrix in spin for navigation
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!
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
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.
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.
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
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
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!
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
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?
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!
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!
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!
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
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
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!
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.
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?
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!
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.