-
Notifications
You must be signed in to change notification settings - Fork 20
Creating Algorithms (C)
C++ Guides: GAMS Primer | Creating Algorithms | Creating Platforms | Creating Threads | Creating Transports | Debugging
GAMS provides an extensible algorithms infrastructure for encoding distributed artificial intelligence. The expressiveness of the algorithm infrastructure is limited only by the functionality of the platforms that the developer has access to. In this wiki, we take a look at how to extend the BaseAlgorithm class, the features that GAMS provides to algorithm developers, and the interactions between algorithms and platforms.
To simplify the algorithm creation process, we have written a script called gams_sim_conf.pl that allows quick creation and configuration of not only new user algorithms but also custom controllers that utilize your algorithms. In this wiki, we'll walk through the process of creating and maintaining new algorithms.
Creating a new algorithm can be greatly simplified by using the gams_sim_conf.pl tool. To use the tool, decide where you want a custom project to be located. We'll refer to this as a PROGRAM_LOCATION environment variable. A good place for this might be in a folder in your home directory, say HOME/gams_examples. The following examples assume perl is installed on your computer and available in the PATH variable. If perl is installed but not in PATH, you will want to call perl on the gams_sim_conf.pl script to run it.
If you have any questions about usage of gams_sim_conf.pl, pass the script a -h or --help option for guidance and information.
Generating new algorithm in Windows command shell (cmd in Start->Run)
%GAMS_ROOT%\scripts\gams_sim_conf.pl --new-algorithm my_algorithm --path %PROGRAM_LOCATION%Generating new algorithm in Linux terminal
$GAMS_ROOT/scripts/gams_sim_conf.pl --new-algorithm my_algorithm --path $PROGRAM_LOCATIONRunning these commands will generate a new directory at PROGRAM_LOCATION. Do not create the directory beforehand. Let the tool do that to ensure it doesn't assume the appropriate infrastructure has already been generated. The tool tries to do no harm to your projects when possible, so you can add new algorithms, platforms, simulations, etc. later.
The tool will generate a number of files and a build infrastructure using the MakefileProjectCreator for portability to Windows, Linux, Mac, Android, etc. As far as editing goes, there are only three files that most users may want to edit:
PROGRAM_LOCATION/src/algorithms/my_algorithm.h
PROGRAM_LOCATION/src/algorithms/my_algorithm.cpp
PROGRAM_LOCATION/src/controller.cppThe my_algorithm class is found in the my_algorithm.h|cpp files. By default this class is a null implementation of the BaseAlgorithm class with stubs for the methods outlined in the Methods section. It also contains a factory class that allows a GAMS controller to dynamically allocate new instances of your algorithm, whenever a user needs it to run remotely. This is going to be where your algorithm is implemented, preferably as a series of non-blocking calls to platforms, other software libraries, etc.
The controller.cpp file contains a custom GAMS controller that initializes your algorithm factory class and allows users to command your robotics system or simulation to perform the algorithm. By default, this controller compiles and links to GAMS, MADARA and ACE as well as using your algorithm. Most users will not need to change it.
Generating/compiling project in Windows command shell (cmd in Start->Run)
cd %PROGRAM_LOCATION%
mwc.pl -type vc12 workspace.mwc
workspace.slnAfter opening the Visual Studio project, compile the project with the settings used during compilation of MADARA and GAMS (e.g. 64 bit, Release mode).
Generating/compiling project in Linux terminal
cd %PROGRAM_LOCATION%
mwc.pl -type gnuace workspace.mwc
makeYou can speed up compilation by call make with -j , where NUMCORES is the number of cores on your build machine. This essentially will parallelize the build process, but with a project this small, the build process is very quick (should take a few seconds).
Believe it or not, you have already just generated and compiled a GAMS algorithm with a custom controller!
The GAMS controller directly calls three algorithm methods during normal execution: analyze, plan, and execute, in that order. Developers will need to provide implementations of each of these methods, and the intentions of these methods are the following:
- analyze: Analyzes the state of the algorithm, the platform, sensor readings, knowledge, or the interactions amongst agents. Usually the results of this analysis are used to either effect better plans or to produce results that a human or another agent might find useful.
- plan: Plans the next step or a sequence of next steps. Most algorithms provided by GAMS only plan one movement at a time. However, more extensive plans are certainly possible, and we do provide some examples of this, e.g., Snake Area Coverage--so named because the pathing looks serpentine.
- execute: Executes the next planned action.
All methods should be non-blocking to allow for platform.sense (), platform.analyze (), and algorithm.analyze () to be called frequently and for updates to the knowledge base to be sent out to other agents or human overseers. If you must use blocking calls, the best way to support them is to create a polling class/infrastructure that launches a thread for the blocking operation and provides a polling mechanism for checking if the blocking operation has completed.
GAMS provides pre-configured variables based on the invocation of init_vars on the BaseController. The init_vars function provides the id of the agent along with the estimated number of processes, and this information is used to populate a set of variables in the knowledge base for usage in algorithms and platforms.
The key variables you should know about are the following:
-
self_: the Self class is a self-referencing variable based on the id of the agent.self_->agentis a container for all variables that begin withagent.{.id}in the knowledge base (where.idis the id passed in through init_vars).self_->idis an Integer container that directly maps to.idin the knowledge base. -
platform_: The BasePlatformplatform_is a pointer to the current platform (the sensors and actuators facade for controlling the platform). During the execute method for an area coverage algorithm, for instance,platform_->move (Position location)might be called to order the agent to move to a new location. Anything implemented in a platform can be accessed via this handle -
status_: Algorithm status is a set of flags that may be useful for algorithms, especially ones implemented as finite state machines. There are flags here that may be enabled to let other agents know you are deadlocked, waiting, ok, etc. -
sensors_: Sensor is a facade for representing sensor readings, typically over a geographic area. Sensors can be configured with ranges to aid with discretization of search spaces, for instance.
A factory class must be added for each new algorithm. This class must inherit from AlgorithmFactory. The only method that must be overwritten is create. The create method shall check the arguments for reasonable values. If the arguments are valid, then create shall construct the algorithm and return a pointer to it. The Land factory is an example of a factory that does not require any argument checking. The Move factory is an example of a factory that performs argument checking.
The new derived Algorithm_Factory class must be added to the Controller Algorithm Factory. There are two options to add new Algorithm_Factory classes. The first option is to add the algorithm to the list of default options in initialize_default_mappings. Resize the aliases variables to the number of commands selected for the new algorithm. Populate the variable. Add the new algorithm with the new factory. For example, here is how the Uniform Random Edge Coverage algorithm is added (ControllerAlgorithmFactory):
aliases.resize (2); // resize to the number of commands that will be valid
aliases[0] = "uniform random edge coverage"; // populate each field
aliases[1] = "urec";
add (aliases, new area_coverage::UniformRandomEdgeCoverageFactory ()); // actually add these as options
Multiple additions of the same name will overwrite previous additions.
The other option is to use the add function. This allows other algorithms to be added after the ControllerAlgorithmFactory has been created.
C++ Guides: GAMS Primer | Creating Algorithms | Creating Platforms | Creating Threads | Creating Transports | Debugging