Aria  2.8.0
ARIA Developer's Reference Manual

MobileRobots Advanced Robotics Interface for Applications (ARIA)

Copyright 2002, 2003, 2004, 2005 ActivMedia Robotics, LLC. All rights reserved.
Copyright 2006, 2007, 2008, 2009, 2010 MobileRobots Inc. All rights reserved.
Copyright 2011, 2012, 2013 Adept Technology. All rights reserved.

Contents

Additional tools in the ARIA toolbox:

Helpful information about C++ development with ARIA:

Advanced Usage:

Introduction

Welcome to ARIA, an object-oriented, robot control applications-programming interface for MobileRobots (and ActivMedia) intelligent mobile robots.

Written in the C++ language, ARIA is client-side software for easy, high-performance access to and management of the robot, as well as to the many accessory robot sensors and effectors. ARIA includes many useful utilities for general robot programming and cross-platform (Linux and Windows) programming as well.

You can access ARIA at different levels, from simply sending commands to the robot through ArRobot to development of higher-level intelligent behavior using Actions. (For a description of how to integrate parts of ARIA with your other code, see Piecemeal Use of ARIA.)

An auxiliary library called ArNetworking is also included with ARIA. ArNetworking provides an easy to use, extensible framework for communication with remote programs over a network, such as MobileEyes.

This page contains an overview of ARIA. Read this overview to become familiar with the ARIA library and how to get started using it. Click a class or function link to view its details. A selection of the most important ARIA classes is listed in Important Classes in the menu to the left, as well as Optional Classes, Device Interface Classes, Utility Classes and Predefined ArAction Classes. All classes are available in the full class list and hierarchy links on the left.

New users should view this document along with the ARIA examples, README.txt, and your robot's operating manual as well.

You can download new versions of ARIA from http://robots.mobilerobots.com/ARIA

What is ARIA? How does it relate to other MobileRobots software?

ARIA is a programming library (SDK) for C++ programmers who want to access their MobileRobots or ActivMedia platform and accessories at either a high or low level. ARIA is also for those who have already prepared robot-control software and want to deploy it on one or more MobileRobots or ActivMedia mobile robot platforms. ARIA also provides various tools useful for robot programming in general.

In addition to providing a complete robot and accessory API to developers, ARIA also serves as a foundation for other libraries providing additional capabilities: For creating applications with built-in advanced navigation routines, you can use the additional ARNL or SONARNL libraries. To communicate with the MobileEyes graphical display/control program, or for general communication over the network, you can use ArNetworking. ArNetworking is included with ARIA in the ArNetworking directory. See the ArNetworking Reference Manual for more information.

Other libraries are available as well for specialized purposes, including speech synthesis and recognition, audio stream recording, playback and network transmission, video image capture, color tracking, etc. Browse the MobileRobots support web pages http://www.activrobots.com and http://robots.mobilerobots.com for these libraries and other mobile robotics resources, including the MobileSim simulator which can be used used for programming and debugging before driving an actual robot.

Programmers working with ARIA should be familiar with using typical C++ concepts, including using classes and objects with simple inheritance, pointers, memory management, the STL containers, and the compiling and linking process. (See below for notes about accessing ARIA from Python or Java.) Experience with multiple threads is also helpful.

Read on for information about the key pieces of ARIA and how to get started. See the README.txt file for a brief practical overview of ARIA software development on Linux and Windows. Many example programs are available as well.

Java and Python

ARIA, ArNetworking, ARNL and SONARNL now work in Java and Python! Each library has a Java wrapper and a Python wrapper. This means that you can write ARIA programs in Java or Python almost as if ARIA itself was written in these languages. This wrapper is automatically generated by SWIG, and the Python and Java APIs are almost the same as the C++ library. Exceptions will be noted in this reference manual.

Read javaExamples/README.txt file for directions on how to use the Java wrapper and pythonExamples/README.txt for directions on how to use the Python wrapper, and likewise see ArNetworking/javaExamples and ArNetworking/pythonExamples for information about and examples of the ArNetworking Java and Python wrappers.

Matlab

A subset of essential robot control and accessor functions from ARIA are now also available for use in Matlab. See matlab/README.txt for instructions on how to create and use this interface, and notes on what is available and what its requirements and supported platforms are.

License and Sharing

ARIA is released under the GNU Public License, which means that the entire source code is included and may be copied. However, if you distribute any work which incorporates ARIA, you must also distribute the entire source code to that work, including ARIA with any modifications you may have made, under the same license terms. Read the included license text for details. We open-sourced ARIA under the GPL not only for your convenience, but also so that you could share your enhancements to the software with the robotics community (you can share them via the aria-users mailing list). If you wish your enhancements to make it into the ARIA baseline, you will need to assign the copyright on those changes to MobileRobots, contact aria-.nosp@m.supp.nosp@m.ort@m.nosp@m.obil.nosp@m.erobo.nosp@m.ts.c.nosp@m.om with these changes or with questions about this.

Accordingly, please do share your work, and please sign up for the exclusive ARIA-.nosp@m.user.nosp@m.s@mob.nosp@m.iler.nosp@m.obots.nosp@m..com newslist so that you can benefit from others' work, too.

For answers to frequently asked questions about what the GPL allows and requires, see http://www.gnu.org/licenses/gpl-faq.html .

On the other hand, ARIA may be also licensed for proprietary, closed-source applications. Contact sales.nosp@m.@mob.nosp@m.ilero.nosp@m.bots.nosp@m..com for details.

The ARIA Package

ARIA/

README.txt
Getting started; essential info. Includes tips on installing ARIA, rebuilding it, building example programs, and using platform development tools. Also see the README files in the examples/, advanced/, and tests/ directories.
LICENSE.txt
GPL license for redistributing ARIA or programs using ARIA
Changes.txt
Summary of changes featured in each version of ARIA
INSTALL.txt
Detailed instructions for installing ARIA on different platforms
docs/
Library reference documentation (this manual).
examples/
ARIA example programs -- a good place to start. Also see the Examples section of this reference manual; selected examples are also linked from classes and methods used by those examples.
include/
Header files for ARIA
src/
ARIA C++ source code files
params/
Robot definition (parameter) files (p3dx.p, for example). Mostly used transparently by ARIA, but can be customized if neccesary.
lib/
Win32 DLL export library (.lib) files and Linux shared library (.so) files
bin/
Win32 binaries and DLLs

Other ARIA Files of Note

Aria.sln
MS Visual C++ workspace for building ARIA libraries and examples
Aria.vcproj
MSVC++ project file used in Aria.sln for the ARIA library.
Makefile
Linux makefile for building ARIA and examples
Makefile.dep
Linux file dependency rules (used internally by Makefile)
utils/
Utility programs, used internally by MobileRobots software development, plus some file format conversion tools
ArNetworking/
Networking infrastructure library, included with ARIA, but a separate library
tests/
Test files, somewhat esoteric but useful during ARIA development
advanced/
Advanced demos and examples, not always for the faint of heart (or ARIA novice)
pythonExamples/
Information about and examples of using ARIA via Python
javaExamples/
Information about and examples of using ARIA via Java
python/
Contains ARIA Python module and other files
java/
Contains ARIA Java package and other files

Documentation and Coding Convention

ARIA follows the following coding conventions:

  1. Class names begin with "Ar" and are in mixed case.
  2. Enums and other constants either begin with a capital letter or are all in caps.
  3. Avoid preprocessor definitions whenever possible (instead using enumerations or inline methods)
  4. Member variables in classes are prefixed with 'my'.
  5. Static variables in classes are prefixed with 'our'.
  6. Member function names start with a lower case.
  7. Capitalize each word except the first one in a variable or method name; likeThisForExample
  8. All classes may be used in a multi-threaded program, either by being inherently threadsafe, or (more typically) by providing an API for protecting it by locking mutexes. See class documentation for notes on access from multiple threads.
See also
Emacs

ARIA-Robot Client-Server Relationship

For those of you who are familiar with SRI International's Saphira software and ActivMedia Robotics' mobile robots and their related technologies, the underlying client-server control architecture for the mobile platform, sensors, and accessories hasn't changed much in ARIA. It's just gotten a lot better and more accessible.

The core mobile robot "server" proceses are implemented in the Pioneer and AmigoBot Operating System firmware (ARCOS, AROS, P2OS, AmigOS, etc.), which runs on the robot's microcontroller. These proceses manage the more critical and time-sensitive low-level tasks of robot control and operation, including maintaining requested motion and heading state and estimating position from odometry, as well as acquiring sensor information (sonar and compass, for example) and driving many accessory components like the PTZ camera, TCM2 compass/inclinometer, and the Pioneer 5-DOF Arm. The robot, its microcontroller, firmware, and integrated devices (such as sonar) together are sometimes referred to as the "robot platform". The robot firmware does not, however, perform any high-level robotic tasks. Rather, it is the job of an intelligent client running on a connected PC to perform these application-level robotic control strategies and tasks, such as obstacle detection and avoidance, sensor fusion, localization, features recognition, mapping, intelligent navigation, PTZ camera control, Arm motion, and much more. ARIA's role is to support these client applications and their communcation with the robot firmware, to any devices that connect to the computer rather than the robot platform, and to remote software via a network.

The heart of ARIA is the ArRobot class. This class manages the communication cycle with the firmware, receiving and providing access to data about the robot platform's operating state, triggering tasks within that cycle and determining commands to be sent back to the robot (see Actions and Robot Synchronization Cycle). It also serves as a container for references to other ARIA objects (such as range devices) and a toolbox of general functions related to the mobile robot.

Through its Actions infrastructure, ARIA provides a powerful mechanism for combining independent behaviors to achieve coordinated motion control and intelligent guidance. With Actions, you easily implement the motion aspects of applications such as guided teleoperation, visual tracking, autonomous navigation, etc.

Other ARIA classes provide interfaces to access and control accessory sensors and devices, including operation and state reflection for sonar and laser range finders, pan-tilt units, arms, inertial navigation devices, and many others.

Robot Communication

One of the most important functions of ARIA, and one of the first and things that your application program must do, is to establish the connection between an ArRobot object instance and the robot platform operating system (firmware).

In addition to the mobile robot itself, some accessories, such as the sonar, the Pioneer Gripper, PTZ cameras, Pioneer Arm, compass, and others, are internally connected to the robot microcontroller's AUX or digital I/O lines, and use the robot connection as well (therefore the interface classes for these objects require a reference to an ArRobot object, which must be connected for the devices to work). Other accessories, such as the SICK laser, video capture cards, etc. are connected directly to the onboard computer.

There are several ways to connect a computer running ARIA to the robot's microcontroller or to a simulator. This figure provides a schematic overview of the many ARIA-robot communication options. Consult your robot Operations Manual for more information about computer-robot hardware setup and communications.

Connecting with a Robot or the Simulator

An ArRobotConnector object is used to set up and perform the connection to the robot, based on robot parameter files, and run-time configuration via command-line arguments (see Specifying Details about Robot and Device Connections). Similarly, ArLaserConnector is used to connect to laser rangefinding devices. (Other connectors are also used for other kinds of accessory devices.) ArRobotConnector and ArLaserConnector are used in most of the example programs, including simpleConnect.cpp, wander.cpp, and demo.cpp. (Some example still use the older ArSimpleConnector). ArRobotConnector will first try to connect to a simulator on a local TCP port, and if no simulator is running, it will then connect to the robot on a local serial port. This makes it easy to develop and debug your program using the simulator, then simply copy it onto the robot's computer and run without modification. ArRobotConnector also parses some command line arguments if supplied, which can explicitly specify a remote hostname and/or port to connect with via TCP, or to specify an alternate local serial port to use for robot connection, as well as other options. If a program uses ArRobotConnector, running it with the "-help" command line argument will print a list of options.

Here is an example which uses ArRobotConnector to connect the ArRobot and ArLaserConnector to connect to a laser rangefinder.

#include "Aria.h"
int main(int argc, char** argv)
{
ArArgumentParser parser(&argc, argv);
parser.loadDefaultArguments();
ArRobot robot;
ArRobotConnector robotConnector(&parser, &robot);
// Try connecting to the robot.
if(!robotConnector.connectRobot(&robot))
{
// Error!
ArLog::log(ArLog::Terse, "Error, could not connect to robot.\n");
robotConnector.logOptions();
}
// Run the ArRobot processing/task cycle thread.
robot.runAsync(true);
ArLaserConnector laserConnector(&parser, &robot, &robotConnector);
// Parse command line arguments (there may be arguments specifying
// what lasers to try to connect to)
{
}
// Try connecting to all lasers specified in the robot's parameter file
// and in command line arguments
if(!laserConnector.connectLasers())
{
ArLog::log(ArLog::Terse, "Error, could not connect to lasers.\n");
}
// Now we're connected, and the robot and laser objects are running in
// background threads reading and processing data. (You can get access
// to the ArLaser objects using ArRobot::findLaser() or
// ArRobot::getLaserMap().
...

Specifying Details about Robot and Device Connections

On any individual robot, there are many possible combinations of hardware accessories, and several options for connecting accessories to the robot and computer. The device interface and connector classes (ArRobotConnector, ArLaserConnector, etc.) need information about what devices are connected and how they are connected, especially if they vary from their defaults.

This information is obtained from two sources: ARIA's parameter file(s) for the robot, and from program runtime arguments via ArArgumentParser (which reads default program argument values from /etc/Aria.args (on Linux) and the ARIAARGS environment variable (on both Linux and Windows), then reads current program arguments from the command line).

Some examples of hardware configuration options that may need to be specified are what kinds of laser rangefinders are connected, and to which ports, laser connection and data parameters, what kind of GPS is connected and to what port (if a GPS is used). Furthermore, if you are connecting to a robot over a wireless TCP connection from an offboard computer rather than an onboard computer, you must provide a runtime command line argument giving the robot network name (and optionally port number).

Robot Parameter Files

Robot parameter files are read by ARIA after a connection to the robot is made and the robot type and individual name are obtained (see Connecting with a Robot or the Simulator). These files provide ARIA with robot-specific conversion factors and physical charactaristics, as well as accessory device connection information.

See Robot Parameter Files for more information.

Program Runtime Options

Various classes in ARIA (notably the Connector classes) use program runtime options (a/k/a command-line arguments).

See Command Line Option Summary for a summary of all the options that various classes in ARIA accept.

Arguments are provided to other ARIA classes by an ArArgumentParser object. All ARIA programs should create an ArArgumentParser, call ArArgumentParser::loadDefaultArguments() to load any arguments that appear in the /etc/Aria.args file or ARIAARGS environment variable, and provide that object to any class constructors that accept it. Once all such objects are created, you can call Aria::logOptions() to print out a summary of all relevant options (e.g. call Aria::logOptions(); and Aria::exit() if ArArgumentParser::checkHelpAndWarnUnparsed() returns true, because the user gave the –help option). Finally, call Aria::parseArgs() to cause each of them to check the ArArgumentParser for their respective arguments.

ArRobot

ArRobot is the heart of an ARIA program, acting as robot communications gateway, central manager of robot state, tool for synchronizing program-added tasks and callbacks, ArAction objects, etc.

Client Commands and Server Information Packets

Client-server communications between ARIA and a mobile robot platform or simulator use packet-based protocols. (In this context, the client is the software using ARIA to operate a robot, and the server is the robot platform's firmware.) The details of the client-server protocol can be found in your robot's Operations or Technical Manual.

ArRobot (using the ArDeviceConnection, ArRobotPacketReceiver, ArRobotPacketSender, ArRobotPacket, and ArSerialConnection classes) handles the details of constructing and sending a command packets to the robot as well as receiving and decoding the packets recieved from the robot server.

Packet Handlers

Server Information Packets (SIPs) are packets sent by the robot server containing information updates about the robot and its accessories. The standard SIP is sent by the robot to a connected client automatically every 100 milliseconds (this frequency may be configured in the firmware parameters). It contains the robot's current position and estimates, current translational and rotational speeds, sonar reading updates, battery voltage, analog and digital I/O states, and more. These data are stored and used by ArRobot's State Reflection (see State Reflection below) and are accessible via methods of the ArRobot class. (Note, within the ArRobot source code the standard SIP is also called a "motor" packet.)

Extended SIPs use the same packet format as the standard SIP, but with a different packet "type" code. Examples of extended SIPs include I/O port data, data from the gripper, or special robot data like raw encoder data. To receive extended SIPs, the client program must request them. In ARIA, this is normally done by the device interface classes (see Device and Accessory Interface Classes) when they are initialized or when the robot connection is established. You may also attach your own custom packet handlers to ArRobot using ArRobot::addPacketHandler(). You can use this to do your own additional processing of extended SIP data, or if creating an alternate implementation of a device interface class.

Command Packets

To control the robot platform, a client program sends command packets through the robot connection. This can be done using ArRobot's Motion Command Functions, using Actions, or at the most basic level, Direct Commands. Each of these methods results in command packets sent to the robot. This means that if both Actions and motion commands are used, or if independent program modules are sending motion commands, they may conflict. See Controlling the robot with Commands and Actions below for more about sending motion commands.

Robot Synchronization Cycle

The standard SIP is sent on a constant cycle, and reception of this SIP triggers a new iteration of ArRobot's synchronized task processing cycle. This cycle consists of a series of tasks, including SIP packet handling, invocation of sensor interpretation tasks, action handling and resolution, state reflection, and invocation of user tasks, in that order. Since the task cycle is (normally) triggered by the reception of each SIP (unless the robot platform begins to fails to send SIPs or the task cycle is explicitly dissasociated from the robot connection – see below), each task will be invoked in a predictable order, have the most recent data to act upon, no task will miss an opportunity to use a SIP, and as long as the tasks do not take too much time to execute, each SIP is handled as soon as possible after the robot sends it.

ArRobot_Task_Cycle.png
Overview of the ArRobot task cycle

To begin the processing cycle, call ArRobot::run() to enter the cycle synchronously, or ArRobot::runAsync() to run the cycle in a new background thread. ArRobot::stopRunning() stops the processing cycle.

ArRobot provides methods to add your own sensor-interpretation and generic user task callbacks. To add a task callback, create an ArFunctor function object (see Functors) and then add it using ArRobot::addSensorInterpTask() or ArRobot::addUserTask(). These tasks can be removed using ArRobot::remSensorInterpTask() or ArRobot::remUserTask().

ArRobot locks it's mutex (see ArRobot::lock() and ArRobot::unlock()) during each iteration of the task cycle, so your task callbacks must not lock this mutex–a deadlock will occur. (However, locks must still be used for safe access to any other thread or ArAsyncTask, such as lasers and other range devices, or ARNL's planning or localization tasks.) This mutex lock protects ArRobot data from modification by other threads (if they correctly use the lock during access), and interruption of the series of tasks. So if you access ArRobot from any other thread (including the main thread, if you used ArRobot::runAsync() to run the task cycle), you must use ArRobot::lock() and ArRobot::unlock() to lock and unlock the robot before and after any method call or use of any data in ArRobot.

It is also possible to run the processing cycle without a connection to a robot, if desired. This alternative cycle is not triggered by receiving a packet, instead it has its own steady, "chained" cycle time (default is 100 milliseconds which you may examine and reset with ArRobot::getCycleTime() and ArRobot::setCycleTime()). You may also explicitly disassociate ArRobot's processing cycle from incoming SIP processing at any time by calling ArRobot::setCycleChained() ("Chained" means that it is the end of a previous cycle that triggers the next after suitable delay to meet the desired cycle frequency). However, in doing so, you may degrade performance, as the robot's cycle will only be run every ArRobot::getCycleTime() milliseconds, and each time only the most recently read (oldest) SIP is used (even if the robot has sent more than one since the last cycle).

ArRobot's synchronization task list is ipmlemented as a tree, with five major branches. Though it is uncommon to do so, a client program may modify this tree or disable branch tasks of the tree. If a particular task is disabled, none of its children will be called. The root of the task tree can be obtained by calling ArRobot::getSyncTaskRoot(), which returns an ArSyncTask object.

Warning
A user task or sensor interpretation task must run quickly. If one or more user tasks or actions runs such that the task cycle takes too long (more that 100ms) then the performance and behavior of the robot and of ARIA-robot communications will be negatively affected. In particular, do not call any functions that could block or wait for an unknown amount of time (such as locking a mutex that could be locked for a long time by another thread) or do any long loops waiting for a condition. Long-running activity can be performed in a separate asynchronous thread (See ArASyncTask) instead, and results can be shared with the user task via storage which is protected by a mutex only during immediate reading and writing of the storage variables.

State Reflection

State reflection in the ArRobot class is the way ARIA maintains a snapshot of the robot's operating conditions and values, such as estimated pose, current velocity, battery voltage, etc. as extracted from the latest standard SIP. ArRobot methods for examining these values include ArRobot::getPose(), ArRobot::getX(), ArRobot::getY(), ArRobot::getTh(), ArRobot::getVel(), ArRobot::getRotVel(), ArRobot::getBatteryVoltage(), ArRobot::isLeftMotorStalled(), ArRobot::isRightMotorStalled(), ArRobot::getCompass(), ArRobot::getAnalogPortSelected(), ArRobot::getAnalog(), ArRobot::getDigIn(), ArRobot::getDigOut().

The standard SIP also contains sonar reading updates, which are reflected in ArRobot and examined with the methods: ArRobot::getNumSonar(), ArRobot::getSonarRange(), ArRobot::isSonarNew(), ArRobot::getSonarReading(), ArRobot::getClosestSonarRange(), ArRobot::getClosestSonarNumber(). The sonar interface class, ArSonarDevice, also receives this information (see Range Devices).

ArRobot also uses the state reflection task to send previously requested motion commands (see Motion Command Functions) to the robot, so the motion commands sent to the robot reflects those desired values set in ArRobot's state reflection by actions or motion command methods, and also so that the watchdog on the robot does not time out and disable the robot (if no motion command is set, ArCommands::PULSE is sent each cycle). You can further tune state reflection's motion command sending rate if neccesary with ArRobot::setStateReflectionRefreshTime().) If desired, you may turn the motion-control state reflector off in the ArRobot::ArRobot() constructor (set the doStateReflection parameter to false). This will cause motion command functions to only be send the command once directly to the robot whenever they are called, rather than storing the command to send each cycle.

Robot Callbacks

There are a number of useful callbacks invoked by ArRobot on connection events. You can add and remove them with the functions ArRobot::addConnectCB(), ArRobot::remConnectCB(), ArRobot::addFailedConnectCB(), ArRobot::remFailedConnectCB(), ArRobot::addDisconnectNormallyCB(), ArRobot::remDisconnectNormallyCB(), ArRobot::addDisconnectOnErrorCB(), ArRobot::remDisconnectOnErrorCB(), ArRobot::addRunExitCB(), ArRobot::remRunExitCB(). Read their individual documentation pages for details.

See also
robotConnectionCallbacks.cpp

Controlling the robot with Commands and Actions

Your ARIA client can drive the robot and run its various accessories through ArRobot's Direct Commands, Motion Commands, or through Actions.

Note
The robot's movement speed will be limited by several parameters. First, the maximum velocities, accelerations and decelerations given in ARIA's robot parameter file (.p file) (TransVelMax, RotVelMax, TransAccel, TransDecel, RotAccel, RotDecel, and for the Seekur only, LatVelMax, LatAccel and LatDecel) are used to limit motion commands sent by ARIA, if the value is nonzero. Next, the max velocities given in the robot firmware (ARCOS) configuration are used to limit motion commands recieved by the robot. All of these maximum values can be changed at runtime with the ArRobot::setTransVelMax(), ArRobot::setRotVelMax(), and for the Seekur only, ArRobot::setLatVelMax() calls. These calls change the parameters in the robot firmware, as well as in ARIA. That is, they override any maximum values given in the robot parameter file (.p file). Finally, the "Top" parameters in the firmware (ARCOS) configuration limit speeds; these cannot be changed at runtime, only using the configuration program. Most robot parameter files use 0 values as maximums, disabling ARIA's initial limiting check; however, to make the Seekur easier to initially teleoperate at safe speeds, the velocity limits in seekur.p are set. Change these limits to 0 to remove those speed limits, and use the platform's defaults, or use ArRobot's methods to change them at program runtime.

Direct Commands

At the lowest level of robot access, you may send any command packet directly to the robot or simulator platform through ArRobot. Direct commands consist of a 1-byte command number followed by none or more arguments, as defined by the robot's operating system (ARCOS, AROS, P2OS, AmigOS, etc.). For example, the command number 4, ENABLE, enables the robot's motors if accompanied by the argument 1, and disables the motors with the argument 0. Use ArRobot::com() for commands that have no argument, such as PULSE; ArRobot::comInt() for a 2-byte integer argument, signed or unsigned, such as the motors ENABLE command; ArRobot::com2Bytes() for commands that accept two individual bytes as the argument, such as the VEL2 command; and ArRobot::comStr() or ArRobot::comStrN() for a null-terminated or fixed-length string argument, respectively, such as the sonar POLLING sequencing command.

The ArCommands class contains an enum with all the direct commands; ArCommands::ENABLE, for example. Not all Direct Commands are supported by every MobileRobots robot, but unrecognized (or malformed) commands are simply ignored.

Please consult your robot's technical manual for details, such as the Chapter 6 in the Pioneer 3 Operations Manual, for client command numbers and syntax.

For most commands, a method exists in ArRobot that either sends the command immediately, or stores it for the state reflection task to send. However, the direct command methods allow you to send any unusual or special commands directly to the robot platform or simulator, without any intervening processing.

Motion Command Functions

At a level just above ArRobot's Direct Commands are the Motion Command Functions. These are explicit simple movement commands sent by ArRobot's state reflection task. For example, ArRobot::setVel() to set the translational velocity, ArRobot::setRotVel to set rotational velocity, ArRobot::setVel2() to or set each wheel speeds separately, ArRobot::setHeading() to set a global heading angle to turn to, ArRobot::move() to drive a given distance, or ArRobot::stop() to stop all motion. ArRobot also provides methods for setting speed limits beyond the limits set in the firmware configuration. These motion functions work at part of with State Reflection, and ArRobot may resend commands each cycle to try to achieve the desired state.

Be aware that a Direct or a Motion Command may conflict with controls from Actions or other upper-level processes and lead to unexpected consequences. Use ArRobot::clearDirectMotion() to cancel the overriding effect of a previously set Motion Command so that your Action is able to regain control the robot. Or limit the time a Motion Command prevents other motion actions with ArRobot::setDirectMotionPrecedenceTime(). Otherwise, the Motion Command will prevent actions forever. Use ArRobot::getDirectMotionPrecedenceTime() to see how long a Motion Command takes precedence once set.

Actions

While simple sequences motion commands can be easy to use, trying to achieve more sophisticated motion using only motion commands can quickly become difficult. To make it possible to define complex behaviors out of independent, reusable components, ARIA provides the higher-level Actions system. Actions are individual objects that independently provide motion requests which are evaluated and then combined each cycle to produce a final set of movement commands. This allows you to build complex behavior from simple building blocks for dynamic and continuous motion control.

Actions are defined by creating a subclass of the ArAction the base class which overloads the ArAction::fire() method. See the actionExample.cpp example program. ARIA also includes some useful pre-made action classes (see Predefined ArAction Classes for a list). Include these in your programs, or use them as examples when creating your own custom ArAction subclass.

Actions are attached to an ArRobot object with ArRobot::addAction(), along with a priority which determines its position in the action list. ArAction::setRobot() is called on an action object when it is added to a robot. You can override this in your action subclass. (For example, this would be useful to add a connection callback, if there were some calculations you wished to do upon connection to the robot.)

Actions are evaluated by ArRobot's action resolver in descending order of priority (highest priority first, lowest priority last) in each task cycle just prior to State Reflection. The action resolver invokes each action's fire() method, combining their desired motion commands (the ArActionDesired objects they return) to a single ArActionDesired object, which is then used in state reflection to send motion commands to the robot.

Note
Sending simple motion commands (e.g. by using ArRobot::setVel()) while actions are also active can result in conflicts between your simple motion commands and the action resolver's commands. See the discussion of Motion Command Functions above.

As the resolver is invoking each action, by it passes the current desired motion combined from the previously invoked, higher priority actions, as the currentDesired argument to fire(). This can be useful information if needed. (For example, a stall-recovery action could be programmed not to exert its motion effects if it has been pre-empted by a stop action, so this stall-recovery action would check currentDesired to see if either the "strength" is "used up" or if there is a maximum velocity, and if so, reset its own state.) However, there is no need for an action to pay attention to the currentDesired if not necessary.

Warning
An action must run quickly. If one or more actions or robot user tasks runs such that the task cycle takes too long (more that 100ms) then the performance and behavior of the robot and of ARIA-robot communications will be negatively affected. In particular, do not call any functions that could block or wait for an unknown amount of time (such as locking a mutex that could be locked for a long time by another thread) or do any long loops waiting for a condition. Long-running activity can be performed in a separate asynchronous thread (See ArASyncTask) instead, and results can be shared with the action via storage which is protected by a mutex only during immediate reading and writing of the storage variables.

Action Desired

ArActionDesired objects are used to pass desired action channel values and strengths out of an ArAction::fire() method back to the resolver. An ArActionDesired object should always be reset (ArActionDesired::reset()) before it is reused.

There are six action channels: velocity (ArActionDesired::setVel), heading (ArActionDesired::setDeltaHeading or ArActionDesired::setHeading for absolute heading), maximum forward translational velocity (ArActionDesired::setMaxVel), maximum reverse translational velocity (ArActionDesired::setMaxNegVel), and maximum rotational velocity (ArActionDesired::setMaxRotVel).

An action gives each channel a strength between 0.0, the lowest, and 1.0, the highest. Strengths are used by the resolver to compute the relative effect of the associated channel when combining multiple actions' desired movements.

The maximum velocity, maximum negative velocity, and maximum rotational velocity channels simply impose speed limits and thereby indirectly control the robot.

For more advanced usage, ArActionDesired objects can be merged (ArActionDesired::merge) and averaged (ArActionDesired::startAverage, ArActionDesired::addAverage, ArActionDesired::endAverage).

The Action Resolver

ArResolver is the base action resolver class. ArPriorityResolver is the default resolver used by ArRobot.

The resolver used by ArRobot may be changed by calling ArRobot::setResolver, if you wish to create an alternative ArResolver implementation. There may only be one resolver per ArRobot object. (Though a resolver could contain within it multiple resolvers of its own.) Note that although a robot has one particular resolver bound to it, a resolver instance is not tied to any robot.

The priority resolver works by iterating through the action list in descending priority (from greatest priority value to lowest), setting each robot movement channel (trans. velocity, heading, max. velocity, etc.) based on the contributing actions' desired values (as returned from their fire() methods) in proportion to their respective strengths as well as the actions' priorities, updating each movement channel until its strength becomes 1.0 or the action list is exhausted. Once a channel's accumulated strength reaches 1.0, no more changes may be made to that channel (this is how higher priority actions can prevent lower priority actions from changing a channel). Same-priority actions are averaged together if they both provide outputs for the same channel.

As an example, the following table illustrates at each step an action's desired value and strength for the velocity channel, and the resulting change to the resolver's final velocity channel value and strength decision, for four fictional actions (A, B, C and D):

step # action priority value of action's desired-velocity channel strength of action's desired-velocity channel current final velocity value current final velocity strength
1 A 4 -400 0.25 -400 0.25
2 B 3 -100 1.0 Combined for use in step 4
3 C 3 200 0.50
4 B&C 3 0 0.75 -100 1.0
5 D 1 500 0.50 no change no change
final result-1001.0

Notice in the example that the same-priority actions B and C are averaged before being combined with the previously computed values from step 1. The resulting combination is: ( (B desired velocity: -100) X (B velocity strength: 1.0) + (C desired velocity: 200) X (C velocity strength: 0.5) ) / 2 => (-100 + 100) / 2 => 0 Therefore actions B and C end up cancelling each other out. Combining this result with the "currentDesired" values computed in step 1 gives (step 1 desired velocity: -400) X (step 1 velocity strength: 0.25) + (step 4 desired velocity: 0) X (step 4 velocity strength: 0.75) => -100.

In this example, it turns out that at step 5, action D has no effect since the strength for this channel has reached 1.0 at step 4, before that action was considered by the resolver.

The same method is used for all of the other channels.

Predefined Actions

ARIA includes several predefined action classes. See Predefined ArAction Classes for a list. Include these in your programs, or use them as examples when creating your own custom ArAction subclass.

Movement action classes have an "ArAction" prefix and set either or both the translational velocity (setVel) and heading (setDeltaHeading and setHeading) channels to effect motion. Limiting action classes are prefixed with "ArActionLimiter" and set one or more of the maximum translational and rotational velocity channels, to slow down or prevent motion, usually based on conditions such as nearby sensor readings.

See the ArAction base class's list of subclasses.

Mixing Actions

Actions are most useful when mixed. The teleopActionsExample.cpp example program is a good example of mixing limiting and movement actions. It creates several limiting actions, including Limiter, LimiterFar, and so on, and two movement actions, joydriveAct and keydriveAct. The limiting actions have higher priority than the movement ones, thereby preventing driving if it might be potentially unsafe due to obstacles detected by sensors.

This example also illustrates fundamental, yet very powerful features of ARIA actions and how they contribute to the overall behavior of the mobile robot. Because they are individuals, contributing discretely to the movements of the robot, actions are easily reusable. For example, a limiting action that prevents the robot from crashing into a wall when translating forward, can be used, as is, in another ARIA program and have the identical effect, except that instead of driving the robot with a joystick, the new program's lower-priority movement action might use color-tracking to have the robot follow a rolling ball. The ball-following action doesn't need to know anything about the finer arts of safe navigation–the higher-priority limiting actions take care of that.

Another ARIA example program, wander.cpp demonstrates how different movement actions can be used and how they interact. The stall-recover action in wander (ArActionStallRecover) influences the robot's movements only when the motors are stalled, disabling the lower priority actions by using up all translational and rotational strength until the robot has extracted from the stall. You should also examine ArActionStallRecover.cpp in the src/ directory to see how the action changes its motion control influences based on the stall state. Also note how ArActionAvoidFront and ArActionConstantVelocity interact.

Action Groups

Action groups allow you to easily enable (activate) or disable (de-activate) a set of actions at once. You must first create an ArActionGroup attached to an ArRobot. Then, when you add an ArAction to the ArActionGroup, it is automatically added to the ArRobot, as well as to the group.

Several predefined action groups are provided by ARIA.

See also
actionGroupExample.cpp

Range Devices

Range devices (ArRangeDevice) are abstractions of sensors which detect the presence of obstacles in the space around the robot, providing a series of spatial readings over time. ARIA's range device classes transform all readings into specific points in the same two-dimensional global coordinate system. (This is the same coordinate system as ArRobot's pose).

Currently, the main ArRangeDevice implementations included with ARIA are: sonar (ArSonarDevice), laser (ArLaser and subclasses), the robot bumpers (ArBumpers), and the "table-sensing" infrared sensors of a PeopleBot (ArIRs). Camera and 3D range devices (MobileRanger devices) are supported by separate software. In addition, ArForbiddenRangeDevice is a "virtual" range device that creates range readings that border "forbidden area" and "forbidden line" regions in an ArMap, and ArRangeDeviceFilter processes the output another ArRangeDevice object in a few ways and provides the processed data through the ArRangeDevice interface. Its parameters can be modified on line through ArConfig.

ArRangeDevice holds two kinds of ArRangeBuffer objects to store readings: current and cumulative, though not all ArRangeDevice implementations supply data to the cumulative buffer. The current buffer contains the most recent set of readings; the cumulative buffer contains readings gathered over a longer period time, limited by the buffer's size (see ArRangeBuffer::setSize()).

Some range devices also provide "raw" readings, which are the original values given by the device itself. Some range devices are also considered "Planar", which means that the readings may undergo some processing to remove duplicates etc., and which include raw readings. This includes the lasers.

Range devices are connected to a specific ArRobot instance, to obtain position and other information from the robot when readings are received and stored, and also to provide a way to find all range devices attached to the robot. Some range devices use the robot connection to communicate to their device (e.g. ArSonarDevice, ArBumpers, ArIRs). Attach an ArRangeDevice to your ArRobot object with ArRobot::addRangeDevice() and remove it with ArRobot::remRangeDevice(). The list of all attached devices can be queried using ArRobot::findRangeDevice() and ArRobot::hasRangeDevice(). The list can be obtained by calling ArRobot::getRangeDeviceList().

(Note that although sonar are integrated with the robot microcontroller, and the microcontroller always sends sonar data to the robot (if the robot has sonar), you still must attach an ArSonarDevice object to the robot to use it.)

ArRangeDevice also includes some methods to help find the closest reading to the robot within a selected box, or a polar sector: ArRangeDevice::currentReadingPolar(), ArRangeDevice::currentReadingBox(), ArRangeDevice::cumulativeReadingPolar(), ArRangeDevice::cumulativeReadingBox().

ArRobot also includes similar methods to do common operations on all attached range devices, including ArRobot::checkRangeDevicesCurrentPolar(), ArRobot::checkRangeDevicesCurrentBox(), ArRobot::checkRangesDevicesCumulativePolar(), and ArRobot::checkRangeDevicesCumulativeBox() to find the closest range reading to the robot within some region.

Each range device has a mutex (Use ArRangeDevice::lockDevice() and ArRangeDevice::unlockDevice() to lock and unlock it) so that it can be accessed safely by multiple threads. For example, ArLMS2xx uses a thread to read data from a laser, but the checkRangeDevice functions in ArRobot lockDevice() so they can read the data without conflicting with ArLMS2xx's data-reading thread, then use unlockDevice() when done. See Threading for more about threading in ARIA.

Functors

Functors are used throughout ARIA. Functor is short for function pointer. A Functor lets you call a function without knowing the declaration of the function. Instead, the compiler and linker figure out how to properly call the function.

Function pointers are fully supported by the C language. C++ treats function pointers like C, but to call class methods, an instance object is required, as well as type information about the class. Therefore, ARIA contains a set of template classes to contain this information.

ARIA makes heavy use of ArFunctors as "callback" functions. To instantiate a functor, you first need to identify how many arguments the function needs and if it returns a value. Many times a pointer to the abstract ArFunctor base class is used, which can be invoked with no arguments and no return value. Subclasses are used for functions with different numbers of arguments and return values. ArFunctor1, ArFunctor2, ArRetFunctor, ArRetFunctor1, and ArRetFunctor2 for example. When invoked, the arguments may be supplied which are passed to the target function or method, and a return value may also be given. The types for the arguments and/or return value are given as template arguments.

When creating a functor object, however, you must also provide the type and instance of an object to invoke the method of; or explicitly state that the function is a class-less global function. Do this by using one of the concrete base classes of ArFunctor instead of the abstract classes: ArFunctorC, ArFunctor1C, ArFunctor2C, ArRetFunctorC, ArRetFunctor1C, ArRetFunctor2C, ArGlobalFunctor, ArGlobalFunctor1, etc.

Example:

class ExampleClass {
public:
void aFunction(int n);
};
...
ExampleClass obj;
ArFunctor1C<ExampleClass, int> functor(&obj, &ExampleClass::aFunction);
...
functor.invoke(42);

ExampleClass is a class which contains a function called aFunction(). The functor functor is declared as an ArFunctor1C, a functor which invokes a class method and takes one argument. The template parameters specify the type of the class (ExampleClass) and the type of the method argument (int). functor is then initialized with a pointer to the ExampleClass instance to call the method on, and a pointer to the class method to call. When a functor is contained within the class, it is typcially initialized in the constructor, giving this as the object instance.

A functor must be initialized with the method to call and, if a "C" functor, a class instance. An unitilialized functor will crash at runtime when invoked.

It is also possible to give values for the method arguments in the functor initialization, see ArFunctor documentation for details.

Once the functor object is created in this fashion, it can now be passed to another function or object that wants a callback functor. And the method ExampleClass::aFunction() will be called on the object obj when the functor is invoked.

To invoke a functor, simply call the invoke() function on the functor. If it takes arguments, call invoke() with those arguments. If the functor has a return value, call invokeR. The return value of the function will be passed back through the invokeR() function. If the functor was initialized with argument values, and invoke() is called without argument values, the argument values provided at initialization are passed.

Keyboard and Joystick Input

ARIA provides several classes getting live joystick and keyboard input, and action classes (see Actions) that use that input to drive the robot.

ArJoyHandler is a cross-platform interface to joystick data. It's key functions are ArJoyHandler::getButtons, ArJoyHandler::getAdjusted, ArJoyHandler::setSpeeds, and ArJoyHandler::getDoubles.

ArKeyHandler is a cross-platform interface for recieving single keystroke events (instead of buffered lines of text). It's key function is ArKeyHandler::addKeyHandler, which binds a specific key to a given functor. It contains an enum ArKeyHandler::KEY that contains values for special keys. You can also attach a key handler to a robot with ArRobot::attachKeyHandler(), which adds some default key handlers, including a handler for Escape that disconnects and exits the program (especially useful on Windows, where Ctrl-C or the terminal close box won't properly clean up). Since a PC can only have ony keyboard, ARIA keeps an ArKeyHandler pointer globally, which may be queried with Aria::getKeyHandler().

Note
if you are using Linux, creating a key handler will make the program hang if put into the background with Ctrl-Z.

ARIA provides two simple actions, ArActionKeydrive and ArActionJoydrive, to drive a robot from keyboard and joystick input. These actions are used by the teleopActionsExample.cpp example program. ARIA also provides a more flexible ArActionRatioInput, which can combine several input sources (such as keyboard, computer joystick, robot-platform (microcontroller) joystick, or teleoperation commands recieved via ArNetworking) in a more consistent and configurable manner. See the class documentation for more details.

Threading

ARIA is highly multi-threaded. This section presents some of the critical concepts behind writing threaded ARIA code.

ARIA provides a number of support classes to make it easier to write object-oriented threaded code. They are: ArASyncTask, ArCondition, ArMutex, and ArThread.

Thread-safe code mostly means proper coordination between threads when handling the same data. You want to avoid the problem of one or more threads reading or writing the data at the same time that other threads read or write the data. data. To prevent this problem from happening, the data needs to be protected with synchronization objects.

Thread Syncronizing Objects

In ARIA, the synchronization objects are ArMutex and ArCondition. ArMutex is the most useful one. ArMutex (mutex is short for mutual exclusion.) provides a wrapper around system calls (pthreads functions on Linux and CriticalSection functions on Windows) that exclude other threads from continuing while the mutex object is "locked". When threads lock a mutex while accessing shared data, it is ensured that only one thread is accessing that shared data at a time. Therefore, the proper way to use a mutex is to lock it right before accessing the shared data, and to always unlock it when done. If the mutex is not already locked, then it becomes locked and the thread continues. If the mutex is already locked by another thread, then it blocks in the lock call until the other thread unlocks it. If a mutex is never unlocked (e.g. a function returns due to an error condition without unlocking it), then any further attempts to lock it will block forever, creating a "deadlock". See the mutex example program to see how ArMutex is used. The documentation of a method may indicate whether locking is necessary before using it; in general, when using an object that may be shared by other threads, all threads using it must lock the same mutex (usually contained within the object's class with methods provided for locking and unlocking) while using the object.

ArCondition is an occasionally used utility that puts the current thread to sleep until another thread signals it to wake up and continue executing. This can be used to wait in a thread for an indefinite amount of time until some event occurs in a another thread which signals the ArCondition.

Asynchronous Task Class

ARIA provides the ArASyncTask which can be subclassed to implement a long-running thread and its state as an object. As opposed to robot-syncronized tasks, asynchronous tasks run in seperate threads. Like ArMutex, this class wraps the operating system's threading calls in a cross-platform way. Typically, an ArASyncTask will reperesent a thread that runs in a loop for the entire program.

To use ArASyncTask, derive a class from ArASyncTask and override the ArASyncTask::runThread() function. This function is automatically called within the new thread when that new thread gets created. To create and start the thread, call ArASyncTask::create(). When the ArASyncTask::runThread() function exits, the thread will exit and be destroyed. Seperate threads can request that the task exit by calling ArASyncTask::stopRunning(), and within the thread, you can check for this request with ArASyncTask::getRunningWithLock().

This class is mainly a convenience wrapper around ArThread so that you can easily create your own object that encapsulates the concept of a thread.

Global Data

The static Aria class contains miscellaneous global data in ARIA.

ARIA contains a list of all the ArRobot instances. Use the Aria::findRobot() to find a robot by name, or use Aria::getRobotList() to get a list of the robots.

Use Aria::getDirectory() to find ARIA's top-level path (Usually either C:\Program Files\MobileRobots\Aria on Windows, or /usr/local/Aria on Linux). This is useful, for instance, to locate robot parameter files for individual operational details. Use Aria::setDirectory() to change this path for the run of the program if you feel the need to override what ARIA has decided.

Call Aria::init() at program start to perform global initialization, and use Aria::exit() to exit all ARIA threads before exiting your program.

The Aria class also contains global objects for sharing configuration parameters and other information: see ArConfig and Shared Info Groups sections below.

See also
ArConfig
Shared Info Groups

Device and Accessory Interface Classes

ARIA includes classes to communicate with various kinds of devices.

(Many of these devices are optional accessories, and not all robots have them installed.)

Some are mentioned below. See Device Interface Classes for a list.

  • Range devices. See Range Devices for more about range devices.

    • The various subclasses of ArLaser are for laser rangefinder sensors. Use ArLaserConnector to automatically create and set up ArLaser objects of the appropriate types based on robot and program configuration parameters. The lasers created by ArLaserConnector will be available as ArLaser objects stored in ArRobot.
    • ArSonarDevice for Pioneer and Amigobot built-in sonar.
    • ArBumpers treats the robot's bumper switch triggers as positions for range device readings.
    • ArRangeDeviceFilter provides an ArRangeDevice interface to data from any other range device that has been filtered in different ways.
    • ArForbiddenRangeDevice is a virtual range device that returns readings indicating the edges of forbidden lines and forbidden areas from an ArMap
    • ArIRs treats triggers of a Peoplebot's infrared "table" sensors as positions for range device readings.

    devices

  • Pan/Tilt servos and camera bases. ArPTZ defines a common interface, and subclasses access specific devices, including:

    • ArVCC4 provides pan, tilt, zoom and other control of a Canon camera via the robot microcontroller's AUX serial port.
    • ArSonyPTZ provides pan, tilt, zoom and other actions of a Sony camera via the robot microcontroller's AUX serial port.
    • ArDPPTU provides control of a Directed Perceptions Pan/Tilt unit (used for stereo cameras).

  • ArAnalogGyro provides data from the optional analog gyro on Pioneer, PeopleBot, PatrolBot, PowerBot or AmigoBot. If the HasGyro parameter in the robot's internal firmware configuration is 2 (the default on most robots), then the robot automatically uses the gyro for position correction before sending its pose estimate to ARIA. However, if GyroType is 1, then create an ArAnalogGyro object to begin receiving data from the robot and allow it to apply those corrections to the position in the ArRobot object.

    The gyro also measures its own temperature as part of its operation, and ArAnalogGyro makes that value available as well.

  • ArGripper provides access to a Pioneer gripper.

  • ArP2Arm provides access to a Pioneer arm.

  • ArTCM2 provides access to an on-board TCM2 compass, if present.

  • ArACTS_1_2 communicates with the ACTS program to get object tracking information.

  • ArVersalogicIO provides access to the digital and analog I/O ports on Versalogic motherboards (Linux only). (Support depends on whether the robot has a Versalogic motherboard, and which board it has.)

  • ArSystemStatus provides data about the operating system (Linux only) such as CPU usage and wireless network signal strength.

  • ArGPS provides access to data received from a Global Positioning System device. Subclasses implement special actions required for specific devices, such as ArNovatelGPS for the NovAtel G2 and similar devices and ArTrimbleGPS for the Trimble GPS. Use ArGPSConnector to create the appropriate ArGPS device based on robot and program configuration parameters.

Some device interfaces are provided by additional libraries, as well. See those libraries for details.

Utility Classes

Some of the general-purpose utility classes included with are ArMath, ArUtil, ArTime, ArPose, ArLog, ArSectors, ArRingQueue, ArLineFinder, the GPS-related subclasses of Ar3DPoint, ArMD5Calculator (and the functions in md5.h), ArMutex, ArCondition and ArASyncTask. See Utility Classes for a list of utility classes.

ArConfig

ArConfig is a mechanism for storing configuration parameters for different independent modules in a text file. The global Aria class maintains a global ArConfig pointer which any program module may access. Use ArConfig::addParam to register a new parameter with ArConfig, and use ArConfig::addProcessFileCB to register a callback functor called when the configuration changes (by loading the file with ArConfig::parseFile, or other means such as an update from a remote client via ArNetworking).

Shared Info Groups

In a program composed of multiple independent modules, it is often necessary to exchange or combine data between them in a general and immediate way. To do this, ARIA provides the ArStringInfoGroup class, of which the global ARIA class contains an instance (in addition to an ArConfig instance used specifically for configuration information which changes infrequently, by loading a file or by user input.) An example of ArStringInfoGroup is the ArServerInfoStrings class contained in the ArNetworking auxiliary library. At program initialization, a callback functor may be added to the global ArStringInfoGroup object which on invocation immediately passes a string key/value pair from the ArStringInfoGroup object over to an ArServerInfoStrings object, which provides access to this data over the network (e.g. to MobileEyes). Independent components of the program may then change the values in the InfoGroup object without needing any special knowledge of the recipients of the data (in this example is the ArServerInfoStrings class). Since MobileEyes displays this data in a small table next to other robot information like position in speed, this is a useful way to provide informative statistics about the robot and software's current operation. (On Linux, for example, you could use the ArSystemStatus class to publish information from the operating system, like CPU load).

Maps

In mobile robot applications, you will often need to store a map of the robot's environment to use in navigation, localization, etc. ARIA provides the ArMap class for reading map data from a file, obtaining and modifying its contents in your application, and writing it back to file. An ArMap contains data about the sensed/sensable environment (walls, obstacles, etc.), and human-provided objects such as goal points.

The Map File Format page describes the map file format in detail.

ARNL, SONARNL and MobileSim all use ArMap format map files.

Sockets

The ArSocket class is a wrapper around the socket network communication layer of your operating system. ARIA mostly uses ArSocket to open a server port and to connect to another server port.

To connect to a port, simply construct a socket containing the hostname or IP address of the host, a port number, and the ARIA socket type (TCP or UDP). For example:

ArSocket sock("host.name.com", 4040, ArSocket::TCP);

Or call the ArSocket::connect() function, such as:

ArSocket sock;
sock.connect("host.name.com", 4040, ArSocket::TCP);

To open a server on (for example) port 4040, simply construct a socket:

ArSocket sock(4040, true, ArSocket::TCP);

Or call open(4040, ArSocket::TCP) on an ArSocket object constructed with the default constructor.

ArNetworking

For a more advanced networking infrastructure, see <a target="_top"
href="../ArNetworking/docs/index.html">the ArNetworking companion
library</a>, 
distributed with ARIA.  ArNetworking provides an extensible system of
data requests and updates between client and server applications via TCP or
UDP, using the same base "packet" concept as robot communication.  
For example, use ArNetworking to connect multiple robots working together, 
off-board user interfaces to on-board control servers, or robot control programs to 
off-board data resources.

Sound and Speech

ARIA provides foundation sound support, and separate libraries use this
for speech and network audio.

<ol>

 <li>ARIA's ArSoundsQueue provides a method for handling sound output 
 generated by various components of a large ARIA application in sequence 
 and in loops. 
 It is a sound playback and speech synthesis manager, which 
 uses a thread-safe queue of sound and speech synthesis requests, and runs
 a background processing thread for it. Use this for most of your non-trivial
 audio playback and voice synthesis needs.
 The speech synthesis libraries, the voice recognition library, and the NetAudio
 library are designed to be used in conjunction with this class to coordinate their 
 usage of the sound device.
</li>

<li>ARIA's ArSoundPlayer provides a basic cross-platform sound-file playback 
capability.
Sound files are in WAV (Windows RIFF) format. This class provides static methods
that can be used by ArSoundsQueue for sound file playback.
</li>

 <li>Separate libraries provide wrappers around some 
  speech synthesis (Text-to-speech) and recognition products:
 <ul>
   <li>The ArSpeechSynth_Festival library  uses the free Festival system from the 
     University of Edinburgh to perform speech synthesis. It provides
     the ArFestival class as a wrapper around Festival.
   </li>
   <li>The ArSpeechSynth_Cepstral library uses the Swift library from
     Cepstral, Inc. to perform speech synthesis. It provides the ArCepstral
     class for this. ArCepstral offers a few extra features over
     ArFestival, and Cepstral, Inc. provides high quality voices for use with Swift.
   </li>
   <li>The ArSpeechRec_Sphinx library uses Sphinx from Carnegie Mellon
     University to perform speech recognition. ArSphinx provides an interface to this.
   </li>
  </ul>
 </li>

 <p>Functions common to both of the speech synthesis libraries are included in a base
    class, ArSpeechSynth. 
  </p>

 <li>The separate ArNetAudio library provides network voice audio recording, transmission and playback:
 <ul>
   <li>ArNetAudioServer automatically decodes and plays or records and
 encodes audio for a network server (typically running on a robot's on-board
 computer) and sends and receives the encoded audio to/from a client.</li>
   <li>ArNetAudioClient automatically decodes and plays or records and
 encodes audio for a network client, sending and receiving the encoded
 audio to/from a server (i.e. a robot's on-board computer).</li>
   <li>ArNetAudioIO is the common class performing cross-platform Audio I/O 
   (via the free PortAudio library), and voice encoding/decoding (via the free Speex codec).
   It is used by ArNetAudioClient and ArNetAudioServer, but is also available for 
   stand alone use.
   </li>
 </ul>
 </li>

Emacs

Here is the configuration specification the developers at MobileRobots Inc. use in their .emacs files, in case you want to modify the code using emacs and not deal with differences in indentation and such.

    (setq c-default-style '((other . "user")))
    (c-set-offset 'substatement-open 0)
    (c-set-offset 'defun-block-intro 2)
    (c-set-offset 'statement-block-intro 2)
    (c-set-offset 'substatement 2)
    (c-set-offset 'topmost-intro -2)
    (c-set-offset 'arglist-intro '++)
    (c-set-offset 'statement-case-intro '*)
    (c-set-offset 'member-init-intro 2)
    (c-set-offset 'inline-open 0)
    (c-set-offset 'brace-list-intro 2)
    (c-set-offset 'statement-cont 0)
    (defvar c-mode-hook 'c++-mode)

Non-everyday use of C++

ARIA uses some features of C++ that some programmers may not be aware of yet, and includes some workarounds for platform differences.

Standard Template Library

ARIA makes heavy use of the C++ standard template library (STL). So you should understand the STL in order to get the best use from some of the more advanced parts of ARIA.

Default Arguments

In the function declaration a default value for an argument may be specified. Arguments with default values may then be omitted from the function call.

For example, after declaring this function with a default value for its integer argument:

void foo(int number = 3);

it can be used in two different ways:

// Use the default value for the argument:
foo();
// Or, use don't use the default:
foo(99);

This behavior is quite useful for having defaults for more obscure options you will usually not need to change, but still allowing you to change them if necessary without making ARIA more complex.

Also note that the function definition must not have the assignment in it, only the declaration. Therefore the definition if our example function would look like this:

void foo(int number)
{
//...
}

Constructor Chaining

Constructor chaining is quite simple though sometimes not used by C++ programmers. Each constructor can give arguments to the constructors of the member variables it contains and to the constructors of classes from which it inherits. For example if you have:

class BaseClass
{
public:
BaseClass(int someNumber);
};

and

class SubClass : public BaseClass
{
public:
SubClass(void);
int anotherNumber;
};

When you write your constructor for SubClass you can initialize both baseClass and anotherNumber:

SubClass::SubClass(void) : BaseClass(3), anotherNumber(37)
{
// ...
}

Note how the constructors to be initialized must follow a colon (:) after the constructor, and be separated by commas. Member variables must be initialized in the order they are in the class. Note that initializing integers is not all that unique or useful, but using this to initialize callback Functors is quite useful.

Constructor chaining is used in many many places by ARIA, thus it must be understood in order to understand ARIA, but the above is all that really needs to be known.

Chars and Strings, Win workaround

During development problems were encountered with Windows if a std::string was passed into a DLL. Thus for all input to ARIA const char * is used, but for all internal storage and all reporting std::strings are passed back out of ARIA.

AREXPORT

Because of the Windows set up for using DLLs, this macro is used to take care of the required declaration attributes for DLLs. Largely users do not need to worry about AREXPORT, but only functions which have AREXPORT and inline functions are usable with DLLs in Windows (all of the ARIA functions which are documented in this manual are usable).

Exceptions

ARIA neither throws nor catches any exceptions.

Topics and Esoterica

Piecemeal Use of ARIA

The most basic layer of ARIA is ArDeviceConnection and subclasses, which handle low-level communication with the robot server. On top of the connection layer, we have a packet layer–ArBasePacket and ArRobotPacket–the basic algorithms for constructing command packets and decoding server information packets.

Above the packet layer is the packet handler classes, ArRobotPacketReceiver and ArRobotPacketSender, when send and receive packets to and from the robot. Finally, on top of all these lowest layers is ArRobot, which is a gathering point for all things, but can be used in a quite basic format without all of the bells and whistles. ArRobot has built-in tasks, actions, state reflection and so forth, all of which can be disabled from the constructor (ArRobot::ArRobot) and ignored or reimplemented.

Also note that if all you do is turn off state reflection, which only affects sending ArRobot-mediated motion commands to the robot, not receiving SIPs from the robot, none of the other activities which ArRobot engages on its loop will take up hardly any time, so it probably isn't worth building your own set of tasks, but the power to do so is there for the intrepid.

One other thing worth noting is that you can call ArRobot::loopOnce() and it will run through its loop a single time and return. This is so that you can use ARIA from your own control structure. If you are using loopOnce you may also find it beneficial to call ArRobot::incCounter, so that the loop counter will be updated. You could also just call ArRobot::packetHandler, ArRobot::actionHandler, or ArRobot::stateReflector on your own, as these are the most important internal functions, though if you make your own loop you should probably call ArRobot::incCounter any way that you do it, as this is how sonar are known to be new or not, and such.

We recommend that whatever you do you use the same type of strict threading/locking that ARIA observes.

Connecting with a Robot or the Simulator the hard way

ArDeviceConnection is ARIA's communications object; ArSerialConnection and ArTcpConnection are its built-in children most commonly used to manage communication between a MobileRobots or ActivMedia robot or the robot simulator, respectively. These classes are not device-specific, however, so use ArSerialConnection, for instance, to also configure a serial port and establish a connection with a robot accessory, such as with the SICK laser range finder.

Opening the Connection

After creating and opening a device connection, associate it with its ARIA device handlers, most commonly with ArRobot::setDeviceConnection for the robot or the simulator.

For example, early in an ARIA program, specify the connection device and associate it with the robot:

Later in the program, after initializing the ARIA system (Aria::init(); is mandatory), set the Connection port to its default values (for TCP, host is "localhost" and port number is 8101), and then open the port:

con.setPort();
if (!con.openSimple())
{
printf("Open failed.");
return 1;
}

TCP and Serial connections have their own implementation of open which is not inherited, but has default arguments that make the generic open work for the all default cases. And open returns a status integer which can be passed to the re-implemented and inherited ArDeviceConnection::getOpenMessage in order to retrieve related status string, which is useful in reporting errors to the user without having to know about the underlying device.

Robot Client-Server Connection

After associating the device with the robot, now connect with the robot's servers, ArRobot::blockingConnect or ArRobot::asyncConnect, for example, to establish the client-server connection between ARIA ArRobot and the robot microcontroller or robot simulator. The blockingConnect method doesn't return from the call until a connection succeeds or fails:

robot.setDeviceConnection(&con);
if (!robot.blockingConnect())
{
printf("Could not connect to robot... Exiting.");
return 1;
}

The previous examples connect with the simulator through a TCP socket on your PC. Use tcpConn.setPort(host, port) to set the TCP hostname or IP address and related socket number to another machine on the network. For instance, use tcpConn.setPort("bill", 8101); to connect to the simulator which is running on the networked computer "bill" through port 8101.

Replace ArTcpConnection con; with ArSerialConnection con; to connect with a robot through the default serial port (/dev/ttyS0 or COM1), or another you specify with ArSerialConnection::setPort(), such as con.setPort("COM3");.

At some point, you may want to open the port with the more verbose con.open().

Connection Read, Write, Close and Timestamping

The two main functions of a device connection are ArDeviceConnection::read and ArDeviceConnection::write. Simple enough. ArDeviceConnection::close also is inherited and important. You probably won't use direct read or write to the robot device, although you could. Rather, ArRobot provides a host of convenient methods that package your robot commands, and gather and distribute the various robot information packets, so that you don't have to attend those mundane details. See the next section for details.

All ArDeviceConnection subclasses have support for timestamping (ArDeviceConnection::getTimeRead). With the robot connection, timestamping merely says what time a robot SIP came in, which can be useful for interpolating the robot's location more precisely.