Information available from here:
Capturing and displaying images from the camera
Please report any errors that you find!
The standard reference book
Version Control
with Subversion (v1.5) has been available online by its authors,
or you may like to
download your own copy.
The book also provides a
High-Speed Tutorial.
When reading the documentation,
there is no need to focus on material describing how to initially create a
repository, and this has been done for you.
Instead,
you should just focus on the very common commands that you'll require to
get started -
checkout,
import,
update, and
commit.
Each repository has a URL from which it can be initially checked out; once
that's done, the URL is remembered for future operations.
Your team's URL will be named something like:
The following is a suggested list of commands to commence.
The lines commencing with the '#' symbol are just comments;
other lines are commands you'll enter:
Using Subversion (SVN) to manage your project
An authenticated network-accessible SVN repository has been created for
each team. It is hosted on one of the Computer Science servers and you
will need to use your DND account name and password to make your initial
connection with your team's repository.
# # Create a new directory for CS23 - you probably already have one # mkdir ~/cs23 # # Change into this directory # cd ~/cs23 # # Make your first 'connection' with your team's SVN repository. # Your exact DND name and password provide the authentication. # Note that you may need single quotes to enter any spaces and periods in your name. # svn checkout https://svn.cs.dartmouth.edu/classes/cs23pink --username 'Full D.N.D. Name' # # The above command will create a new directory for you. Change into this directory. # cd cs23pink # # You may now create and edit your project's files in this directory - # but before you commence your team should design the working layout, e.g. : # mkdir, create, edit, copy, .... # # Once you have your directory layout (partially) created, import it into # your repository. Note the -m switch to provide a log message explaining your actions: # svn import . https://svn.cs.dartmouth.edu/classes/cs23pink -m "initial import" # # If all has gone well, your initial files will be copied to the repository. # (Bravely) you may now delete them, and recover an "official" copy of them from svn: # svn checkout https://svn.cs.dartmouth.edu/classes/cs23pink/trunk . # # Throughout the project, after you've made changes to your files, update your # your copy of the project to ensure that your changes don't conflict with those of others: # svn update # # And finally commit your changes (and any merged changes with others) into the repository: # svn commit -m "removed the final bug" |
# # Use a shell environment variable to save typing: # set WWW /net/class/cs23/public_html/W09/cs23pink # # Create a new directory within your team's website: # mkdir $WWW/newdir chgrp cs23pink $WWW/newdir chmod 771 $WWW/newdir # # Add a new file to your team's website: # cp newfile.html $WWW chgrp cs23pink $WWW/newfile.html chmod 664 $WWW/newfile.html |
To save typing, and to "automate" this for all team members likely to contribute to your webpages, create a target in your project's top-level Makefile, so that the command make publish will perform all of the necessary commands.
/net/class/cs23/W09project/grc
|-- Makefile
|-- abort.gif
|-- grc.c
|-- grc.h
|-- grc.tcl
|-- landscape.gif
|-- libgrc.a
`-- src/
/net/class/cs23/W09project/garcia
|-- Makefile
|-- brainstem/
|-- brainstem.tgz
|-- cs23garcia.h
|-- libcs23garcia.a
|-- src/
`-- testprogram.c
|
INCLUDES = -I/net/class/cs23/W09project/grc LIBDIRS = -L/net/class/cs23/W09project/grc LIBS = -lgrc -ltcl -ltk -lm |
The W09project/grc directory is "open", and you are welcome to read or copy any of the files therein. However, it is recommended that you compile and link against the files in that directory (rather than your own copies) - if during the project any bugs are found, updates will be made to these "official" copies.
To connect to the Garcia robot, your grc should call GRCconnect, which receives the robot's hostname or Internet Protocol (IP) address, the TCP/IP communication port on which the robot should be listening, and a maximum timeout (in seconds):
#include "grc.h"
FILE *fp;
fp = GRCconnect( "129.170.210.z", GARCIA_PORT, 5);
if(fp == NULL) {
fprintf(stderr, "could not connect to robot within 5 seconds\n");
exit(EXIT_FAILURE);
}
// ... communicate with robot
GRCdisconnect(fp);
|
Once the connection has been established, we may use standard C functions, such as fprintf(), fgets(), fread(), fwrite(), and fclose() to perform bi-directional communication with the robot. Note that when writing to the robot you should call fflush() after each write operation to prevent the data being buffered inside grc. Note, however, that unlike disk-based I/O using FILE *, network-based I/O is more likely to fail (the robot may move out of range), and so we need to be dilligent about checking the return values of I/O functions.
| Team color | Ad-Hoc address | Registered address |
|---|---|---|
| Orange | 192.168.3.x | 129.170.210.228 |
| Red | 192.168.3.x | 129.170.210.231 |
| Blue | 192.168.3.x | 129.170.210.x |
| Black | 192.168.3.x | 129.170.210.229 |
| Yellow | 192.168.3.42 | 129.170.210.230 |
Compiling and installing software to execute on the Garcia robot
Developing software to execute on the Garcia robot is much more difficult,
and probably something quite new for many.
The processor on the robot is not a standard Intel Pentium, like our
workstations and laptops - it's an
ARM processor,
used in many embedded devices, even the iPhone.
In addition, we do not compile programs on the robots themselves,
as their capapcity is too limited to host all necessary compiler programs
and files.
Instead we compile programs for the robots on Pentium-based machines,
informing the compiler and linker that the target device uses a
different architecture.
This activity, term
So, to compile a simple program for execution on the robots,
we require a command such as:
The compilation and linking of programs that will execute on the robot,
on our Linux platform,
is rather messy.
Not only do our C files need to be cross-compiled (as described above),
but we to include many Garcia-specific header files
and link against many Garcia-specific libraries,
that scattered around a number of directories.
To simplify the process,
the Makefile
in the directory /net/class/cs23/W09project/garcia
should be used (at least as a starting point).
The directory /net/class/cs23/W09project/garcia
also contains the cs23garcia.h header file,
which declares the constants and functions
forming the robot's API for our project.
The header file should be included by all of your on-robot programs.
Once we have cross-compiled and linked our ARM-based executable,
we need to copy it to the robot.
As is typical on embedded Linux platforms,
only a single user is supported on the robots,
that user being the traditional administrator account,
or root account.
While we work on our workstations and laptops as "ourselves",
we work as root on the robots.
We are able to connect to the robots using the ssh command,
just as we do to connect between standard Unix machines,
and using the related scp command to copy files.
Of course typing in these repetitive commands becomes tedious,
and so we prefer to develop a Makefile so that we may just type
make robot and make push (or similiar)
to perform common tasks.
When you commence developing on-board programs that make use of the
Copy this shellscript to
/root/runit on your robot,
make the shellscript executable,
and then execute your
program with ./runit ./yourprogram [arguments]
The captured image has very little structure - it is just a vector of
unsigned bytes, with each byte's value (0..255) representing the
blue, green, or red intensity of each pixel. For example:
This 24-bit data format cannot be displayed by our Garcia Robot Controller GUI.
# Cross-compile a single C file:
#
/usr/local/arm/3.3.2/bin/arm-linux-gcc -o helloworld helloworld.c
#
# OK, what did we just produce?
#
file helloworld
helloworld: ELF 32-bit LSB executable, ARM, version 1, dynamically
linked (uses shared libs), for GNU/Linux 2.0.0, not stripped
# Copy our executable to the robot
#
scp helloworld root@ROBOTS-IP-ADDRESS:/tmp
enter root's password for the robot
#
# Login to the robot
#
ssh root@ROBOTS-IP-ADDRESS
enter root's password for the robot
cd /tmp
./helloworld
output of helloworld appears
exit
#!/bin/sh
if [ ! -r garcia.config ]
then
cat << EOF > garcia.config
# Configuration file for Garcia robot
# Define the serial port of the Stargate attached to the Stem
portname=tts/1
# Define the serial baud rate
baudrate = 38400
EOF
fi
LD_LIBRARY_PATH="/usr/local/acroname/brainstem/aBinary" $@
The function garciaSnapshot() takes a snapshot using the robot's
on-board camera and, on success, returns a pointer to the captured data.
All images will be the same size,
320 pixels wide, 240 pixels high, with 24 bits of color information per pixel.
Thus the size of each captured image is (320 * 240 * 3) = 230400bytes
(225KBytes).
Capturing and displaying images from the camera
data[0] is the blue intensity of pixel[0][0];
data[1] is the green intensity of pixel[0][0];
data[2] is the red intensity of pixel[0][0];
data[3] is the blue intensity of pixel[0][1];
....
Instead, we'll need to convert the representation to either the
GIF format or the
Portable
Pixel Map format with one of these functions:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#include <unistd.h>
#include <gd.h>
bool raw24bit_to_gif(FILE *outfp, uint8_t *raw, int width, int height)
{
// ENSURE THAT WE RECEIVED REASONABLE PARAMETERS
if(outfp == NULL || raw == NULL || width < 1 || height < 1)
return false;
// CREATE THE IN-MEMORY IMAGE
gdImage *im = gdImageCreateTrueColor(width, height);
if(im == NULL)
return false;
int p = 0;
for(int h=0 ; h<height ; h++)
for(int w=0 ; w<width ; w++, p+=3)
gdImageSetPixel(im, w, h,
gdImageColorResolve(im, raw[p+2], raw[p+1], raw[p]));
// WRITE THE IMAGE TO DISK AS A GIF FILE
gdImageGif(im, outfp);
// DEALLOCATE SPACE ALLOCATED HERE
gdImageDestroy(im);
return true;
}
bool raw24bit_to_ppm(FILE *outfp, uint8_t *raw, int width, int height)
{
// ENSURE THAT WE RECEIVED REASONABLE PARAMETERS
if(outfp == NULL || raw == NULL || width < 1 || height < 1)
return false;
fprintf(outfp, "P6\n%d %d\n255\n", width, height);
for(int p=0 ; p<width*height*3 ; p+=3)
fprintf(outfp, "%c%c%c", raw[p+2], raw[p+1], raw[p]);
return true;
}