Using GRL to Control FlexBot

Topics

  1. What Is GRL?
  2. Why Develop FlexBot Behaviors Using GRL?
  3. Loading the FlexBot Interface for GRL
  4. FlexBot Interface For GRL
  5. Making an Empty Behavior Workspace
  6. Compiling The GRL Program To C++
  7. Adding The NPC Files To The Behavior Space
  8. Building The Behavior DLL

What Is GRL?

GRL or "GiRL" is a high level language for writing robot control policies. GRL programs are structured like electronic circuits (or neural networks) in that they consist of networks of signals, which are the equivalents of variables. Like variables in standard programming languages, signals have types and values. GRL is strongly typed, meaning that the type of a signal can't change over time. Its value, on the other hand, is recomputed continually, so it typically changes over time. The GRL compiler performs type propagation, so you typically don't need to declare the types of your signals; The compiler figures them out.

GRL is embedded in Scheme. That means that it runs inside of Scheme; You can type GRL code at the Scheme prompt, change things you don't like, and when you're ready, have the GRL compiler compile it for you. The compiler expands all your signals, computes their types, does a lot of optimization, and spits it all as either Scheme code or some other language that you can compile for the robot of your choice.

For more information about GRL, refer to:
http://cs.northwestern.edu/academics/courses/c95-robotics/grl-primer.pdf


Why Develop FlexBot Behaviors Using GRL?

While a simple FlexBot behavior can be programmed easily and directly in C, it may be more manageable to design complex behaviors in a higher-level functional language such as GRL. Since Scheme code cannot be compiled directly into a DLL, it must first be compiled into C or C++ so that it can be built into a FlexBot behavior DLL. In order to make the method for controlling the FlexBot via GRL similar to the method for controlling a robot in GRL, a special collection of code was developed for GRL. This code allows actuators to be invoked by passing a motor vector to a drive procedure and allows sensors to be devined as signals.


Loading the FlexBot Interface for GRL

The FlexBot interface can be loaded (after GRL has been started) by loading the file "hl-bot-interface.scm". With a default setup for the bot programming system, the file will reside in the directory "C:\robots\". This defines all of the transducers and customized code (groups, signals, procedures) that will be needed to write a FlexBot behavior that can be easily compiled to C of C++. Assuming default settings, the command to load the interface will be ",load c:\robots\hl-bot-interface.scm".


FlexBot Interface For GRL

FlexBot is designed to use actuators to make the bot do things and sensors to learn about the bot and its environment.

Actuators

In GRL, control of the FlexBot is accomplished by passing a behavior to the procedure drive-hl-bot (similar to drive-base for the robots). The behavior contains an activation level and an hl-bot-vector (similar to a motor-vector). The FlexBot actuators in GRL are used as follows:

(hl-bot-vector rotation translation strafe pitch shoot jump
duck secondary weapon reload use)

Takes a rotation speed as an integer, a translation speed as an integer, a strafe speed (side-to-side movement) as an integer, a pitch speed (looking up and down) as an integer, trigger status as a boolean (#t is shoot, #f is don't shoot), whether or not to jump as a boolean (#t is jump, #f is don't jump), whether or not to duck as a boolean (#t is duck, #f is don't duck), secondary trigger status as a boolean (#t is shoot, #f is don't shoot), weapon-selection as an integer, and whether or not to reload as a boolean (#t is reload, #f is don't reload).

(drive-hl-bot behavior)
Takes a behavior and tells the bot to use the behavior's hl-bot-vector as the action for the think cycle. Multiple behaviors can also be passed to drive-hl-bot in order from highest-priority to lowest-priority.

Sensors

Because information about the bot and its environment must be obtained through calls to functions in the FlexBot DLL, the compiler must know information such as return types for sensor calls. To save the user the trouble of writing this code, the sensor calls have all been written into transducers in GRL. These transducers may be used in GRL programs to access the sensors described in the Sensors portion of this documentation. The wrappers for the sensors are listed below:

(get-left-distance range) - returns an integer
(get-right-distance range) - returns an integer
(get-center-distance range) - returns an integer
(get-vision-distance range) - returns an integer
(get_vision_sweep_distance angle range sweep interval) - returns an integer
(is-player-visible player-num) - returns a boolean
(distance-to-player player-num) - returns an integer
(yaw-to-player player-num) - returns a float
(pitch-to-player player-num) - returns a float
(get-health) - returns an integer
(get-absolute-yaw) - returns a float
(get-absolute-pitch) - returns a float
(nearest-visible-enemy) - returns an integer
(is-moving) - returns a boolean
(get-vision-distance-with-pitch angle pitch range) - returns an integer
(ammo-in-clip) - returns an integer
(primary-ammo-in-stock weapon) - returns an integer
(secondary-ammo-in-stock weapon) - returns an integer
(get-possesses-gun weapon) - returns a boolean
(get-x) - returns an integer
(get-y) - returns an integer
(get-z) - returns an integer
(get-current-weapon) - returns an integer
(is-friend player-number) - returns a boolean
(nearest-visible-teammate) - returns an integer
(nearest-item type) - returns an integer
(yaw-to-item type index) - returns a float
(distance-to-item type index) - returns an integer
(pitch-to-item type index) - returns a float
(can-get-item type index) - returns a boolean
(yaw-to-enemy_sound) - returns a float
(distance-to-enemy_sound) - returns an integer
(nearest-waypoint) - returns an integer
(yaw-to-waypoint waypoint-number) - returns a float
(distance-to-waypoint waypoint-number) - returns an integer
(pitch-to-waypoint waypoint-number) - returns a float
(nearest-infopoint type) - returns an integer
(yaw-to-infopoint infopoint-number type) - returns a float
(distance-to-infopoint infopoint-number type) - returns an integer
(pitch-to-infopoint infopoint-number type) - returns a float
(next-infopoint-to-expire type) - returns an integer
(on-a-ladder) - returns a boolean


Making an Empty Behavior Workspace

To begin building a behavior DLL, make a copy of the "BotBehavior" directory that comes with the FlexBot. This will give you a framework into which your compiled GRL code can be placed. It is important to always work on a copy of this directory so that the original template is preserved.


Compiling The GRL Program To C++

Once the GRL program has been written, it needs to be compiled to C or C++. Before GRL can be compiled to C, the c-generator package must be loaded by typing ",open c-generator". The default BotBehavior template is designed to work very easily with C++ code. The template is designed to look for files called "npc.h" and "npc.cpp" with a class named "npc" that has a public member function update(int clock). This file and associated class can be easily generated for a GRL program by using compile-to-c++. The first step is to define a signal that holds the command to drive-hl-bot on your behavior. For example, you might (define-signal foo (drive-hl-bot my-behavior)). Once this has been defined, you can use a call to (compile-to-c++ "npc" "C:/robots/my behavior/" foo) where "C:/robots/my behavior/" is the path to the directory where your empty behavior workspace for this behavior DLL resides. Assuming that there are no errors at compile-time, two files, "npc.h", and "npc.cpp" will be placed in the destination directory.


Adding The NPC Files To The Behavior Space

Although the BotBehavior template is told to expect "npc.h" and "npc.cpp" to exist, we still must manually add these files to the project after they have been compiled from GRL. (Note that this only applies to the first time that the workspace is used. If you do subsequent compilations of the same behavior this is unnecessary.) You can add the files by right-clicking on the name of the project "BotBehavior" in the FileView tab in Visual Studio and selecting "Add files…". Browse to and add the files "npc.h" and "npc.cpp".


Building The Behavior DLL

At this point, everything is in place to build the behavior DLL. The resulting behavior DLL can be given an appropriate name and destination by modifying the build paths from the menu "Project -> Settings -> Custom Build". The name of the DLL is the name that will appear in the menu when the user attempts to load the available DLL's. The default DLL name for an empty workspace is "BotBehavior.dll". The DLL can now be built by choosing "Build". The final destination of this behavior DLL needs to be the "behavior_dlls" directory within the "dlls" directory of the FlexBot directory.