Laser line tracking

This forum is used for discussing hardware, software, and technical details of the AVRcam embedded system.

Laser line tracking

Postby kiteswing » Fri Jun 10, 2005 5:12 pm

I want use the AVRcamera to track a laser line in 5 meters. The questions are

1. What laser color will be more easily detected by AVRcamera, green or red?

2. I want to make the the laser detection in the daytime. Here is the filter information I found
http://nercslr.nmt.ac.uk/optics/optic.html . Which filter is most appropriate, Dichroic, Narrow/Daytime Filter, Red/Green Filters?


Thanks!
kiteswing
 
Posts: 5
Joined: Tue May 31, 2005 10:40 pm

Postby ringo42 » Thu Jun 23, 2005 9:59 am

I have just started working on tacking a laser line as well. I'm using a red laser and a red filter from scientificsonline.com. I only plan on using it inside and have only tested it out to about 3 meters but is shows up pretty well at that range. I have been looking at the source code and I'm not sure where to start. Basically all I want to do is report back the brightest pixel in each column. Theoretically this will be the laser line. Where do you suggest I try to parse the image info to look for the bright spot? Would FrameMgr_processLine be the best place?
Thanks
Ringo
ringo42
 
Posts: 2
Joined: Tue May 03, 2005 12:11 pm

Postby eddy » Thu Jun 23, 2005 3:19 pm

Wouldn't the default code return a bounding box around the laser line? Seems like that would work ok for locating the line...

Eddy
Eddy Wright
Wright Hobbies, LLC
http://www.wrighthobbies.net
eddy
 
Posts: 3
Joined: Thu Dec 02, 2004 10:47 pm
Location: Near Chicago, IL USA

Postby Ringo » Thu Jun 23, 2005 6:18 pm

eddy wrote:Wouldn't the default code return a bounding box around the laser line? Seems like that would work ok for locating the line...

Eddy


The line is too thin, I would have to at least take out the minimum width. Even then the line is brighter the closer it is, so 1 foot away it is white, but 6 feet away it is a brighter red than everythgin else, so it would be hard to set up a color to track. but I think the brightest pixle in each column would work %90 of the time. The only problem is I'm a HW guy, not a SW guy :-)
Ringo
Ringo
 
Posts: 19
Joined: Thu Jun 23, 2005 9:48 am

Postby Guest » Mon Jun 27, 2005 7:48 am

The AVRcam isn't set up to report back the "brightest" pixel in a particular row. The user configures colors of interest, and the system reports back bounding box information when a color of interest is found in a captured frame.

That being said...you may be able to set up a few different colors, such as the white you mentioned that shows up when close to the laser, or the red that shows up when you are further away from the laser, so that you can detect a rough distance to the laser line. This would still return a bounding box around the line though.

Of course, you can always tweak the code to your hearts content. It would take some pondering to figure out how to return the "brightest" pixel in a particular row, but I really think there may be a more elegant solution to the problem at hand. Can you give a better description of what exactly you are trying to do?
Guest
 

Postby Ringo » Mon Jun 27, 2005 9:14 am

What I'm doing is mounting a laser below the camera and projecting a horizontal line out. I have a red filter in from of the camera lens to make it easier to see the laser line. When the laser hits an object, the closer the object is to the camera the lower the line appears. So once I get it working I can make a calibration table and then when the camera reports back the height of the line I get a range reading. It won't be perfect but it should give a pretty good estimate of where objects are in front of the robot. I'm only going for a 10-15 foot range, and it looks like that should be do-able from my experiments so far.

My thought was to create 2 arrays the width of the number of colums, a location array and a value array. The Location array holds the row value for the brightest pixel and the value array holds the actual value. If the current pixle value is greater than the one in the "value" array then you replace it and also store the row value in the "location" arrray. Does that make sense? One thing I'm not sure of is if I should check all teh pixels or just the red ones? I guess I need to dump some data into a spreadsheet and see if the non-red pixels matter.
Does this seem like it will work to you?

Thanks,
Ringo
Ringo
 
Posts: 19
Joined: Thu Jun 23, 2005 9:48 am

Postby Ringo » Tue Jun 28, 2005 8:54 am

first silly question, I remember seeing somewhere that there should still be about 500 bytes left of RAM, is this correct? I tried to create a couple new arrays to hold my brightest pixle data but I get a compile error, is this because I'm out of ram? I added teh 2 commented lines below in Caminterface.c
unsigned char currentLineBuffer[LENGTH_OF_LINE_BUFFER];
unsigned char previousLineBuffer[LENGTH_OF_LINE_BUFFER];
//unsigned char Brightest_Row_location[LENGTH_OF_LINE_BUFFER];
//unsigned char Brightest_Row_value[LENGTH_OF_LINE_BUFFER];

and here is what I get when I try to compile:
Size before:
AVRcam.elf :
section size addr
.noinit 48 8389376
.bss 628 8388720
.data 16 8388704
.text 4572 0
.eeprom 0 8454144
.stab 1404 0
.stabstr 63 0
.debug_aranges 200 0
.debug_pubnames 1214 0
.debug_info 4299 0
.debug_abbrev 1743 0
.debug_line 5465 0
.debug_str 2259 0
Total 21911


avr-gcc -c -mmcu=atmega8 -I. -g -O1 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-ahlms=CamInterface.lst CamInterface.c -o CamInterface.o
avr-gcc -mmcu=atmega8 -I. -g -O1 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-ahlms=CamInterface.o CamInterface.o Main.o Executive.o FrameMgr.o UIMgr.o UartInterface.o I2CInterface.o CamConfig.o Utility.o DebugInterface.o CamInterfaceAsm.o --output AVRcam.elf -Wl,-Map=AVRcam.map,--cref,--section-start=.noinit=0x800300 -lm
C:\WinAVR\bin\..\lib\gcc\avr\3.4.3\..\..\..\..\avr\bin\ld.exe: section .bss [00800070 -> 00800393] overlaps section .noinit [00800300 -> 0080032f]
make.exe: *** [AVRcam.elf] Error 1

> Process Exit Code: 2

I don't understand the error. If I reduce the size of the array down to something below 28 then there is no error, but as soon as I hit 29 the error appears. Does this mean I'm out of memory, or am I doing something wrong?
Thanks
Ringo
Ringo
 
Posts: 19
Joined: Thu Jun 23, 2005 9:48 am

Postby Guest » Tue Jun 28, 2005 8:44 pm

Hi Ringo,
Ok...here is the situation. There is in fact around 500 bytes of RAM left for the user to play with. The deal with the error you are receiving is due to how the colorMap is setup in the software. The colorMap (which is a lookup table/array of 48 bytes, 16 for red, 16 for green, and 16 for blue)is specifically and purposefully placed at a memory location in RAM where the low byte of the start of the array is 0x00. In practice, the best location for this array was at 0x300. The reason this is important is because when, say, a red pixel is actually sampled in (see CamInterfaceAsm.S, in the acquirePixelBlock routine), the value of the red pixel is dumped directly into an index register (the Z register in this case). The upper byte of the Z index register is already pre-setup to point to the beginning of the colorMap. Thus, the lookup is as fast as possible because all that needs to be done is to load a value from the address pointed to by Z, and voila, the lookup table for the red pixel is returned.

The colorMap is forced to start at location 0x300 in RAM by defining a new memory section in the makefile to hold the color map (see line 101 of the makefile). But this only defines the section. In CamInterface.c, you'll see that the declaration of the colorMap is a little different:

Code: Select all
unsigned char colorMap[NUM_ELEMENTS_IN_COLOR_MAP] __attribute__ ((section (".noinit")));


This forces the colorMap to be located in the noinit section, which was forced to start at address 0x300 by the makefile (the RAM actually "starts" at 0x800000, and thus the lookup table starts at 0x800300...confusing I know).

Running "avr-nm -n AVRcam.elf" at a command line (DOS or linux) will show the actual locations of all objects in memory. You'll see that the bss section (normal RAM) ends around 0x8002e4, and that the colorMap is then located at 0x800300. When you add in your new arrays, they are added into the bss section, which is where all normal RAM items are allocated. However, as soon as you cross over into the noinit section (with an object greater than 28 bytes or whatever), there is already an object allocated there, and whamo, compiler error.

So you're probably wondering what can be done to fix this. There are actually a couple of solutions. The easiest one is to declare your new arrays to be fit into the noinit section as well, and place them after the color map. Thus, your code should look like this:

Code: Select all
unsigned char colorMap[NUM_ELEMENTS_IN_COLOR_MAP] __attribute__ ((section (".noinit")));
unsigned char Brightest_Row_Location[NUM_ELEMENTS_IN_COLOR_MAP] __attribute__ ((section (".noinit")));
unsigned char Brightest_Row_Value[NUM_ELEMENTS_IN_COLOR_MAP] __attribute__ ((section (".noinit")));


This will force the new arrays to start after the color map, where a nice chunk of RAM is waiting to be used. Please note that you will need to initialize this memory location (the whole noinit thing means that the section is not cleared out after power up).

There are a few other ways to deal with the situation, but this is probably the cleanest/easiest for now. Again, if you are going to be using less than ~28 bytes of additional RAM in the system, you don't have to mess with this. Its only when you want to use a whole bunch more.

Hope this long-winded answer makes sense. Please don't hesitate to throw back a follow up question if needed.
Guest
 

Postby Ringo » Wed Jun 29, 2005 9:29 am

Thanks, great answer! I made the changes and now everything compiles. Now for the fun part of getting the correct values I need out to the serial port.

Where would be the best place to initial the values in my arrays? Should I do it right after declaring them, or in FrameMgr_processLine whenever FrameMgr_processLine==0?

I guess that leads to a generic C question. Is there a simple way to assign 0 to every value in an array at once? I've always just used a FOR loop, but since the CPU cycles are so sparse I don't need to waste a bunch at the beginning of every frame like that if there is a better way.

Which leads to another question. All my comparing values is likely to take more time in FrameMgr_processLine than is currently being used, will this screw things up? I guess I'm wondering if the camera waits to send the next line of data until the atmel asks for it, or does it just send it out blind and the atmel will miss it? IF it waits I guess the only thing my code will do is slow down the frame rate, which would not be a big deal, but if it hoses the data, that could be bad.
Thanks
Ringo
Thanks
Ringo
Ringo
 
Posts: 19
Joined: Thu Jun 23, 2005 9:48 am

Postby Ringo » Wed Jun 29, 2005 11:46 am

will this work to initalize the array?
memset(Brightest_Row_Location,0x00,LENGTH_OF_LINE_BUFFER*sizeof(char));

Ringo
Ringo
 
Posts: 19
Joined: Thu Jun 23, 2005 9:48 am

Postby Guest » Thu Jun 30, 2005 6:13 am

Yes, memset will work, and is usually the fastest way to clear out memory. I would advise, though, to only do this if absolutely necessary. If you have a couple of new arrays that are 100 bytes or so each, and you want to clear them out, you're talkin about a bunch of extra cycles. Depending on where you put this (i.e., when it is executed), it could possibly reduce your overall framerate. There is more time available in between frames than there is in between lines in a particular image.

Nonetheless...sounds like you may need to play around and see what works for you. As you may have noticed by reading the code, I would typically debug stuff by generating ASCII strings and sending them out the serial port (and then watch them with hyperterminal or something similar), or, for faster debugging, would toggle the two availabe i/o lines and watch them relative to each other on an oscilloscope. Not ideal, but it got the job done.

Good Luck!
Guest
 

Postby foobert » Sat Jul 02, 2005 10:01 pm

it would narrow your field of view, but if you were to mount the camera sideways, you could process your data one column at a time.
foobert
 

Postby Ringo » Sun Jul 03, 2005 1:40 pm

Would Doing a colum at a time help? Here is what I'm doing right now. It compiles but I haven't tried downloading it yet. I'm about to start looking for a downloader, do you recomend avrdude, or is there a better one?
Ringo

else if (currentState ==ST_FrameMgr_TrackingBrightFrame)
{
UIMgr_txBuffer("Ringo",5);
UIMgr_txBuffer("\n\r",2);
while(pixelCount < ACTUAL_NUM_PIXELS_IN_A_LINE)
{
if( currentLineBuffer[pixelCount] > Brightest_Row_Value[pixelCount])
{
Brightest_Row_Location[pixelCount]=trackedLineCount;
}
pixelCount++;
}
Ringo
 
Posts: 19
Joined: Thu Jun 23, 2005 9:48 am

Postby Ringo » Sun Jul 03, 2005 1:57 pm

Speaking of AVRDude, How do you use it? I downloaded it an see that it is command line driven, but can you tell me what options to use? I have the programming cable from your website.
This is my guess but I would like to be sure. (as a pn option)

-p m8 -c stk200 -i %d%n.hex

Thanks
Ringo
Ringo
 
Posts: 19
Joined: Thu Jun 23, 2005 9:48 am

Postby Guest » Fri Jul 08, 2005 7:01 am

Check out this thread, which discusses the usage of avrdude and, depending on which version you use, some simple mods to make life easier:

http://www.jrobot.net/Forums/viewtopic. ... ht=avrdude
Guest
 

Next

Return to AVRcam Embedded System

Who is online

Users browsing this forum: Google [Bot] and 15 guests

cron