quotes from "Really Reusable Robot Code and the Player/Stage Project"

Further some significants parts of the paper "Really Reusable Robot Code and the Player/Stage Project" have been copied. The purpose it to present a possible philosophy to drive the development of OCL 2.0 (it is recommended to read the entire paper). Feel free to discuss these concepts in the forum.



Our design philosophy is heavily influenced by the operating systems (OS) community, which has already solved many of the same problems that we face in robotics research. For example, the principle function of an operating system is to hide the details of the underlying hardware, which may vary from machine to machine. Similarly, we want to hide the details of the underlying robot. Just as I expect my web browser to work with any mouse, I want my navigation system to work with any robot. Where OS programmers have POSIX, we want a common development environment for robotic applications. Operating systems are equipped with standard tools for using and inspecting the system, such as (in UNIX variants) top, bash, ls, and X11. We desire a similar variety of high-quality tools to support experimental robotics.
Operating systems also support virtually any programming language and style. They do this by allowing the low-level OS interface (usually written in C) to be easily wrapped in other languages, and by providing language-neutral interfaces (e.g., sockets, files) when possible. Importantly, no constraints or normative judgments are made on how best to structure a program that uses the OS. We take the same approach in building robotics infrastructure. Though not strictly part of the OS, another key feature of modern development environments is the availability of standard algorithms and related data structures, such as qsort(), TCP, and the C++ Standard Template Library. We follow this practice of incorporating polished versions of established algorithms into the common code repository, so that each researcher need not re-implement, for example, Monte Carlo localization. Finally, an important but often over-looked aspect of OS design is that access is provided at all levels. While most C programmers will manage memory allocation with the library functions malloc() and free(), when necessary they can dig deeper and invoke the system call brk() directly. We need the same multi-level access for robots; while one researcher may be content to command a robot with high-level “goto” commands, another will want to directly control wheel velocities.
Player comprises four key abstractions: The Player Abstract Device Interface (PADI), the message protocol, the transport mechanism, and the implementation. Each abstraction represents a reusable and separable layer. For example, the TCP client/server transport could be replaced by a CORBA
The central abstraction that enables portability and code re-use in Player is the PADI speci?cation. The PADI defines the syntax and semantics of the data that is exchanged between the robot control code and the robot hardware. For ease of use, the PADI is currently specified as a set of C message structures; the same information could instead be written in an Interface Definition Language (IDL), such as the one used in CORBA systems. The PADI’s set of abstract robot control interfaces constitutes a virtual machine, a target platform for robot controllers that is instantiated at run time by particular devices. The goal of the PADI is to provide a virtual machine that is rich enough to support any foreseeable robot control system, but simple enough to allow for an e?cient implementation on a wide array of robot hardware. The key concepts used in the PADI, both borrowed from the OS community, are the character device model and the driver/interface model.
The interface/driver model groups devices by logical functionality, so that devices which do approximately the same job appear identical from the user’s point of view. An interface is a specification for the contents of the data stream, so an interface for a robotic character device maps the input stream into sensor readings, output stream into actuator commands, and ioctls into device configurations. The code that implements the interface, converting between a device’s native formats and the interface’s required formats is called a driver. Drivers are usually speci?c to a particular device, or a family of devices from the same vendor. Code that is written to target the interface rather than any specific device is said to be device independent. When multiple devices have drivers that implement the same interface, the controlling code is portable among those devices. Many hardware devices have unique features that do not appear in the standard interface. These features are accessed by device-specific ioctls, while the read and write streams are generally device independent. Interfaces should be designed to be suficiently complete so as to not require use of device-specific ioctls in normal operation, in order to maintain device independence and portability. There is not a one-to-one mapping between interface definitions and physical hardware components. For example, the Pioneer’s native P2OS interface bundles odometry and sonar data into the same packet, but a Player controller that only wants to log the robot’s position does not need the range data. For portability, Player separates the data into two logical devices, decoupling the logical functionality from the details of the Pioneer’s implementation. The pioneer driver controls one physical piece of hardware, the Pioneer microcontroller, but implements two different devices: position2d and sonar. These two devices can be opened, closed, and controlled independently, relieving the user of the burden of remembering details about the internals of the robot.
In order to more conveniently support different devices, we introduced the interface/driver distinction to Player. An interface, such as sonar, is a generic specification of the format for data, command, and configuration interactions that a device allows. A driver, such as pioneer-sonar, specifies how the low-level device control will be carried out. In general, more than one driver may support a given interface; conversely, a given driver may support multiple interfaces. Thus we have extended to robot control the device model that is used in most operating systems, where, for example, a wide variety of joysticks all present the same “joystick” interface to the programmer.
The primary cost of adherence to a generic interface for an entire class of devices is that the features and functionality that are unique to each device are ignored. Imagine a fiducial-finder interface whose data format includes only the bearing and distance to each fiducial. In order to support that interface, a driver that can also determine a fiducial’s identity will be under-utilized, some of its functionality having been sacrificed for the sake of portability. This issue is usually addressed by either adding configuration requests to the existing interface or defining a new interface that exposes the desired features of the device. Consider Player’s Monte-Carlo localization driver amcl; it can support both the sophisticated localization interface that includes multiple pose hypotheses, and the simple position2d interface that includes one pose and is also used by robot odometry systems.
These higher-level drivers use other drivers, instead of hardware, as sources of data and sinks for commands. The amcl driver, for example, is an adaptive Monte Carlo localization system [TFBD00] that takes data from a position2d device, a laser device, and a map device, and in turn provides robot pose estimates via the localize interface (as mentioned above, amcl also supports the simpler position2d interface, through which only the most likely pose estimate is provided). Other Player drivers perform functionality such as path-planning, obstacle avoidance, and various image-processing tasks. The development of such higher-level drivers and corresponding interfaces yields three key benefits. First, we save time and effort by implementing well-known and useful algorithms in such a way that they are immediately reusable by the entire community. Just as C programmers can call qsort() instead of reimplementing quicksort, robotics students and researchers students should be able to use Player’s vfh driver instead of reimplementing the Vector Field Histogram navigation algorithm [UB98]. The author of the driver benefits by having her code tested by other scientists in environments and with robots to which she may not have access, which can only improve the quality of the algorithm and its implementation. Second, we create a common development environment for implementing such algorithms. Player’s C++ Driver API clearly defines the input/output and startup/shutdown functionality that a driver must have. Code that is written against this API can enter a community repository where it is easily understood and can be reused, either in whole or in part. Finally, we create an environment in which alternative algorithms can be easily substituted. If a new localization driver implements the familiar localize interface, then it is a drop-in replacement for Player’s amcl. The two algorithms can be run in parallel on the same data and the results objectively compared.