The vutils library

Ian Horswill 2/10/00
Most of this code was written by Mark DePristo.  The windows port of iview was written by Rob Zubek and Chris Beckmann.  Some of the vision operators were written by Dac Le.  The GRL interfaces and the ancient C code on which the Polly and tracker systems were once based were written by Ian.

GRL data types

Images are represented in the GRL type signal as one of the following types:

Note that these are not parameterized by width or height, so width and height can't be tracked by the type system (sorry).  However, you can generally get away with looking width and height up at run-time, particularly if you do it in this initialization of your transducer.

Depth maps are, not surprisingly, type depth-map and are indexed by column number.  Regions of the depth map are represented as column-region groups.

(column-region start-column  length)
(column-region-start column-region)

GRL Operators

Vision and image processing

(grab-grayscale-frames image-width    image-height)
(grab-rgb-frames image-width    image-height)
(grab-yuv-frames image-width    image-height)
Opens frame buffer and allocates storage for a grayscale (or rgb, or yuv) image of the specified width and height.  On each cycle of the GRL code, a new image will be grabbed.
(smooth-grayscale-image image  smooth-count)
Approximates a Gaussian blurring using repeated convolution with triangle functions.   This is actually a signal procedure that's smart enough to optimize the code if smooth-count is known at compile time.  So there's no added cost of smoothing an image with a smooth-count of zero.
(dangerous-pixels-grayscale image   edge-threshold)
Runs the cheapo Polly edge detector and returns the result (a binary image).
(dangerous->depth-map dangerous-image   distance-floor)
Computes the Polly "depth map" from the binary image.  The result is of type depth-map and is actually a C-array.  It is indexed by image column and gives the image-plane height, in pixels, of the lowest dangerous pixel in that image column.  The distance-floor parameter specifies how many rows to ignore from the bottom of the image.  This is used, e.g. to keep the robot from seeing its own body as an obstacle if part of itself is in view.
(region-depth depth-map  column-region   ceiling)
Returns the minimum reading from the selected region of column regions, or ceiling, whichever is smaller.

Information display

(display-image image &optional window-title)
Returns the minimum reading from the selected region of column regions, or ceiling
(show-image image)
Macro.  Like show-values, but for images - displays the image in a window whose title is formed from the actually expression passed in for image.
(draw-vectors xy-vectors  &optional   scale  window-size  window-title  colors)
Draws a set of vectors in a window.  xy-vectors should be a vector of xy-vectors (note that this would techncally be an xv-vector whose components were two vectors);  scale, window-size, and window-title are self-explanatory; colors is an optional vector of colors in which to render the respective lines.  For example:

(define-signal foo-display
  (draw-vectors foo 1 100 "Foo"
                (if (< (magnitude foo) 50)
                    (enum color-type red)
                    (enum color-type green))))

would draw the vectors in foo, rendering the short ones in red and the long ones in green.
(show-pings &optional  scale   window-size  window-title  colors)
Draws egocentric-ping-positions.

Polly implementation

The vision pipeline for Polly-style collision avoidance is implemented by the polly package.  The pipeline is returned as a group from which all the relevant information can be accessed.  In order to make the interface to the pipeline resolution-independent, region widths are specified in percent of the screen width and distances are represented in (integer) percentages of the total height.

(polly-pipeline &key  width  height   input  edge-threshold smoothing-factor
                                                  top-margin   bottom-margin  side-margin
(color-polly-pipeline &key  width  height   input  edge-threshold  intensity-weight chroma-weight
                                                                   smoothing-factor  top-margin   bottom-margin  side-margin
Returns a group containing all the signals of the standard Polly collision avoidance algorithm.  Since there are a lot of arguments, they are specified with pseudo-Common Lisp keyword arguments.  Note that since Scheme doesn't support keywords, they are just normal symbols, and so need to be quoted when passed in.
The grayscale image signal to use as input.  If unspecified, the pipeline will open the framegrabber itself.
Desired resolution.  The default is currently 80x60.
Half-width of the smoothing kernel to use for edge detection.  Default is 2.
Edge detector threshold.  The current default is 15.
How much of the image to ignore in computing the left-, right-, and center distances.
Desired width of the left-, right-, and center-regions, expressed as a percentage of the width of the image after the side margins are removed.
(polly-input polly-pipeline)
The image signals used by the pipeline.
(polly-width polly-pipeline)
(polly-height polly-pipeline)
Image resolution used by the pipeline.
(polly-depth-map polly-pipeline)
The depth map computed by the pipeline it is indexed by image column.  Values indicate the image-plane height of the lowest edge pixel in each column.  Under normal conditions, this is a monotone function of distance.
(polly-max-distance polly-pipeline)
The maximum possible "distance" in the depth map, i.e. the height of the screen less the top- and bottom- margins.
(polly-left-region polly-pipeline)
The column-regions corresponding to the left-, right-, and center regions of the screen.
(polly-left-distance polly-pipeline)
The distances to the closest objects in the left-, right-, and center regions of the screen, expressed as integer percentages of  polly-max-distance.
(polly-left-line polly-pipeline)
Cheapo lines fit to the left-, right-, and center regions.   The lines are fit to the two endpoints of their respective regions.
(polly-left-line-fit-error polly-pipeline)
Cheapo measures of fit for the cleapo lines fit to the left-, right-, and center regions. The fit is measured by taking the average distance from the line to the depth map at four equally space points.
(show-polly polly)
Displays the raw image with the edge map as an overlay, and the left-, right-, and center-distances as colored horizontal lines
(show-polly-lines polly  &key   left-enable  right-enable  center-enable)
Displays the raw image extracted left, right, and center lines.  The enable controls determine whether they are displayed.  By default, the lines display if their fit error is less than 20 pixels.
(polly-freespace-follower polly-pipeline  gains   stopping-distance)
Returns a the standard freespace follower as a behavior.  The gains should be an rt-vector, and the stopping-distance should be an integer.

Low-level Scheme procedures

Accessing resources in the C heap

The package vutils exports the following routines for accessing named resources in the C heap.  Each procedure takes a name and a set of constructor arguments and returns the named resource.  If the resource does not already exist, it is created and a pointer to it is saved for future use.  Successive calls will then return the same object without reallocating it.

(get-frame-grabber width height)
Returns a frame grabber object configured for the specified dimensions.  If this function is called with different arguments, different objects are returned that are configured for different resolutions.  These objects can be used simultaneously.   Note that this function does not take a resource name, since it would be useless.   However, successive calls with the same arguments always return the same object.
An enumeration containing the set of low-level C image pixel types.   It is currently defined as:

(define-enumeration pixel-type (
                    yuv         ;; 24-bit
                    grayscale   ;; 8-bit
                    monochrome ;; binary,one byte/pixel
                    cdt         ;; 8-bit bitset
                    rgb         ;; 24-bit
                    nuv         ;; 24-bit

values are accessed by using the enum macro: (enum pixel-type type)
This isn't actually part of the vutils package.  It is a pseudofunction that is recognized by the GRL compiler and replaced with the name (as a quoted symbol) of the variable in which the current signal's value is stored.  It is therefore useful to pass as the name parameter to get-image, etc. since it tends to stay consistent from compilation to compilation.
(get-image name  width  height   pixel-type)
Returns an image of the specified width, height, and pixel type.
(get-image-like name  image  &optional   pixel-type)
Returns an image of the same size as image.  If no pixel-type is specified, then the type of the image is the same too.
(get-window name  width  height   title)
Returns an window of the specified width and height, and with the specified title.
(get-window-like name  image  title)
Returns an window of the same dimensions as image, and with the specified title.
Deallocates all windows managed by the resource manager.
(get-c-array name  width)
Returns C array of the specified width.
Deallocates everything managed by the resource manager.

The low level resource manager routines are found in package resource-pools, which exports:

(make-resource-pool name  constructor   destructor  lookup-proc)
Creates a new resource pool.  When resources are created, the constructor will be called with whatever arguments are passed to get-resource.   When a resource is freed, destructor will be called on it with no arguments.  When looking for resources in its alist, lookup-proc will be used.  lookup-proc should generally be assoc or assq.
(get-resource pool  name  .   constructor-args)
Returns the specified resource.  If it needs to be created, constructor-args will be used.
(deallocate-resource pool  name)
Frees the specified resource.
(deallocate-all pool)
Frees all the resources in the specified pool.
Frees all resources in all pools.

The iview graphics library

The vutils package also exports stubs for iview.  Here is a partial list of the iview functions.  Note that iview is double-buffered, so that updates do not appear on the screen until iview-show is called.

An enumeration containing the defined color pens in iview.  It's present definition is:

(define-enumeration color-type (white red green blue black))
(iview-background-color! window  color)
Sets the background color of window.
(iview-circle window  x  y  radius   color)
Draws the specified circle in the window.
(iview-clear window)
Clears the window.
(iview-draw-image window  image)
Draws the specified image in the window.
(iview-ellipse window  x  y  width   height  color)
Draws the specified (horizontal?) ellipse in the window.
(iview-line window  start-x start-y  end-x end-y  color)
Draws the specified line in the window.
(iview-overlay-opaque window  image  color)
Overlays the specified image in the window using foreground color color.   This presumably only works for binary images (i.e. image type monochrome).  This would appear to effectively just be draw-image with the option of changing the color in which the image is rendered.   Thus the term "overlay" is a misnomer.
(iview-overlay-transparent window  image   color)
Transparently overlays the specified image in the window using foreground color color.  Window pixels for which the corresponding image pixel is zero (false) are left intact.  This presumably only works for binary images (i.e. image type monochrome).
(iview-point window  x  y  color)
Draws the specified point in the window.
(iview-rectangle window  start-x start-y   end-x end-y  color)
Draws the specified rectangle in the window.
(iview-text window  start-x start-y   string  color)
Draws the specified string in the window.
(iview-show window)
Repaints the window.
(iview-y-level! window  level)
Sets the intensity with which to render nuv (intensity-normalized yuv) images in window.

In addition to the drawing functions about, the following routines can be used to create and destroy windows.  However, they should generally be avoided in favor of get-window or get-window-like.

(make-iview-driver width  height  title)
Creates an iview "driver" object.  (I don't actually know what this does).
(make-iview driver)
Creates an iview window.
(destroy-iview-driver driver)
Destroys an iview driver object.
(destroy-iview window)
Destroys an iview window.  (Although they don't seem to disappear from the screen, at least for a while).