OpenSteer Documentation |
|
November 11, 2004 (revised June 15, 2007 for SVN) Version 0.8.2 |
|
by Craig Reynolds Research and Development Sony Computer Entertainment America |
OpenSteer is an open source library of components to help build steering behaviors for autonomous characters in games and other kinds of multi-agent simulations. These agents may represent characters (humans, animals, alien creatures), vehicles (cars, planes, spaceships) or other kinds of mobile agents. OpenSteer was originally developed on Linux and was subsequently ported to Windows and Mac OS X.
OpenSteer provides a toolkit of steering behaviors, defined in terms of an abstract mobile agent called a vehicle. Sample code is provided, including a simple vehicle implementation and examples of combining simple steering behaviors to produce more complex behavior. In order to allow flexible integration with existing game engines OpenSteer can add its functionality by either layering or inheritance. [see "Integrating with Your Code" below] Note that OpenSteer is intended for use by programmers. It does not plug into interactive production tools, nor does it support behavior authoring by non-programmers.
In addition to the library, OpenSteer provides an interactive application called OpenSteerDemo which initially demonstrates several steering behaviors. OpenSteerDemo can also help you create novel steering behaviors, providing facilities to visualize, annotate and debug your code. OpenSteerDemo is written in C++ and uses OpenGL graphics. All OpenGL calls are segregated in one module, in case you need to substitute another graphics API.
OpenSteerDemo is based on a plug-in architecture: an empty framework into which plug-ins can be added incrementally. OpenSteerDemo comes with several sample plug-ins. [see "Sample PlugIns" below] You can easily create your own plug-ins by starting from these examples. A OpenSteerDemo plug-in specifies several generic actions required by the OpenSteerDemo framework: open, close, reset, run one simulation step, display one frame, and so on. The plug-in defines vehicle classes and manages them in simulation. It defines scene geometry in terms of obstacles, pathways and so on. Plug-ins control the camera and handle Function Keys.
OpenSteerDemo's plug-in framework allows a game AI programmer to quickly prototype behaviors during game design, and to develop behaviors before the main game engine is finished. In OpenSteer 0.8.2, OpenSteerDemo allows the user to interactively control simulation time (stop, start, single step), select the vehicle/character/agent of interest, and adjust the view and tracking behavior of the camera.
OpenSteer is distributed as open source software in accordance with the MIT License.
Warning: OpenSteer 0.8.2 is still under active development. It is not mature or stable. Its current design is subject to change and reorganization, although every attempt will be made to avoid gratuitous changes. We welcome your interest in OpenSteer and encourage experimentation. However please contact us before planning to integrate OpenSteer into any large project.
Note also that the term plug-in is currently misused here. Normally it implies that a new module can be added to an application at run time. Whereas in OpenSteer 0.8.2 the "plugging-in" must happen at application build (link) time. One would hope this was fixed in a future release (he said, hoping to avoid specific promises of future enhancements).
After installation [see "Installing OpenSteer" below] launch the OpenSteerDemo application. (On Linux, Mac or Windows you can do this by double clicking on a desktop icon. If you have downloaded the OpenSteer source code and compiled it yourself, you can also launch the application from your IDE build tools. If you use the supplied Makefile for Linux, you can execute the make run command.) When you first use OpenSteerDemo, this quick reference guide may be helpful. The application will open a single window labeled "OpenSteerDemo 0.8.2". You should see a diagrammatic 3d view of the default PlugIn. Typically you will see moving vehicles, annotation graphics and textual overlays, as shown in [Figure 1].
Eventually OpenSteerDemo may have a menu-based graphical user interface. For now it supports limited mouse-based interaction (camera view adjustment, vehicle selection) and recognizes several single key commands:
Tab | select next PlugIn |
r | restart current PlugIn |
s | select next vehicle/agent/character (or mouse-click to select) |
c | select next camera aiming mode |
f | select next preset frame rate (as-fast-as-possible, 24fps, 60fps) |
a | toggle annotation on/off |
Space | toggle between Run and Pause |
-> (right arrow) | step forward one frame |
? | print "mini help" on console (or see the quick reference guide) |
Esc | exit OpenSteerDemo |
In addition a PlugIn can provide handlers for the Function
Keys (labeled F1 through F12 on most keyboards). Type a ? to print a list of all recognized
commands, including those handled
by the current PlugIn. (There is an issue with printing [see "Known Bugs" below].)
OpenSteerDemo keeps track of a single selected agent which the camera follows. In some demos additional annotation is provided for the selected agent. The user can change selection with the mouse. Pointing the mouse near an agent will cause it to highlight (for example, in the provided 2d demos, a gray disk is drawn under it). Clicking the (left) mouse button selects the highlighted agent. OpenSteerDemo's camera (point of view) adjusts itself automatically to keep the selected vehicle in view. Several different camera aiming modes are provided:
static | fixed camera |
fixed distance offset | camera remains a fixed distance from selected vehicle |
fixed local offset | camera remains fixed in selected vehicle's local space |
straight down | camera looks at selected vehicle from directly above |
offset POV | camera looks in selected vehicle's forward direction, from a given offset in the vehicle's local space |
You can adjust the camera's view with the mouse (or whatever input device you use). OpenSteerDemo lets you adjust the camera's position relative to its aimpoint. The aimpoint is defined by camera aiming mode and is normally the (predicted future position of the) selected vehicle. To adjust the camera: hold down the keyboard's control (Ctrl) key while dragging the mouse with its left button held down. 2D mouse motion is mapped into the camera's space, rotating the camera's position around its aimpoint. This allows the camera to move on the surface of a sphere centered at the aimpoint. The radius of this sphere--the "viewing distance"--can be adjusted by dragging the mouse with the middle button held down (vertical mouse motion maps to distance). If you use a one- or two-button mouse (hence no middle button) you can adjust the radius by holding down both the Ctrl and Alt ("control-meta-") keys while dragging the mouse with its left button held down. Note that adjustments in "offset POV" camera aiming mode actually translate rather than rotate the camera position relative to the selected vehicle.
To preserve a stable view, OpenSteerDemo's camera will smoothly interpolate over changes due to: motion of the selected vehicle, mouse-based camera adjustment, or switching camera aiming modes.
OpenSteerDemo's clock provides two time streams: real time and simulation time. The redraw cycle and camera update are based on passage of real time. Simulation time normally follows real time but can also be paused, freezing simulation of vehicle motion. Pausing the simulation often helps to allow examining annotation in detail, or to interactively reposition the camera. (In the current implementation: when simulation time is paused, simulation updates continue to happen each frame, but the elapsed time ("dt") is given as zero.) The clock can be set to run in one of three modes described in the table below. You can use OpenSteerDemo's f keyboard command to cycle among several preset combinations of clock mode and target frame rate. Your PlugIn code can also set these modes using Clock methods: get/setFixedFrameRate, get/setAnimationMode, get/setVariableFrameRateMode, get/set/togglePausedState. For more detail, see Clock.h
variable frame rate | For viewing real-time simulations. Updates
run as
fast as possible. Simulation time steps are set equal to the amount of
real time elapsed since the previous update. Similar to graphics
on a PC. |
fixed target frame rate | For viewing real-time simulations. Updates are constrained to occur at multiples of a fixed frame rate (often 30 or 60 fps) by waiting until the next fame boundary. If the update takes too long, it has to wait for the second frame boundary (aka frame out or double framing). Similar to graphics on a video game console. |
animation mode |
For running fixed time step simulations,
generally not in real-time,
which may
appear to run in "slow motion". Ignores real time to produce
consistent simulation results. |
OpenSteerDemo aims to support a developer's work by providing tools and utilities that while helpful, might not be critical enough to justify writing them during a production schedule. This includes various API for drawing annotation using elements such as lines, vectors, boxes, circles, disks, spheres and text attached to the screen or positions in 3d space. A facility is provided for drawing streamers/trails which display a vehicle's recent motion then fade away. There are utilities for drawing a ground plane and highlighting vehicles in various ways. See Annotation.h and OpenSteerDemo.h for details. You can turn annotation on and off with OpenSteerDemo's a command.
OpenSteerDemo is distributed with several PlugIns intended to serve both as demonstrations of steering behaviors, and as sample code: jumping off places for you to begin developing your own steering behaviors. The current list of sample PlugIns are:Capture the Flag: a single (bluish) attacker attempts to reach a central goal while four (reddish) defenders try to intercept ("tag") the attacker before it gets to the goal. The playing field is optionally littered with obstacles. This benchmark was proposed by Marcin Chady of the Working Group on Steering of the IGDA's AI Interface Standards Committee. The obstacles are spheres, depicted by their equator. Press F1 to add an obstacle (up to 100 of them), F2 to remove one. The "game" ends when the attacker reaches the goal or a defender tags the attacker. The demo automatically restarts a few seconds later. The attacker combines three basic steering behaviors: goal seeking, evasion and obstacle avoidance. The defenders combine pursuit and obstacle avoidance. A key to "non-stupid" behavior by the attacker was to notice when there is a defender-free "corridor" between it and the goal. When found, this corridor is depicted by a green outline. In this case the attacker uses pure seek and stops evading nearby defenders. The pursuit behavior of the defenders needed to specialized so that they "knew" not to predict the motion of the attacker past its goal. The defenders do not otherwise think about global strategy, for example they don't try to place themselves between the attacker and the goal. Currently defenders ignore each other, they probably should separate or avoid collisions with each other, ideally they would coordinate their pursuit. The attacker is easily confused when several defenders converge from different directions. Obstacles are always avoided by going toward the nearer edge, as discussed in the Steering Working Group's forum, this is frequently the "wrong" direction when considering the agent's other goals. I want to revisit this later.
MapDrive: path-following through map-based obstacles using curvature-based prediction and steering. This demonstration is inspired by the DARPA Grand Challenge cross country race for autonomous vehicles. A route is defined as a series of (GPS) waypoints and a width associated with each segment between waypoints. This demo assumes sensors on-board the vehicle create a binary map classifying the surrounding terrain into drivable and not drivable. The vehicle tries to follow the route while avoiding obstacles and maximizing speed. When the vehicle finds itself in danger of collision, it "gives up" (turns yellow) and slows to a stop. If it collides with an obstacle it turns red. In both cases the simulation is restarted. (This plug-in includes two non-path-following demos of map-based obstacle avoidance. Use F1 to select among them.)
Pedestrians: 100 agents follow a path (the red line) and try not to collide with each other or two large spherical obstacles. Press F1 to add a Pedestrian and F2 to remove one. This multiagent simulation uses a spatial database to accelerate proximity queries, F3 cycles among types of proximity databases (two exist in OpenSteer 0.8.2). F4 toggles between two versions of path following: stay on the path and directed path following. The latter means to stay on the path while moving along it in a given direction. A Pedestrian's direction is reversed when reaches the end of the path. Press F5 to toggle a Pedestrian's wander component on and off.
Boids: 200 simulated flocking bird like objects. The
boids model is a simple combination of separation, alignment
and cohesion steering behaviors. Press F1 to add a Boid
and F2 to remove one. This multiagent simulation uses a spatial
database to accelerate proximity queries, F3
cycles among types of proximity databases (two exist in OpenSteer
0.8.2). The flock flies within a sphere, F4 toggles between two
boundary
conditions. One is "steer back when outside" -- when a boid
travels
outside the sphere it begins to seek
towards the center. The other is "wrap around (teleport)" --
boids that fly out of the sphere are instantly repositioned to the
opposite side of the sphere.
Soccer: this simulation of a
simple soccer game was contributed by Michael Holm of IO Interactive on July 9, 2003.
It consists of a blue and red team of 8 Players each, a green Ball and
an axis aligned bounding box
class (AABBox) used to represent the field and the two goals. As
play proceeds the PlugIn keeps score. The ball is derived from
SimpleVehicle but its vehicle-like motion is replaced by bounce
physics. Michael invites others to contribute improved Player
designs.
Multiple Pursuit: a "test fixture" for the pursue behavior. 30 pursuers chase one wandering quarry. The colored lines indicate the predicted future position of the quarry being used as a seek target by each pursuer. The colors indicate which of nine prediction cases is active. When a pursuer reaches the quarry it is "teleported" away to a random position.
Low Speed Turn: a "test fixture" for evaluating the response of a vehicle to backward-pointing steering force while moving at low speed.
One Turning Away: this was the first one, now it serves as a minimal example of a PlugIn.
Developing interesting, lifelike steering behaviors is an unique type of programming. It mixes the mathematical and algorithmic rigor of computer programming with a more artistic, aesthetic-based phase of parameter tweaking. OpenSteer is intended to allow you to focus on developing steering behaviors without having to worry about all of the required framework. This is supported through OpenSteerDemo's PlugIn mechanism. When you write a PlugIn, you need to provide only the code that is specific to your own vehicles and their steering behaviors.Currently the best source of detailed information on the PlugIn interface is in the C++ header file PlugIn.h. See particularly the commented-out meta-example called FooPlugIn. That header file defines two classes: AbstractPlugIn (a pure virtual interface class) and PlugIn which provides the base implementation. To create a new OpenSteerDemo PlugIn, you will define a new class which inherits the base implementation from PlugIn. It provides some default methods (see PlugIn.h for details) which you can overload to customize, particularly reset. You must implement six methods on your new class to fulfill the AbstractPlugIn protocol:
name | returns a character string name |
open | allocate and initialize vehicles |
close | deallocate |
update | perform one stimulation step |
redraw | do all graphics for one frame |
allVehicles | return a group of all this PlugIn's vehicles |
For a minimal working PlugIn see "One Turning Away" (opensteer/plugins/OneTurning.cpp) which defines a single vehicle with trivial behavior. LowSpeedTurn also has trivial behavior and features multiple vehicles, Boids has many vehicles, MultiplePursuit has two kinds of vehicles, Pedestrian and CaptureTheFlag are more complicated samples.
Probably the easiest way to get started on your own PlugIn is: (1) pick one of the samples that seems most closely related (2) make a renamed copy of it (3) build OpenSteerDemo (4) verify that the new PlugIn appears and has its old behavior (5) make incremental changes to the working PlugIn to create your own behavior. If you are using an IDE (an Integrated Development Environment such as Xcode or Visual Studio) you will have to add your new PlugIn's source file to your IDE project (probably by adding it as a component to the OpenSteerDemo build target). On Linux using make (or KDevelop), if you leave your PlugIn's source file in the standard directory (opensteer/plugins/) will be compiled automatically. (Ideally compiling a PlugIn should not require compiling OpenSteerDemo [see "Known Bugs" below].)
The samples in opensteer/plugins/ each define at least one new vehicle class and one new PlugIn class. A key requirement is that a single instance of the new PlugIn class be statically allocated, as in:
// define a new Vehicle
class OneTurning : public SimpleVehicle {...}
// define a new PlugIn
class OneTurningPlugIn : public PlugIn {...}
// instantiate the PlugIn
OneTurningPlugIn gOneTurningPlugIn;
The name of that global (gOneTurningPlugIn) is irrelevant, what matters is that a single instance of the new PlugIn class (OneTurningPlugIn) is allocated for the lifetime of the OpenSteerDemo application. The actual "plugging in" is handled by the constructor(/destructor) of the PlugIn base class. A class which is intended to be instantiated exactly once is sometimes called a singleton. PlugIns expect to be instantiated exactly once but do not enforce or detect violations of that policy. Because PlugIns register themselves, the samples are defined in .cpp files and there is no need for .h files. You may wish to organize your PlugIn differently, perhaps with a .h file or perhaps including one for a class of vehicle defined elsewhere.
Normally your PlugIn will define one or more classes of Vehicle. OpenSteer tries to provide a lot of flexibility in how this can be done. On the other hand, if you are just trying to get your first experiment running under OpenSteerDemo, you probably want what Devo called "freedom from choice." The easiest approach, and what all the provided samples do, is to define a new vehicle class as a specialization of SimpleVehicle. In general, all that is required to make use of the OpenSteer steering library is to support the AbstractVehicle protocol in whatever manner you see fit.
OpenSteerDemo and the provided PlugIns make use of two types defined in AbstractVehicle: AbstractVehicle::group and AbstractVehicle::iterator. These are typedefed to the names AVGroup and AVIterator. AVGroup is used whenever a group of AbstractVehicles need to be remembered or passed as a function argument. AVIterator is used to iterate over the contents of an AVGroup. These types are based on the C++ STL (Standard Template Library) parameterized types vector and const_iterator. AVGroup and AVIterator are used inside the OpenSteer library, but if you wish to avoid using STL it should be easy to replace them with your own implementation of collections and iteration.
Random notes for PlugIn writers:
Time values are currently passed as float values, measured in seconds. Perhaps there should be a more specific typedef for time.
Vec3 is the type used throughout OpenSteer to represent geometric vectors in 3d Cartesian space. Colors are currently represented as Vec3s. Perhaps there should be a more specific typedef for color.
One way to help debug or analyze your steering behaviors is to pick one vehicle and provide additional information about it, using graphical annotation or printed output. A convenient choice is OpenSteerDemo's selected vehicle: the one the camera normally follows and which can be changed with a mouse click (or the OpenSteerDemo s command). To trigger code specifically for the selected vehicle, use something like this in your vehicle's update method: if (this == OpenSteerDemo::selectedVehicle) {...}
Note: this section is preliminary and subject to change. The documentation could conceivably be out of sync with the library itself. For the Real Truth always consult the source code.
In current organization of OpenSteer, its main library of steering behaviors is contained in the class SteerLibraryMixin (defined in SteerLibrary.h). A mixin is a class with templated superclass -- it is used to add a set of methods to a given base class. [see "Integrating with Your Code" below] In this case, SteerLibraryMixin adds steering functionality to a class which supports the AbstractVehicle interface. For example, SimpleVehicle combines SteerLibraryMixin and several other utilities with AbstractVehicle. As a result, SimpleVehicle has all of the methods defined in SteerLibraryMixin, which are listed below.
Note that several of the steering behaviors will return a zero vector value (0, 0, 0) to indicate "no steering is required at this time" typically because a goal is already met. The caller can detect these cases by testing to see if the returned steering value is equal to zero: if (steering == Vec3::zero) ...
Wander behaviorSeek behaviorVec3 steerForWander (float dt);Returns a steering force for wandering behavior. The steering value is purely tangential (has no Forward component). The time step value allows wander rate to be consistent when frame times vary.
Flee behaviorVec3 steerForSeek (const Vec3& target);Returns a steering force to seek the given target location. Causes a vehicle to turn toward the target and move to it. If this behavior is used alone and unconditionally, it will cause the vehicle to pass through the target then turn around for another pass.
Path Following behaviorVec3 steerForFlee (const Vec3& target);Returns a steering force to flee from the given target location. Causes a vehicle to turn away from the target and move away from it it.
Obstacle Avoidance behaviorVec3 steerToFollowPath (const int direction,
const float predictionTime,
Pathway& path)
Vec3 steerToStayOnPath (const float predictionTime, Pathway& path)Returns a steering force to follow a given path. steerToStayOnPath just tries to keep the vehicle on the path. steerToFollowPath provides directed path following where the vehicle both stays on the path and heads in a given direction along the path, as indicated by the direction argument which should be either +1 or -1. The path defines a tube in terms of a spine and a radius , the goal is to keep a vehicle headed toward a point inside that tube. (OpenSteer 0.8.2 provides one kind of Path with a polyline spine: a series of connected line segments (see Pathway.h) and a prototype of another kind of path called GCRoute is defined in the MapDrive PlugIn.) Steering is determined based on a prediction of the vehicle's position predictionTime seconds into the future. If that predicted position is inside the pathway (and in the case of directed path following, is headed in the correct direction) this function returns a zero vector value. Otherwise it steers toward a point on the path.
Unaligned Collision Avoidance behaviorVec3 steerToAvoidObstacle (const float minTimeToCollision,
const Obstacle& obstacle);
Vec3 steerToAvoidObstacles (const float minTimeToCollision,
const ObstacleGroup& obstacles)Returns a steering force to avoid given obstacles. The obstacles can be specified as either a single Obstacle or as a ObstacleGroup (an STL Vector of Obstacle pointers). The purely lateral steering force will turn our vehicle towards a silhouette edge of the obstacle. Avoidance is required when (1) the obstacle intersects the vehicle's current path, and (2) it is in front of the vehicle, and (3) is within minTimeToCollision seconds of travel at the vehicle's current velocity. If multiple Obstacles were specified, and multiple potential collisions exist, the nearest (most urgent) one is chosen. When no avoidance is required this function returns a zero vector value. Note that the older steerToAvoidObstacle calling sequence may be changed or removed in the future.
Separation behaviorVec3 steerToAvoidNeighbors (const float minTimeToCollision,
const AVGroup& others);Returns a steering force to avoid colliding with other nearby vehicles moving in unconstrained directions. Determine which (if any) other other vehicle we would collide with first, then steers to avoid the site of that potential collision. (The current (2D) version only steers laterally, it does not speed up or slow down, as described in the GDC 1999 paper.) Returns a steering force vector of zero length if there is no impending collision.
Alignment behaviorVec3 steerForSeparation (const float maxDistance,
const float cosMaxAngle,
const AVGroup& flock);Returns a steering force to move us away from nearby boids.
Cohesion behaviorVec3 steerForAlignment (const float maxDistance,
const float cosMaxAngle,
const AVGroup& flock);Returns a steering force to align us with nearby boids.
Pursuit behaviorVec3 steerForCohesion (const float maxDistance,
const float cosMaxAngle,
const AVGroup& flock);Returns a steering force to move us towards the "center of mass" of nearby boids.
Evasion behaviorVec3 steerForPursuit (const AbstractVehicle& quarry);
Vec3 steerForPursuit (const AbstractVehicle& quarry,
const float maxPredictionTime);Returns a steering force to pursue another moving vehicle. Heads towards the predicted point of interception. An alternate version is provided to specify a ceiling on the prediction interval: aim for where the quarry will be in (say) 5 seconds, or the point of interception, whichever happens sooner.
Speed Maintenance behaviorVec3 steerForEvasion (const AbstractVehicle& menace,
const float maxPredictionTime);Returns a steering force to evade another moving vehicle. Heads away from the predicted point of interception.
Vec3 steerForTargetSpeed (const float targetSpeed);Returns a steering force to maintain a given target speed. The value will be along the vehicle's forward/backward axis and its length will be clipped to the vehicle's maxForce parameter.
Annotation "hooks"
These "do nothing" methods are defined by SteerLibraryMixin. They are called when various steering behaviors decide to take action. These hook methods are intended to be overloaded by PlugIn writers to provide graphical annotation, or other side effects. For example the Pedestrian vehicle class overloads annotateAvoidObstacle to draw annotation lines around the vehicle's obstacle avoidance corridor when an obstacle is found inside of it.// Called when steerToAvoidObstacles decides steering is required.
virtual void annotateAvoidObstacle (const float minDistanceToCollision);
// Called when steerToFollowPath decides steering is required.
virtual void annotatePathFollowing (const Vec3& future,
const Vec3& onPath,
const Vec3& target,
const float outside);
// Called when steerToAvoidCloseNeighbors decides steering is required.
virtual void annotateAvoidCloseNeighbor (const AbstractVehicle& other,
const float additionalDistance);
// Called when steerToAvoidNeighbors decides steering is required.
virtual void annotateAvoidNeighbor (const AbstractVehicle& threat,
const float steer,
const Vec3& ourFuture,
const Vec3& threatFuture);
Note: this section is so preliminary that it is really just a placeholder...
This section will eventually talk about the structure of OpenSteer's classes, and how they are designed to provide you with flexibility as you integrate OpenSteer with your existing code. It will mention that if you were writing new code, you could always base your classes on OpenSteer's. More typically you will already have an existing code base, a game engine or a procedural animation system, into which you want to integrate some of OpenSteer's facilities.
OpenSteer's classes have been designed to allow you freedom to either inherit its functionality, or to layer its functionality on top of your existing classes. The latter approach is supported by the concept of mixin classes (essentially a class with templated superclass) which allows its functionality to be "mixed in with" (or "layered on top of") your existing classes. A similar effect can be obtained by multiple inheritance of your preexisting base classes and OpenSteer's classes, but most C++ programmers prefer to avoid multiple inheritance. Many of OpenSteer's classes are defined in three parts: an abstract protocol (aka interface or pure virtual class: "AbstractLocalSpace"), an implementation expressed as a mixin ("LocalSpaceMixin") and an instantiable class made by layering the mixin on top of the abstract protocol ("LocalSpace"). For more detail see LocalSpace.h and the discussion at the top of SimpleVehicle.h
Finally OpenSteer anticipates that it may be used in class hierarchies based on either the IS-A or the HAS-A architecture. That is, you might want an agent in your game to be structured so that it IS-A OpenSteer Vehicle or you may want to structure it so that it HAS-A Vehicle as a component part. (But no sample of using an OpenSteer Vehicle in a HAS-A architecture is provided [see "Known Bugs" below].)
OpenSteer can be used several ways. You may want to simply download the OpenSteerDemo application to run the demos. You may want to browse through some of the source code over the web. You may want to download a complete copy of the source to try some informal code-tweaking experiments. Or you may be interested in joining with the community of developers actively maintaining and improving the OpenSteer software by using code from the Subversion repository.To download an executable copy of the OpenSteerDemo application, or a zip archive of the full source, visit OpenSteer's file release page at SourceForge. The OpenSteerDemo application is available as precompiled binary executables for Linux, Mac OS X, and Windows. Source code and compiled applications are grouped together by release. You can receive notifications of future releases by subscribing to a low traffic mailing list for OpenSteer announcements. The current release is OpenSteer 0.8.2 which contains these files:
OpenSteer_0_8_2_source.zip |
Full source code for OpenSteer 0.8.2 |
OpenSteerDemo_0_8_2_linux.zip |
OpenSteerDemo application (Linux .elf) |
OpenSteerDemo_0_8_2_macosx.dmg |
OpenSteerDemo application (Mac OS X .app) |
OpenSteerDemo_0_8_2_win32.zip |
OpenSteerDemo application (Windows .exe) |
Otherwise, use Subversion (SVN) to obtain the most up-to-date version of the OpenSteer source code. See this short introduction on using SVN command line tools with SourceForge.net. If you want to be a developer, or at least a serious kibitzer, or want to help by testing the newest version of the code, or frankly, as long as you feel comfortable doing a SVN checkout from SourceForge -- you should visit OpenSteer's Subversion repository and checkout the code. Subversion client software is included with Linux and Mac OS X systems. Up to date and easy to install Subversion packages for Mac OS X can be found at Martin Ott's blog. A free and easy-to-use Windows Subversion client is TortoiseSVN (instructions how to use TortoiseSVN with SourceForge.net).
On the command line check out
a local
working copy of the latest
OpenSteer code from the SVN repository (this will place the project files into the subdirectory opensteer of the current directory): svn co https://opensteer.svn.sourceforge.net/svnroot/opensteer/trunk opensteer To get all branches and published code snapshots (tags) aside the latest code version use: svn co https://opensteer.svn.sourceforge.net/svnroot/opensteer opensteer Update your local working copy with recent changes from the SVN repository (first change into the directory containing the OpenSteer project files you checked out): svn update |
Update Sourceforge.net has changed the access method for Subversion on November 32, 2006 (see https://sourceforge.net/docs/E09#notice). If you have checked out OpenSteer before this date use the following method to switch your local copy to the new access method:
|
This
is the
directory structure
of OpenSteer:
opensteer/ | main directory |
opensteer/src/ | source code (*.cpp files) |
opensteer/include/OpenSteer/ | headers (*.h files) |
opensteer/plugins/ | source for supplied OpenSteerDemo PlugIns (*.cpp files) |
opensteer/linux/ | Makefile (and KDevelop project) for building
on Linux |
opensteer/macosx/ | files for building with Xcode on Mac OS X |
opensteer/win32/ | files for building with Visual Studio on
Windows |
To
build your own copy of OpenSteer's library and application you will
need: (1) a copy of the source code, (2) copies of two external
libraries (OpenGL and GLUT)
required by OpenSteer, and (3) the
appropriate programmer's tools for your platform. The table
below lists three platforms, four build tools, and which project file to use for
each. Note that make and Xcode are
supplied free with their respective operating systems, KDevelop is available for free
download. Visual Studio
and VC++ are
available for sale. Regarding compiler versions: on Windows
please use Visual C++ 7.1
(or newer), on Linux please use GCC 3.0 (or newer), on Mac OS X if you
have Xcode you have the right compiler.
Linux |
make command:
opensteer/linux/Makefile KDevelop: opensteer/linux/OpenSteer.kdevelop |
Mac OS X |
Xcode: opensteer/macosx/OpenSteer.xcode |
Windows |
Visual Studio (Visual C++): opensteer/win32/OpenSteer.sln |
To build using an IDE (Xcode, Visual Studio or KDevelop) simply double click on the project file indicated above, then do a Full Build or Build Solution. To run the resulting application, use the IDE's Run command or double click on the OpenSteerDemo desktop icon. To use the Linux Makefile, cd to opensteer/linux/ -- build using the make command, run the application with the make run command.
Known Bugs and Missing Features
In OpenSteerDemo, it seems like you ought to be able to use the mouse to interactively adjust position and orientation of the vehicles. But you can't. Other things you can't do include interactively creating new instances of a PlugIn's vehicle types, or deleting old ones. As anyone who has tried it knows, the hardest part of creating interesting life-like behaviors is tuning the parameters. It sure would be nice if OpenSteerDemo provided mouse-driven sliders ("valuators") PlugIns could call to interactively adjust behavioral parameters.
Some of the behaviors detailed in the 1999 paper have not been implemented yet in OpenSteer. They are: offset pursuit, arrival, wall following, containment, flow field following, and leader following. Also unimplemented are behaviors which the paper mentioned in passing: explore, forage, interpose, shadow, docking, hide. Eventually OpenSteer should provide all of them.
When avoiding obstacles it looks much more sensible, efficient
and lifelike if the vehicle steers toward the nearer edge of a looming
obstacle. But obstacle avoidance is blended with other behaviors (say
with evasion, as in the Capture the Flag PlugIn) this will often steer
the vehicle into a strategically bad position. Much better to go the
"long way" around an obstacle than to go directly in to the path of
your opponent. Perhaps obstacle avoidance should take an argument
representing the steering that would be used in the absence of an
obstacle. This can be used to bias the choice of a path around the
obstacle. There is an underlying suggestion that effective blending of
behaviors cannot be cleanly separated from the behaviors themselves.
(See also Fast, Neat
and Under Control: Inverse Steering Behaviors for Physical Autonomous
Agents.)
Currently the Pedestrians always move forward at full speed and try to avoid collisions purely by turning. They should be improved so they modulate both their heading and their speed, coming to a stop if necessary to avoid a collision.
As can be seen occasionally in the Capture the Flag PlugIn, when obstacle avoidance steering behavior fails to prevent collisions (intersection of vehicle and obstacle) the obstacle avoidance behavior appears to give up: it ignores the obstacle and steers right through it.
One ought to be able to add a PlugIn to OpenSteerDemo at
runtime. [forum
thread]
Non-penetration constraints should be supported in OpenSteer so vehicles can be prevented from intersecting obstacles and other vehicles.
Current demos use either 2d vehicles on the plane or 3d vehicles in space. Opensteer should provide support for 2d vehicles on non-planar surfaces.
OpenSteer should divide cleanly into a runtime library and a demo application. It currently does not. [bug, forum thread.]
When OpenSteerDemo is launched from the desktop (say by
double-clicking on an icon) printed messages may
be lost, or at
least not be seen immediately by the user. [forum
thread]
Many of OpenSteer's component APIs (such as: Clock, Annotation
and SimpleVehicle) are not documented beyond cryptic comments in header
files. It has been suggested
that perhaps OpenSteer should use comments compatible with the Doxygen system for
generating API docs.
Stupidly, the various annotation
(deferred graphics) types
(lines, circles) are currently limited to a fixed number of
objects. OpenSteerDemo incessantly prints complaints when these limits
are exceeded.
There should be sample code (in a PlugIn) showing how to use
OpenSteer in a more traditional, non-mixin, HAS-A architecture. [forum
thread]
Besides, shouldn't all these bugs be listed in the appropriate place on SourceForge?
OpenSteer on the web at SourceForge.Net
Steering Behaviors For Autonomous Characters the GDC 1999 paper on steering behaviors, and this companion page with background, updates and Java demos.
Systems that use OpenSteer:
Intelligent Support of Interactive Manual Control: Haptic Guidance Based on a Look-Ahead Predictor by Ben Forsyth . In his Master's thesis, Ben used OpenSteer as a framework for his experiments, used path following behavior in a novel application, and invented a new and more realistic model of a steerable wheeled vehicle.
Systems similar to OpenSteer (see also this list of related simulators):
breve: a 3d Simulation Environment for Decentralized Simulations and Artificial Life
MASON
is a fast discrete-event multiagent simulation library core in
Java.
Emergent Behaviour Programming Language E.B.P.L. (2003) by Jonathan Macey describes a specialized language for programming multi-agent simulations.
Sample applications of steering behaviors (pre-OpenSteer):
Interaction with Groups of Autonomous Characters (2000) describes a interactive system featuring large group of characters based on steering behaviors, includes a video.
Video Game Play and Design: Procedural Directions (2001) includes video of the Stuart/Bird/Fish demo with a skinned articulated 3d character driven by steering behaviors.
Steering,
planning and learning, a forum thread on advanced steering
architectures which cites several recent publications.
Online resources on computational geometry:
Please feel free to contact us with
comments or suggestions.
Last update: November 11, 2004