Warning: strlen() expects parameter 1 to be string, array given in /home/sharpr6/public_html/wp-content/themes/starscape/code/starscape.php on line 450
SharpRobotica.com - Part 3

Q&A of Urbi, a Robot OS

datePosted on 18:32, July 16th, 2010 by Billy McCafferty

For decades, since the dawn of Shakey, the software side of robotics was primarily constrained to the world of hardware-limited embedded systems which needed to be redeveloped from the ground up with every new robot. This approach limits code reuse, is painfully tricky to debug, and becomes a serious time sink with each hardware upgrade. Accordingly, increasing efforts have been made to create an operating system for robots to provide better hardware abstraction, enable greater code reuse and maintainability, and to facilitate the development of software regardless of the robotic platform that it will be run on. Does this sound similar to what DOS and Windows enabled for the PC revolution to occur? (I don’t think I need to try to convince you of what an impact that approach had in the PC world.) Accordingly, the hope is that a similar effect, if not monetarily, will occur in the robotics world. Indeed, it is likely that such a step must be taken to catalyze the world of robotics to become a true game changer, on par with the PC movement and the introduction of the internet itself.

We seem to be an a moment in time that a practical robot OS is ready to be more fully embraced and leveraged. While there are a number on the market, time will tell if one will win out or if niches will exist to support a number of OSes concurrently within the robotics world. In the meantime, the work of organizations to introduce a common robot OS is making it exceedingly easier for software geeks (such as myself) to get deeper into robotics without having to put on our hardware-hacker hat as often. A few robot OSes which are making an impact in this direction include Microsoft Robotics Developer Studio (RDS), CARMEN, Player, Robot Operating System (which incidentally leverages Player), YARP (used by RobotCub), Orca, and Urbi. I’d like to share with you a little more information about one of these in particular, Urbi.

Jean-Christophe Baillie, the CEO of Gostai (the company behind Urbi), took some time to share with me some Q&A concerning Urbi and information concerning why they decided to open source Urbi (a terrific move in my opinion). While I have not yet experimented with Urbi, I have found this information very helpful in understanding more of what Urbi is all about (and in piquing my interest to try it out):

  • What is Urbi?Urbi is complete open source software platform to control robots, a kind of Operating System for robotics. It includes a C++ distributed components architecture called UObject, and an orchestration script language called urbiscript. The urbiscript language is innovative because it integrates new ways to handle parallel and event-based programming, which are two essential issues in robot programming. Recently, Urbi is also integrating ROS support to be able to integrate ROS nodes inside an Urbi project, and benefit from the best of both worlds.
  • What kind of robots can it control?Any kind of robot, from Lego NXT, Bioloid and Spykee, to Aibo, Nao, Segway RMP or Spykee. There is a complete list on urbiforge.org, and they are all available for free.

    We believe that Urbi is also suitable to control not only robots but also complex systems in general, involving multiple components highly interacting, like video games, simulations or factory/process management.

  • Can you tell more about urbiscript and its relationship to the Gostai C++ support.urbiscript is an orchestration language, which means that its role it to coordinate various components, organize their interactions, the data they exchange, etc. All this in realtime, with a dynamic approach (you can reconfigure everything at runtime), and with advanced parallel and event-based control capabilities. This last part really distinguishes Urbi from other script languages like python for example, where you have to handle parallelism or events in a more traditional way. And it saves a lot of time.

    The way C++ and urbiscript talk together is via UObject, which is a C++ library capable to transparently bind any C++ object to urbiscript. With UObject, you take your favorite C++ class and it will appear as a native class of urbiscript, except that it is in fact C++ behind the scene. You can then connect this C++ class to other C++ classes using the orchestration capabilities of urbiscript.

  • What makes Urbi unique?The parallel orchestration approach that comes with urbiscript is quite unique. We are also the only one to provide with Gostai Studio a graphical programming suite that handles hierarchical finite state machines (most other graphical approaches offered are flow charts). On a more technical side, the way UObject is bound to urbiscript provide very interesting asynchronous possibilities on the side of C++, which kind of enhances C++ itself with abstractions inherited from urbiscript. This makes UObject a little bit more than a traditional component architecture.

    Finally, I know it is not very convincing because almost everyone claims it for itself, but our users really support the fact that Urbi is amazingly simple to master, intuitive and well designed. You will have to make your own opinion on this, but we consider it a big difference with other competing alternatives. It just works, and we like it when we we can keep it simple.

  • How does Urbi fit within a distribute and remote control environment?A nice feature that comes with UObject is that you can plug your C++ class into urbiscript in two ways: first in plugin mode, where the C++ class is physically bound to the Urbi engine that integrates the urbiscript interpreter. Everything is tightly connected then, shared memory, etc. The second way is to connect it in remote mode, where your C++ class becomes an executable program that will connect itself to the Urbi engine over the network. From within urbiscript, there is no difference, in both cases you will see that your C++ class appears inside urbiscript and you will get a transparent access to all its methods/variables. But behind the scene you have either direct memory access, or TCP/IP relaying. This means that you can very easily distribute a project simply by selecting certain UObject to run in remote mode, some of them on remote machines, some of them locally on the robot.
  • Urbi has gone open source. Why did Gotsai take this step?I think it is the right move in 2010. You see how Android and other open source initiatives gain a tremendous momentum and add value to their underlying companies by creating a community, and I believe this is a model that has a future. We can have more community, more users, more feedback and ultimately perhaps more customers for our GostaiNet cloud based technologies, or Gostai Studio programming IDE. This commercial activity increase will allow us to reinvest more money into Urbi and the community will benefit back from it. This is a virtuous circle.
  • What is Gostai RTC?Gostai RTC is the first commercial implementation of the RTC robotics standard. It is based on Urbi underneath, and you can benefit from the urbiscript orchestration layer together with RTC. Of course, you can also simply just use RTC without Urbi, and benefit from Gostai’s support. Gostai RTC is a product for the industry, so we sell it together with support and maintenance contracts.
  • What is the difference between the full RTC implementation and the one supported by the openRTM open source version?The openRTM version of RTC is based on CORBA and, to my opinion, is much more complex to master. Also, the big difference is that we offer support, which matters the most for our industrial clients.
  • What operating platforms do the various versions support?GostaiRTC is working on all platforms where you can run Urbi, which means a lot! We have support for almost all flavors of Linux, Windows or MacOSX, plus a few more exotic platforms and processors. GostaiRTC provides also support for the realtime operating system Xenomai, which we don’t offer with Urbi at the moment.
  • What needs to be done to support a new, custom robot?Basically, you will develop drivers for your robots by creating appropriate UObjects in C++ to bridge the robot API with urbiscript. The procedure is described at http://www.urbiforge.org/index.php/Robots/Custom

    For example, you might create a ‘headYaw’ C++ object, with a ‘val’ attribute, and use callbacks on read/write on ‘val’ to trigger the appropriate robot API messages to actually move the robot head. All this is heavily documented and relatively easy to do. Of course, you also have existing examples that you could use as a starting point to adapt on your robot, and most common bus interfaces (CAN or i2c) are already supported.

  • What is Gostai Studio?Gostai Studio Suite is a set of two graphical programming tools: Gostai Studio and Gostai Lab. Gostai Studio is an editor for hierarchical finite state machines (HFSM), which is a very common way to represent a robot behavior as a series of states connected by transitions, which are associated to conditions. For example, you can be in a ‘search the ball’ state, and move to the ‘follow the ball’ state through a transition that is attached to the ‘see the ball’ condition. Gostai Studio includes a debugger, and since it is based on urbiscript underneath, it is able to do some very sophisticated things, like pause the execution, trace the current state in realtime, and of course run many things in parallel. It’s really a unique implementation of the classical HFSM approach, which is standing apart.

    Gostai Lab is a user interface (UI) generator. You can create a UI by drag&dropping widgets on a blank sheet, each widget being associated to a variable in urbiscript that you want to monitor. You can create a widget for a camera, another for a numerical value, seen as a slider, another one could be a button that you associate to some urbiscript code to execute, etc. At the end, you can design a complete application in a completely graphical way. It saves a lot of time, and since it is based on a client/server approach, you can have many instances running in parallel and monitoring different aspects of your robot or algorithms.

  • What is GostaiNet?GostaiNet is a cloud architecture for robotics. It allows to manage and remotely execute services for robots on distant servers, lowering the need for powerful and expensive CPU inside robots, and opening the door to web-based services and interactions.

    GostaiNet is operational and used by selected clients and also internally for some of Gostai’s own projects.

  • Where can developers get Urbi?The community site is on www.urbiforge.org, where you can get Urbi for free, plus many modules, components, help on the forum, etc. You can also go to www.gostai.com to get a trial version of Gostai Studio, which is a product that we sell.

I hope this helps to provide a basic introduction to what Urbi and its creator, Gostai, are all about. Although I have not yet used Urbi in my own research efforts, I plan to give it a try and will post my experiences when I get further into it.

Enjoy!
Billy McCafferty

Robot Operating System (ROS) Command Cheat Sheet

datePosted on 18:32, July 15th, 2010 by Billy McCafferty

So far, I have found ROS to be logical, concise and easy to use (after going through all of the tutorials and practicing with it a bit). Honestly, I’ve found it to be more intuitive and tractable (i.e., more enjoyable to work with) than Microsoft Robotics Developer Studio; albeit, I have not yet used the 2008 R3 release and intend on giving Microsoft RDS a more concerted and focused go around. While both RDS and ROS support messaging design patterns, so far I’m leaning towards ROS as a better enabler for cleanly separating components (e.g., ROS package) from the messaging middleware.

One of the most daunting tasks of getting up to speed with ROS is learning and understanding the plethora of available commands and sequences of commands for performing common tasks. Fortunately, the ROS documentation – which is continually improving at a very fast rate – now includes a comprehensive cheat sheet for referencing ROS commands. Since I began using ROS, I’ve been maintaining my own cheat sheet which describes (my) most commonly used commands, descriptions of use, and example invocations (unsurprisingly, there is a lot of overlap with ROS’ cheat sheet).

With my spreadsheet, I’ve also begun keeping track of common sequences of commands within my cheat sheet as a quick means to look up what series of commands are necessary to perform a common task, such as creating a new service from an existing one. This kind of information is certainly available via the ROS documentation, but keeping it consolidated has been a great help in reducing searching around for it. Finally, I also like to keep track of a glossary of common terms and other useful ROS info.

As it has for me, you may find my ROS cheat sheet (an OpenOffice spreadsheet) as a useful starting point for maintaining your own list of common-sequences-of-commands and other at-your-finger-tips information for quickly navigating through ROS capabilities.

Enjoy!
Billy McCafferty

Sequencing Layer with ESL (Execution Support Language)

datePosted on 00:06, July 13th, 2010 by Billy McCafferty

In Architectural Paradigms of Robotic Control, I discussed a number of control architectures with a bias towards a hybrid approach, for facilitating reactive behaviors without precluding proper planning. With 3T, a common hybrid approach, the three layers include a skill layer for reactive behavior and actuator control, a sequencing (or execution) layer for sequencing behaviors based on relevant conditions, and a planning (or deliberative) layer for making plans for future actions.

While the skill layer is typically developed in a low level language such as C++, the sequencing and planning layers frequently require a “higher” language to manage complexity and required flexibility. (E.g., a language using XML to express and execute first-order predicate logic without worrying about the low level implementation details of C++ control structure could be considered a “higher” language.) Indeed, Douglas Hofstadter, in his classic work Gödel, Escher, Bach, suggests that such higher level languages will most certainly be a prerequisite for developing more intelligent machines.

ESL (Execution Support Language), developed by Ron Garret (the artist formerly known as Erann Gat), is one such higher language, built on Lisp, for the implementation of the sequencing layer of a hybrid control architecture. ESL is discussed in both Artificial Intelligence and Mobile Robotics and Springer Handbook of Robotics as being a language which:

  • Supports hierarchical decomposition of tasks into subtasks
  • Supports design by contract (pre/post conditions)
  • Supports signaling of state changes
  • Supports clean-up procedures
  • Exhibits robust execution monitoring and exception handling
  • Includes symbolic database (world model) for linking environment to behavior layer

After looking around for an implementation of ESL, I contacted Dr. Garret to find out where I might be able to find it. Amiably, Ron has made ESL available for download from his site. While I admit that I have not yet used ESL, I look forward to digging into Ron’s code to learn more about this seemingly solid approach to developing and managing a proper sequencing layer.

While I am also familiar with Task Description Language (TDL) as an alternative to ESL, I am quite interested in hearing about any other approaches actively being taken to managing the sequencing/execution layer. I’ll certainly post more about ESL or other options as I research more on this topic. Incidentally, I’m also looking forward to digging into Herbal for the planning layer…but that’s for another post altogether!

Enjoy!
Billy McCafferty

Part IV: Developing and Testing the Application Services

[Author's note, July 28, 2010: Introduced Boost::shared_ptr to manage reference to message endpoint so as to enable postponed construction, as will be required in Part VI.]

Ah, we’ve made it to the application services layer.  After defining the architecture, setting up the package, and implementing the core layer which contains the domain logic of the application, we’re ready to take on developing the application services layer.  In short, the service layer provides the external API to the underlying domain layer.  Ideally, one should be able to develop the entirety of the “non-UI” portions of an application and have it exposed via the application services layer.  In other words, one should be able to swap out the front end – say from a web front end to a Flash front end – without having the application services layer effected. If you’d like to go ahead and download the source for this article, click here.

The application services layer is analogous to a task or coordination manager; i.e., it doesn’t know how to carry out the low level details of a particular action but it does know who is responsible for carrying out particular tasks.  Accordingly, the application services layer of the package (or any application for that matter) is mostly made up of a number of publicly accessible methods which, in turn, pass responsibilities on to external service dependencies (e.g., a message endpoint) and the domain layer for execution.

With that said, the services layer should still eschew direct dependencies on external services, such as communications with a messaging framework (e.g., ROS).  Accordingly, in this post, we’ll materialize the application services layer of our package and give it two responsibilities:

  • Coordinate with the domain layer to begin laser report reading and handle the raised reports, accordingly;
  • Forward laser reports on to the appropriate message endpoint(s) to have the information disseminated over the message based system.

But (there’s always a “but” isn’t there), while the application services layer should be responsible for passing messages received from the domain layer on to the messaging middleware, it should not have a direct dependency on that messaging middleware itself.  This decoupling facilitates testing of the application services layer with test doubles, keeps a clean separation of concerns between task coordination and messaging, and provides greater flexibility with being able to modify/upgrade the messaging layer without affecting the application services layer.

A moment needs to be taken to clarify the differences among application services, domain services, and “external resource” services.

  • Application services are our current concern.  The word “services” in their convoluted title is misleading and should not be inferred as being web services, RESTful services, or the like.  A better name for describing the application services responsibilities is “task coordination layer,” “workflow management layer,” or “not-real-services application services layer.”  We’ll examine a bit in this post exactly how the application services layer can be properly leveraged.
  • Domain services are really utility classes used by the core layer (the concern of our previous post) for processing data or encapsulating a specific, reusable task or behavior.  Domain services almost never have state (i.e., properties) and sometimes expose behavior as static methods.  A good example of a domain service would be a calculator class (e.g., Kalman filter calculator) or a string utility class.
  • External resource services are what we typically think of when we hear the word “service.”  An external resource service is any class which depends upon…well…an external resource.  Examples of an external resource include databases, resource files (e.g., maps), messaging middleware, third party web services, and even the laser reading class that we simulated in Part II of this series.  Ideally, external resource services should be abstracted, allowing consumers of the services to interact with them via interfaces or abstract classes.  In this way, layers remain decoupled from the implementation details of the services, reflecting the benefits of proper OOP design.  Proper abstraction of service layers usually involves separated interface and dependency injection.  We’ll see in this post how these techniques are leveraged to decouple the application services layer from the message endpoints (which are indeed external resource services).

Before we delve in, let’s briefly review what we plan to accomplish:

  • An application service class – LaserScanReportingService – will be developed to provide a public API for starting and stopping the laser reader.  In addition to exposing this behavior, the class will also listen for laser scan reads and pass the laser scans onto a message endpoint for publication to ROS.
  • A message endpoint interface will be introduced to provide an abstraction to the implementation details of the concrete message endpoint itself.  The application service class will communicate with the message endpoint via this abstraction to allow for unit testing the application services layer in isolation of the messaging middleware.
  • Unit tests will be written to verify the functionality of the application service class.  Furthermore, a message endpoint test double, a stub in this case, will be added to simulate communications with the messaging middleware.  Again, this will allow us to verify the task coordination behavior of the application services layer without concerning ourselves with messaging middleware integration details.

Enough with the chatter, let’s see some code!

Target Class Diagram

The following diagram shows what the package will look like after completing the steps in this post. While the individual elements will be discussed in more detail; the class diagram should serve as a good bird’s eye view of the current objectives. The elements with green check marks were completed in previous posts.

1. Setup the Package Skeleton and Domain Layer

If not done already, follow the steps in Part II and Part III to create the package and develop/test the domain layer.

2. Create an interface for the message endpoint service which the application service layer will leverage to communicate with ROS.

Create src/core/message_endpoint_interfaces/ILaserScanEndpoint.hpp containing the following code:

// ILaserScanEndpoint.hpp
 
#ifndef GUARD_ILaserScanEndpoint
#define GUARD_ILaserScanEndpoint
 
#include "sensor_msgs/LaserScan.h"
 
namespace ladar_reporter_core
{
  class ILaserScanEndpoint
  {
    public:
      // Virtual destructor to pass pointer ownership without exposing base class [Meyers, 2005, Item 7]
      virtual ~ILaserScanEndpoint() {}
      virtual void publish(const sensor_msgs::LaserScan& laserScan) const = 0;
  };
}
 
#endif /* GUARD_ILaserScanEndpoint */

There shouldn’t be anything too surprising in this interface.  It simply exposes a method to publish a laser scan to the underlying messaging middleware.  Why not put the interface in the application services layer, which intends to use it?  A couple of good reasons come to mind: 1) since it’s a pure interface, having elements within core aware of it (or even directly dependent upon it) does not introduce any further coupling to the underlying external resource, the messaging middleware, and 2) in very simply packages, an application services layer might be overkill, so keeping the “external resource service interface” (there’s a mouthful) in the core layer facilitates either approach without having to move anything around if the selected approach changes during development.

3. Create the application service header class.

Create src/application_services/LaserScanReportingService.hpp containing the following code:

// LaserScanReportingService.hpp
 
#ifndef GUARD_LaserScanReportingService
#define GUARD_LaserScanReportingService
 
#include <boost/shared_ptr.hpp>
#include "ILaserScanEndpoint.hpp"
 
namespace ladar_reporter_application_services
{
  class LaserScanReportingService
  {
    public:
      explicit LaserScanReportingService(boost::shared_ptr<ladar_reporter_core::ILaserScanEndpoint> laserScanEndpoint);
 
      void beginReporting() const;
      void stopReporting() const;
 
    private:
      // Forward declare the implementation class
      class LaserScanReportingServiceImpl;
      boost::shared_ptr<LaserScanReportingServiceImpl> _pImpl;
  };
}
 
#endif /* GUARD_LaserScanReportingService */

A few notes:

  • Line 7:  Includes the previously defined message endpoint interface.
  • Line 14:  Provides a constructor for the application service class, accepting an implementation of ILaserScanEndpoint, accordingly.
  • Lines 16-17:  Exposes methods for exposing behavior found within the core layer.
  • Lines 21-22:  Declaration for a pImpl (private implementation) that will allow the application service class to be updated frequently while minimizing the rebuilding of other class libraries which depend upon it.  Using the pImpl pattern will likely be overkill in smaller packages, but can be an appreciable timesaver as packages grow in size. It has been included in the sample code here as a example reference for when it might be more appropriately required.

4.  Create the application service implementation class.

Create src/application_services/LaserScanReportingService.cpp containing the following code:

// LaserScanReportingService.cpp
 
#include "sensor_msgs/LaserScan.h"
#include "ILaserScanListener.hpp"
#include "LaserScanReader.hpp"
#include "LaserScanReportingService.hpp"
 
using namespace ladar_reporter_core;
 
namespace ladar_reporter_application_services
{
  // Private implementation of LaserScanReportingService
  class LaserScanReportingService::LaserScanReportingServiceImpl : public ladar_reporter_core::ILaserScanListener
  {
    public:
      explicit LaserScanReportingServiceImpl(boost::shared_ptr<ILaserScanEndpoint> laserScanEndpoint);
 
      void onLaserScanAvailableEvent(const sensor_msgs::LaserScan& laserScan) const;
      LaserScanReader laserScanReader;
 
    private:
      boost::shared_ptr<ILaserScanEndpoint> _laserScanEndpoint;
  };
 
  LaserScanReportingService::LaserScanReportingService(boost::shared_ptr<ILaserScanEndpoint> laserScanEndpoint)
    : _pImpl(new LaserScanReportingServiceImpl(laserScanEndpoint)) {
 
    // Wire up the reader to the handler of laser scan reports
    _pImpl->laserScanReader.attach(*_pImpl);
 }
 
  LaserScanReportingService::LaserScanReportingServiceImpl::LaserScanReportingServiceImpl(boost::shared_ptr<ILaserScanEndpoint> laserScanEndpoint)
    : _laserScanEndpoint(laserScanEndpoint) { }
 
  void LaserScanReportingService::beginReporting() const {
    _pImpl->laserScanReader.beginReading();
  }
 
  void LaserScanReportingService::stopReporting() const {
    _pImpl->laserScanReader.stopReading();
  }
 
  void LaserScanReportingService::LaserScanReportingServiceImpl::onLaserScanAvailableEvent(const sensor_msgs::LaserScan& laserScan) const {
    // Send laserScan to the message end point
    _laserScanEndpoint->publish(laserScan);
  };
}

A few notes:

  • LaserScanReportingService::LaserScanReportingServiceImpl defines the pImpl implementation.  As shown, this pImpl implementation accepts a ILaserScanEndpoint via its constructor and also adds members for communicating with LaserScanReader and with the provided message end point.  As discussed earlier in this post, it’s preferable to abstract dependencies on external resource services using interfaces or abstract classes, as was done with ILaserScanEndpoint.  Quite arguably, LaserScanReader is also an external resource service.  But since the core of our package is in providing a means to read laser scans from a particular laser range finder, I made a purity concession, if you will, allowing the application services layer to have a direct dependency on the reader itself.  Alternatively, an interface could be introduced for the LaserScanReader; but since the very heart of this package is in reading and reporting laser scans, I felt this concession to be warranted…or at least justifiably defendable.  With that said, concessions such as this should be carefully thought out and discussed with the project team to determine the pros and cons of either approach and to ensure that everyone has a clear understanding of the motivations of the decision.  (If the team – or yourself – does not understand or can explain why an architectural decision was made, it’s a good chance that the architectural decision will not be adhered to or may become a source of code rot.)

    The other item to note is that the pImpl class implements ILaserScanListener; accordingly, this class will act as the observer for receiving and handling laser scan reports raised from LaserScanReader.

  • The constructor of LaserScanReportingService accepts a reference to ILaserScanEndpoint, passes that reference on to the constructor of LaserScanReportingServiceImpl and attaches the observer to LaserScanReader to listen for raised laser scans.
  • The constructor of LaserScanReportingServiceImpl accepts a reference to ILaserScanEndpoint and initializes the laserScanEndpoint member to that reference, accordingly.
  • beginReporting and stopReporting provide pass through methods to the underlying behavior exposed by laserScanReader.
  • Finally, onLaserScanAvailableEvent provides an event handler to accept a laser scan from LaserScanReader and pass it on to laserScanEndpoint’s publish function.

As mentioned previously, the above implementation could be done without a private implementation design pattern, but this serves to illustrate how such a pattern may be leveraged when warranted.

5. Configure CMake to Include the Header and Implementation

With the header and implementation classes completed, we need to make a couple of minor modifications to CMake for their inclusion in the build.

  1. Open /ladar_reporter/CMakeLists.txt. Within the include_directories statement, add an include for the following directory to include the message endpoint and application service headers:
    "src/core/message_endpoint_interfaces"
    "src/application_services"
  2. Open /ladar_reporter/src/CMakeLists.txt. Add an inclusion for the application_services directory at the end of the file:
    add_subdirectory(application_services)
  3. Now, in order to create the application services class library itself, a new CMake file is needed under /ladar_reporter/src/application_services. Accordingly, create a new CMakeLists.txt under /ladar_reporter/src/application_services, containing the following:
    # Create the library
    add_library(
      ladar_reporter_application_services
      LaserScanReportingService.cpp
    )

6. Build the application services Class Library

In a terminal window, cd to /ladar_reporter and run make. The class library should build and link successfully.

Like before, we’re not done yet…it’s now time to test our new functionality.

7. Unit Test the LaserScanReportingService Functionality

When we go to test the functionality of the laser scan reporting application service, it will likely be quickly noticed that there’s a missing dependency which will be needed to test the functionality of this class: a concrete implementation of ILaserScanEndpoint.hpp. The job of the message endpoint class will be to take laser scans and publish them to the appropriate topic on ROS. But we’re just not there yet…what we’d really like to do is to be able to test the functionality of the application service layer – LaserScanReportingService.cpp to be specific – without necessitating the presence of the message endpoint and ROS itself. While we’ll have to cross that bridge eventually (in Part V to be exact), we’re not currently interested in doing integration tests. Instead, we’re only interested in testing the behavior of the application service regardless of its integration with ROS.

Accordingly, a “stub” object will be employed to stand in for an actual message endpoint. In this case, the stub object is nothing more than a concrete implementation of ILaserScanEndpoint.hpp; but instead of publishing the laser scan to ROS, it’ll do something testable, such as keep a tally, or possibly a temporary queue, of laser scans “published” which can then be verified with testing asserts. If you’re new to unit testing, you’ll want to read about test doubles, Martin Fowler’s Mocks Aren’t Stubs, and XUnit Test Patterns for a more comprehensive treatment of the subject.

Onward with testing…

  1. Create /ladar_reporter/test/message_endpoints/test_doubles/LaserScanEndpointStub.hpp containing the following code to declare and define the message endpoint stub:
    // LaserScanEndpointStub.hpp
     
    #ifndef GUARD_LaserScanEndpointStub
    #define GUARD_LaserScanEndpointStub
     
    #include "sensor_msgs/LaserScan.h"
    #include "ILaserScanEndpoint.hpp"
     
    namespace ladar_reporter_test_message_endpoints_test_doubles
    {
      class LaserScanEndpointStub : public ladar_reporter_core::ILaserScanEndpoint
      { 
        public:
          LaserScanEndpointStub()
            : countOfLaserScansPublished(0) { }
     
          void publish(const sensor_msgs::LaserScan& laserScan) const {
            countOfLaserScansPublished++;
     
            // Output the laser scan seq number to the terminal; this isn't the
            // unit test, but merely a helpful means to show what's going on.
            std::cout << "Laser scan sent to LaserScanReceiver with angle_min of: " << laserScan.angle_min << std::endl;
          };
     
          // Extend ILaserScanEndpoint for unit testing needs.
          // May be modified by const functions but maintains logical constness [Meyers, 2005, Item 3].
          mutable int countOfLaserScansPublished;
      };
    }
     
    #endif /* GUARD_LaserScanEndpointStub */

    If you’re paying attention (of course you are!), you’ll notice that this code looks very similar to the code used within the LaserScanReaderTests.cpp class’ fake event handler from Part III. In fact, it’s the exact same code but now it’s encapsulated within a message endpoint stub. Admittedly, this is not a very good testing endpoint (since it won’t make it easier to verify that the laser scans have been “published” via testing asserts), but it does provide an easy means to visually note, while the tests are running, how the message endpoint stub is behaving. More importantly, seeing the laser scans output to the screen will show the application service layer is interacting with the message endpoint appropriately…which is exactly what we’re trying to verify.

    While the LaserScanEndpointStub class could have been coded inline within the unit test class (discussed next), encapsulating it within an external class allows the stub to be reused by other tests as well. This may not be necessary in all cases – in which coding it inline would be just fine – but I typically find myself reusing stubs and mocks to avoid duplicated code in my testing layer; besides, keeping it within an external test double keeps the code arguably cleaner.

  2. Create /ladar_reporter/test/application_services/LaserScanReportingServiceTests.cpp containing the following testing code:
    // LaserScanReportingServiceTests.cpp
     
    #include <gtest/gtest.h>
    #include "LaserScanEndpointStub.hpp"
    #include "LaserScanReportingService.hpp"
     
    using namespace ladar_reporter_application_services;
    using namespace ladar_reporter_test_message_endpoints_test_doubles;
     
    namespace ladar_reporter_test_application_services
    {
      // Define the unit test to verify ability to leverage the reporting service using the messege endpoint stub
      TEST(LaserScanReportingServiceTests, canStartAndStopLaserScanReportingService) {
        // Establish Context
        boost::shared_ptr<LaserScanEndpointStub> laserScanEndpointStub =
          boost::shared_ptr<LaserScanEndpointStub>(new LaserScanEndpointStub());
        LaserScanReportingService laserScanReportingService(laserScanEndpointStub);
     
        // Act
        laserScanReportingService.beginReporting();
        sleep(2);
        laserScanReportingService.stopReporting();
     
        // Assert
     
        // Since we just ran the reader for 2 seconds, we should expect a few readings.
        // Arguably, this test is a bit light but makes sure laser scans are being pushed 
        // to the message endpoint for publication.
        EXPECT_TRUE(laserScanEndpointStub->countOfLaserScansPublished > 0 &&
          laserScanEndpointStub->countOfLaserScansPublished <= 10);
      }
    }
  3. Open /ladar_reporter/test/CMakeLists.txt. Modify the contents to reflect the following:
    include_directories(
      "message_endpoints/test_doubles"
    )
    
    rosbuild_add_executable(
      ladar_reporter_tests
      TestRunner.cpp
      ./core/LaserScanReaderTests.cpp
      ./application_services/LaserScanReportingServiceTests.cpp
    )
    
    rosbuild_add_gtest_build_flags(ladar_reporter_tests)
    
    # Link the libraries
    target_link_libraries(
      ladar_reporter_tests
      ladar_reporter_application_services
      # Important that core comes after application_services due to direction of dependencies
      ladar_reporter_core
    )
  4. With everything in place, head back to the terminal and run:
    make
    cd bin
    ./ladar_reporter_tests

While running the tests, you should see a few messages published to the message endpoint stub. This demonstrates that all of the interactions among our core and application service layers are occurring exactly as expected. Now for the fun part…

In Part V, we’ll finally take a look at using all of these pieces together in order to publish messages to a ROS topic via a message endpoint.

Enjoy!
Billy McCafferty

Download the source for this article.

Microsoft RDS R3 Now Available…and free (as in beer)!

datePosted on 17:47, May 20th, 2010 by Billy McCafferty

Whether ROS and other recent moves have had a direct impact on the decision or not, it looks like Microsoft is getting the message that professional robotics software isn’t just the realm of licensed, proprietary software, but frequently supported by world class software solutions which are often free and open source. In a step in this direction, Microsoft has released Microsoft 2008 Robotics Developer Studio (RDS), making it available completely free of charge with all of the bells and whistles provided with the previous standard edition.

http://www.microsoft.com/robotics/

Enjoy!
Billy McCafferty

Part III:  Developing and Testing the Domain Layer

[Author's note, July 28, 2010: Fixed minor bug in LaserScanReader.cpp wherein it couldn't be restarted after being stopped; had to reset _stopRequested to false.]

In Part II of this series, we created the humble beginnings of the package and added folders to accommodate all of the layers of our end product, a well-designed ROS package that reports (fake) laser scan reports.  In this post, the domain layer of the package will be fleshed out along with unit tests to verify the model and functionality, accordingly.  The entire focus will be on implementing just one of the requirements initially described in Part I:  The package will read laser reports coming from a laser range-finder. If you’d like to download the resulting source for this article, click here.

That certainly sounds easy enough.  Disregarding the previous discussions concerning architecture, the gut reaction might be to start adding code to main(), simply taking the results from the range-finder, turning them directly into a ROS message, and publishing the messages to the appropriate ROS topic.  This myopic “get ‘er done” approach quickly gets out of hand as main() turns into a tangled mess of code managing a variety of responsibilities.  Object oriented principles aside, having all of these separate concerns mashed into main turns the little package into a maintenance nightmare with little ability to reuse code.  As mentioned, the first concern that we’ll want to tackle is the ability to read laser range-finder reports.  We’ll tackle this requirement by encapsulating the range-finder integration code within a class called LaserScanReader.cpp.  By doing so, all of the communications to the range-finder are properly encapsulated within one or more classes, making the integration code easier to reuse and maintain.  To keep our focus on the overall architecture, and to avoid the need to have a physical range-finder handy, we’ll simulate range-finder communications within LaserScanReader.cpp.  Certainly an added benefit of this approach, if we were doing this for a real-world package, is that one group could work on the “rest” of the package while another group works on the actually range-finder communications; so when ready, LaserScanReader.cpp could be switched out with the “real” range-finder integration code.

Prerequisites:

Before proceeding, recall that, as described in Part I, the domain layer of the package should not have knowledge concerning how to communicate with the messaging middleware directly (e.g., ROS).  This implies that the domain layer should have no direct dependencies on the messaging middleware.  This allows the domain layer to be more easily reused with another messaging middleware solution.  Additionally, keeping this clean separation of concerns facilitates the testing of the domain layer independently from its interactions with the messaging middleware.  Accordingly, the simple domain layer developed in this post will adhere to this guidance along with full testing for verification of capabilities as well.

Our LaserScanReader class will expose two methods, beginReading() and stopReading(), along with an observer hook to provide a call-back to be invoked whenever a new reading is available.  For now, we won’t worry about what exactly will be called back in the completed package, as that’ll be a concern of the application services layer; but we’ll need to prepare for it by including an interface for the laser scan observer.

Target Class Diagram

The following diagram shows what the package will look like after completing the steps in this post. While the individual elements will be discussed in more detail; the class diagram should serve as a good bird’s eye view of the current objectives.

1. Setup the Package Skeleton

If not done already, follow the steps in Part II to create the beginnings of the package.

2. Create the ILaserScanListener Observer Header

Whenever a laser scan is read, it’ll need to be given to whomever is interested in it. It should not be the responsibility of the laser scan reader to predict who will want the laser scans. Accordingly, an observer interface should be introduced which the laser scan reader will communicate through to raise laser scan events to an arbitrary number of listeners.

Add a new interface header file to /ladar_reporter/src/core called ILaserScanListener.hpp containing the following code:

// ILaserScanListener.hpp
 
#ifndef GUARD_ILaserScanListener
#define GUARD_ILaserScanListener
 
#include "sensor_msgs/LaserScan.h"
 
namespace ladar_reporter_core
{
  class ILaserScanListener
  {
    public:
      // Virtual destructor to pass pointer ownership without exposing base class [Meyers, 2005, Item 7]
      virtual ~ILaserScanListener() {}
      virtual void onLaserScanAvailableEvent(const sensor_msgs::LaserScan& laserScan) const = 0;
  };
}
 
#endif /* GUARD_ILaserScanListener */

As you can see, this C++ interface (or as close as you can get to an interface in C++) simply exposes a single function to handle laser scan events.

3.  Create the LaserScanReader Header

Add a new class header file to /ladar_reporter/src/core called LaserScanReader.hpp containing the following code, which we’ll discuss in detail below.

// LaserScanReader.hpp
 
#ifndef GUARD_LaserScanReader
#define GUARD_LaserScanReader
 
#include <pthread.h>
#include <vector>
#include "sensor_msgs/LaserScan.h"
#include "ILaserScanListener.hpp"
 
namespace ladar_reporter_core
{
  class LaserScanReader
  {
    public:
      LaserScanReader();
 
      void beginReading();
      void stopReading();
 
      // Provides a call-back mechanism for objects interested in receiving scans
      void attach(ILaserScanListener& laserScanListener);
 
    private:
      void readLaserScans();
      void notifyLaserScanListeners(const sensor_msgs::LaserScan& laserScan);
 
      std::vector<ILaserScanListener*> _laserScanListeners;
 
      // Basic threading support as suggested by Jeremy Friesner at
      // http://stackoverflow.com/questions/1151582/pthread-function-from-a-class
      volatile bool _stopRequested;
      volatile bool _running;
      pthread_t _thread;
      static void * readLaserScansFunction(void * This) {
        ((LaserScanReader *)This)->readLaserScans();
        return 0;
      }
  };
}
 
#endif /* GUARD_LaserScanReader */

Let’s now review the more interesting parts of the header class:

  • Lines 3-4:  Standard header guard so that the class is not declared multiple times.
  • Line 8:  Include the laser scan message from ROS.  As discussed previously, the domain layer should not have any direct dependencies on the messaging infrastructure.  The question here is whether or not the domain layer’s knowledge of the laser scan message class violates this principle.  When I initially developed this example code, I wrote a domain-specific equivalent of the laser scan message, placed within /core, so as to avoid any direct dependencies on anything ROS related.  Continuing in this vein, it would then be required that the message endpoint contain a message translator to  convert the domain-specific laser scan class into the corresponding ROS laser scan message, for subsequent publication to ROS.  The motivation for taking this “theoretically pure” approach was to reduce coupling between the domain layer and the messaging infrastructure; one of the advantages being to enable the ability to swap out the messaging infrastructure with another messaging option while having no impact on the domain layer of the package.
    With that said, ROS makes available a very well organized model which is useful to the domain beyond the concerns of messaging itself.  For example, our laser scan reader class is only concerned with  reading information from the laser scanning device (e.g., Sick LMS111 or Hokuyo URG-04LX-UG01) and raising the laser scan event data.  Accordingly, regardless of the chosen messaging infrasturcture, the laser reader ultimately needs to encapsulate the laser scan information within a class for intra-package data passing.  The reader could use a custom (domain-specific) class to encapsulate this information, but we’d end up replicating many of the ROS message classes along with an equivalent number of message translators, without much decoupling benefit.  To illustrate, in the unlikely event that the ROS messaging infrastructure needed to be swapped out with another messaging solution, the domain layer could continue using the strongly typed ROS message classes in the domain, using message translator within the message endpoints, to translate between the ROS message classes (and other domain-specific classes we may be using) with the messages required by the messaging infrastructure.  If ROS messages were not strongly typed, being a collection of name/value pairs instead, for example, then I would avoid referencing ROS message classes from within the domain layer.
    So in our example package here, we will slightly ease the rule of strict domain-layer/ROS decoupling and allow the use of ROS message classes from within the domain layer while still avoiding the introduction of any ROS communication details to the domain, such as how to publish to a topic.  This theoretical vs. practical compromise is a discussion that should be had with any project team to carefully decide how strictly decoupling should be enforced on a given package and specifically where the rule may be eased, if and when appropriate.  In this case, the benefits of using the strongly typed ROS message classes were weighed against the introduction of domain-layer coupling to those classes, accordingly.  Keep in mind that any introduction of coupling with the messaging infrastructure should be carefully reviewed, and well justified, before doing so.
  • Lines 18-19:  Declare the methods beginReading() and stopReading() which will provide the ability to start and stop the reader, respectively.
  • Line 22:  Provide a means for laser scan listeners (observers) to register to receive laser scan reports when available.
  • Line 25:  The readLaserScans() function actually does the work of reading laser reports from the laser scanner and raising the laser data events.  We’ll see in the implementation that it’ll be invoked within the beginReading() function.
  • Line 26: notifyLaserScanListeners() has the responsibility of informing all laser scan listeners that a new laser scan is available.
  • Line 28: _laserScanListeners will hold a reference to every laser scan listerner.
  • Lines 32-38:  These members will facilitate the ability to read and raise laser scan events asynchronously. (As a side note, I spent an abhorrent amount of time trying to get Boost::Thread and Boost::signals2 in place for the threading and callback mechanisms within the ROS context. While I got it working most of the time, the intermittent segfault finally made me throw in the towel in favor of pthreads and observer pattern; more on this below.)

4.  Create the LaserScanReader Class Implementation

Add a new class file to /ladar_reporter/src/core called LaserScanReader.cpp containing the following code, which we’ll discuss in detail below.

// LaserScanReader.cpp
 
#include "LaserScanReader.hpp"
 
namespace ladar_reporter_core
{
  LaserScanReader::LaserScanReader()
    : _stopRequested(false), _running(false) {
    _laserScanListeners.reserve(1);
  }
 
  void LaserScanReader::attach(ILaserScanListener& laserScanListener) {
    _laserScanListeners.push_back(&laserScanListener);
  }
 
  void LaserScanReader::beginReading() {
    if (! _running) {
      _running = true;
      _stopRequested = false;
      // Spawn async thread for reading laser scans
      pthread_create(&_thread, 0, readLaserScansFunction, this);
    }
  }
 
  void LaserScanReader::stopReading() {
    if (_running) {
      _running = false;
      _stopRequested = true;
      // Wait to return until _thread has completed
      pthread_join(_thread, 0);
    }
  }
 
  void LaserScanReader::readLaserScans() {
    int i = 0;
 
    while (! _stopRequested) {
      sensor_msgs::LaserScan laserScan;
      // Just set the angle_min to include some data
      laserScan.angle_min = ++i;
      notifyLaserScanListeners(laserScan);
      sleep(1);
    }
  }
 
  void LaserScanReader::notifyLaserScanListeners(const sensor_msgs::LaserScan& laserScan) {
    for (int i= 0; i < _laserScanListeners.size(); i++) {
        _laserScanListeners[i]->onLaserScanAvailableEvent(laserScan);
    }
  }
}

Let’s now review the more interesting parts of the class implementation:

  • LaserScanReader constructor:  The constructor for the LaserScanReader class initializes the _stopRequested member to false.  Since the reading of laser scans will be performed asynchronously, this private member acts as a poor man’s state machine, facilitating a means to stop the reading of laser scans if set to true. In addition to this, the constructor reserves a wee bit of expected space to avoid too much space being allocated upon the first add to the vector.
  • beginReading():  This function will be called to begin the process of reading laser scans from the laser range finder.  The first step of this process sets the _stopRequested member to ensure that the readings won’t stop until requested to do so.  Next, a new thread is begun to execute the readLaserScans() function asynchronously.  I spent a very long amount of time researching different approaches for the simple thread management needed in this class; the most simple and stable solution I found was on stackoverflow.com. (Please let me know if you have a simpler, cleaner – and still stable – solution.)
  • stopReading():  This function does not explicitly stop the laser scan reading process.  Instead, it simply sets the _stopRequested member to false to inform the asynchronous reading process to terminate. The pthread_join() function is called to wait until the thread represented by the thread object has completed.
  • readLaserScans():  In a real package, this function would communicate with the physical range finding device, collect data, and raise laser scan information via the onLaserScanAvailableEvent.  In our example code here, we’ll simply create a number of fake laser scan reports as long as the _stopRequested member does not equal true.

    Note again that by using the observer pattern to raise laser scan events to listeners, the implementation code need not be aware of who a priori is listening for laser scans, only that a means exists to raise laser scan events, accordingly.  Arguably, readLaserScans() could publish laser scans directly to ROS topics. But this approach comes with the drawback of tightly coupling the laser scan reading functionality to the ROS messaging system, it violates the Single Responsibility Principle, and it makes it more difficult to do “any other stuff” (whatever that may be) with the laser scans before they’re handed off to ROS for publishing without further cluttering readLaserScans().  As the package evolves, we’ll see that an application services layer will be put in place to coordinate the task of handling the laser scan events and passing the information onto a message endpoint for publication to ROS.

  • notifyLaserScanListeners(): Raises the laser scan to any observers. Be sure to note that this does not publish laser scans to ROS, but only raises them to registered observers within the package.

5.  Add a ROS sensor_msgs Dependency to manifest.xml

Since the code above refers to sensor_msgs::LaserScan, a dependency needs to be added for the package to use this class, accordingly:

  • Under /ladar_reporter, open manifest.xml and add the following line just before the closing </package> tag:
    <depend package="sensor_msgs" />

6.  Configure CMake to Include both the Header and Implementation

With the header and implementation classes completed, we need to make a couple of minor modifications to CMake for their inclusion in the build.

First, open /ladar_reporter/CMakeLists.txt and make the following modifications:

  1. Under the first line, which sets the cmake_minimum_required, add a new line to set the project name:
    project(ladar_reporter)
  2. At the end of the CMake file:
    # Include subdirectories for headers
    include_directories(
      "src/core"
    )
    
    add_subdirectory(src)

In doing so, the LaserScanReader header has been included for consumption by other classes and application layers.  This inclusion has been done in the root CMakeLists.txt as this will make the headers available to the unit tests as well.  For more complex packages, this approach of including the headers in the root CMakeLists.txt, to make them globally accessible, may become a bit messy; it may be more appropriate to put the header inclusions in only the CMakeLists.txt which actually require the respective headers if the package is larger.

At this point, a new CMake file is needed under /ladar_report/src:

  • Create a new CMakeLists.txt under /ladar_reporter/src, containing the following:
    # Include subdirectories with their own CMakeLists.txt
    add_subdirectory(core)

You’ll quickly notice that this CMake file has merely passed the buck of defining class libraries further down the chain.  Accordingly, a CMakeLists.txt will be setup for each of the package layers including application_services, core, message_endpoints, and ui.  All of these layers will be compiled into separate class libraries and, finally, an executable.  Arguably, all of these layers could be combined into a single executable with a single CMakeLists.txt file.  But keeping them in separate class libraries keeps a clean separation of concerns in their respective responsibilities and makes each aspect of our package more easily testable in isolation from the other layers.

Next, in order to create the core class library, a new CMake file is needed under /ladar_reporter/src/core:

  • Create a new CMakeLists.txt under /ladar_reporter/src/core, containing the following:
    # Create the core library
    add_library(
      ladar_reporter_core
      LaserScanReader.cpp
    )

We’re now ready to compile the class library for the “core” layer of the package…

7.  Build the core Class Library

In a terminal window, cd to /ladar_reporter and run make.  The class library should build and link successfully.

Woohoo!  Done, right?  Well, not yet…time to test our new functionality.

8.  Unit Test the LadarScanReader Functionality

So far, you’ve had to simply assume that a successful build means everything is working as expected.  Obviously, when developing a ROS package, we’ll want a bit more reassurance than a successful build to be confident that the developed capabilities are working as expected.  Accordingly, unit tests should be developed to test the functionality; in the case at hand, a unit test will be developed to initialize, begin and stop the laser reading cycle to ensure that it is raising laser scan events as designed.

The standard ROS testing tool is gtest; this is a great choice as gtest is very easy to setup and provides informative output during unit test execution.  To setup and run unit tests for the package, only two elements are needed:  a “test runner” to act as the unit tests’ main and to execute all of the package unit tests, and the unit tests themselves which may be spread out among a variety of folders and classes.  When unit testing, I typically write one unit testing class (a test fixture) per class being tested.  Furthermore, I include one unit test for each public function or behavior of the class being tested.  As for a couple of other unit testing best practices, be sure to keep the unit tests independent from each other – they should be able to be run in isolation without being dependent on the running of other unit tests.  Additionally, each unit test is organized as three stages of the test:  “establish context” wherein the testing context is setup, “act” wherein the desired behavior is invoked, and “assert” wherein the results of the behavior are verified. Finally, no testing code should be added to the “production” source code itself; all tests should be maintained in a separate executable to keep a clean separation of concerns between application code and tests.  We’ll see an example of this as we proceed.

  1. To begin testing the laser scan reader, first define the test runner by creating /ladar_reporter/test/TestRunner.cpp containing the following:
    #include <gtest/gtest.h>
     
    // Run all the tests that were declared with TEST()
    int main(int argc, char **argv){
      testing::InitGoogleTest(&argc, argv);
      return RUN_ALL_TESTS();
    }
  2. Now that the unit tests’ main is in place, create /ladar_reporter/test/core/LaserScanReaderTests.cpp containing the following testing code:
    #include <gtest/gtest.h>
    #include "LaserScanReader.hpp"
    #include "ILaserScanListener.hpp"
    #include "sensor_msgs/LaserScan.h"
     
    using namespace ladar_reporter_core;
     
    namespace ladar_reporter_test_core
    {
      // Will be used by unit test to handle laser scans
      struct LaserScanReceiver : public ladar_reporter_core::ILaserScanListener
      {
        LaserScanReceiver()
          : countOfLaserScansReceived(0) { }
     
        mutable int countOfLaserScansReceived;
     
        void onLaserScanAvailableEvent(const sensor_msgs::LaserScan& laserScan) const {
          countOfLaserScansReceived++;
     
          // Output the laser scan seq number to the terminal; this isn't the
          // unit test, but merely a helpful means to show what's going on.
          std::cout << "Laser scan sent to LaserScanReceiver with angle_min of: " << laserScan.angle_min << std::endl;
        }
      };
     
      // Define the unit test to verify ability to start and stop the reader
      TEST(LaserScanReaderTests, canStartAndStopLaserScanReader) {
        // Establish Context
        LaserScanReader laserScanReader;
        LaserScanReceiver laserScanReceiver;
     
        // Wire up the reader to the handler of laser scan reports
        laserScanReader.attach(laserScanReceiver);
     
        // Act
        laserScanReader.beginReading();
        // Let it perform readings for a couple of seconds
        sleep(2);
        laserScanReader.stopReading();
     
        // Assert
     
        // Since we just ran the reader for 2 seconds, we should expect a few readings.
        // Arguably, this test is a bit light but makes sure laser scans are being reported.
        EXPECT_TRUE(laserScanReceiver.countOfLaserScansReceived > 0 &&
          laserScanReceiver.countOfLaserScansReceived <= 10);
      }
    }
  3. Then to include the new test in the build, open /ladar_reporter/CMakeLists.txt and add the following to the end of the file:
    add_subdirectory(test)

    As seen before, this has just passed the buck onto subsequent CMake file(s) to include the appropriate files in the build – which is preferred. Ideally, each CMakeLists.txt should only know about its immediate “surroundings” and not have the concerns of subfolders added to it.

  4. Next, create a new CMakeLists.txt file under /ladar_reporter/test containing the following:
    rosbuild_add_executable(
      ladar_reporter_tests
      TestRunner.cpp
      ./core/LaserScanReaderTests.cpp
    )
    
    rosbuild_add_gtest_build_flags(ladar_reporter_tests)
    
    # Link the libraries
    target_link_libraries(
      ladar_reporter_tests
      ladar_reporter_core
    )

    This CMake file instructs the make process to create a stand-alone gtest executable called ladar_reporter_tests, made up of the two files indicated. (As a side note, ROS has a macro called rosbuild_add_gtest which will include and run the tests automatically when compiled with the command make test. I have reliably encountered segfaults when using Boost asynchronous threading and building with rosbuild_add_gtest. Interestingly, I do not run into such problems if I build and run the testing executable separately from the make process. I have thoroughly researched this topic (i.e., thrown laptops through windows), and have found no solution. Moral of the story: use rosbuild_add_executable to create your test executable.)

  5. With everything in place, head back to the terminal and run:
    make
    cd bin
    ./ladar_reporter_tests

When the test runs, you should see a few laser scan angle_min values get printed to the terminal along with the final report that the test successfully passed.

Now that we’ve done all of the above to complete the core domain layer of the package, let’s review what have was accomplished:

  • Header and implementation classes were developed for communicating with the (fake) laser scan range finder;
  • An observer interface was established to allow (yet unseen) observers listen for new laser scans;
  • A unit test was developed, outside of the package source, to test the reader functionality;
  • CMake was configured to compile the artifacts and to run tests with gtest; and
  • Most importantly, we’ve been able to develop and test our core functionality without needing to involve the ROS messaging system (outside of the use of its LaserScan message class) and without having to prematurely develop any UI layers to test the completed code.

In Part IV, we’ll be setting our sights on developing and testing the application services layer of the application with a test double standing in for the ROS messaging system.

Enjoy!
Billy McCafferty

Download the source for this article.

Passing Containing Parent to pImpl Idiom Implementation Class

datePosted on 17:38, April 29th, 2010 by Billy McCafferty

The pImpl Idiom is a useful technique for hiding implementation details of C++ classes away from being exposed in the header file.  A couple of the primary benefits include decoupling of the implementation from the interface of the object (as declared in the header) and reduced compilation time if only the pImpl class is modified.  As a rule of thumb, when using pImpl Idiom, there should be clean separation of any implementation details from the containing class.  Spreading implementation details across both the containing class and the pImpl class muddies the separation of concerns and can quickly lead to maintenance issues, with unclear direction as to what should go into the parent vs. the pImpl class.  Accordingly, public methods declared in the parent should simply act as pass-through methods to pImpl.  I’ve seen arguments that any public method which does not require access to the internal state of pImpl may instead be defined on the parent and not require a pass-through; this sounds reasonable while still providing a gauge for cleanly deciding where implementation definitions should reside (i.e., if it’s a public method which doesn’t require access to pImpl state, define it on the parent).  To that end, there may be scenarios wherein the pImpl class needs to invoke a method or property on the parent.  Accordingly, this post shows how to pass a reference to the parent object to the pImpl object while avoiding a copy of the parent in the process.

The first step is in defining the header class which will expose the public methods and properties along with a forward declaration of the pImpl class:

// LaserScanReader.hpp
 
#ifndef GUARD_LaserScanReader
#define GUARD_LaserScanReader
 
#include <boost/shared_ptr.hpp>
 
namespace ladar_reporter_core
{
  class LaserScanReader
  {
    public:
      ...
 
    private:
      // Forward declare the implementation class
      class LaserScanReaderImpl;
      boost::shared_ptr<LaserScanReaderImpl> _pImpl;
  };
}
 
#endif /* GUARD_LaserScanReader */

Note that the _pImpl member is stored as a boost::shared_ptr so that _pImpl will be destructed automatically when it loses all references to it.

Now that the parent has been declared, we can turn our attention towards the implementation class.

// LaserScanReader.cpp
 
#include "LaserScanReader.hpp"
 
namespace ladar_reporter_core
{
  // Private implementation
  class LaserScanReader::LaserScanReaderImpl
  {
    public:
      explicit LaserScanReaderImpl(const LaserScanReader& laserScanReader);
 
    private:
      // Provides access to methods/properties of parent; e.g., _laserScanReader.someProperty
      const LaserScanReader& _laserScanReader;
  };
 
  LaserScanReader::LaserScanReader()
    // Passes a reference of LaserScanReader to LaserScanReaderImpl (not a copy)
    : _pImpl(new LaserScanReaderImpl(*this)) { }
 
  LaserScanReader::LaserScanReaderImpl::LaserScanReaderImpl(const LaserScanReader& laserScanReader)
    // Initialize the reference to the LaserScanReader (parent object of _pImpl)
    : _laserScanReader(laserScanReader) { }
}

Let’s now look at a few of the interesting points in more detail.

  • The constructor declaration of LaserScanReaderImpl takes a const reference to LaserScanReader, avoiding copying the parent object when passed to it.
  • The private member _laserScanReader holds the reference to the parent object, providing access to it’s public methods and properties, accordingly.
  • The constructor definition of LaserScanReader passes a pointer to itself to the constructor of LaserScanReaderImpl.  While it appears to pass a value pointer, thus creating a copy of itself as the parameter, the fact that the constructor is expecting a reference to LaserScanReader avoids copying the object, accordingly.
  • The constructor definition of LaserScanReaderImpl accepts a reference to the parent object, initializing the member _laserScanReader with that reference, accordingly.

With that, the pImpl class now has access to the parent object’s properties and methods via its _laserScanReader member.

Billy McCafferty

Part II:  Creating the Package Skeleton

In Part I of this series, we examined the overall architecture that will be put in place with the development of the ROS package.  It’s time to get our hands dirty and put the theory hypothesis to work!  Accordingly, this post in the series will focus on putting together the skeletal package which will contain the various layers of the described architecture. If you’d like to skip to the chase and download the source to this article, click here.

Prerequisites:

If you went through the excellently written ROS tutorials (you did, didn’t you?), you’re no doubt aware that ROS brings with it a number of helpers to make our lives easier.  Accordingly, we’ll start by using roscreate-pkg to create the ROS package itself followed by placeholder folders for the remainder of the package.

  1. Open a terminal and cd to where you’d like your package to reside.  You’ll need to put the package in a folder which is included in the ROS environment variable $ROS_PACKAGE_PATH.  (You can check this setting by running echo $ROS_PACKAGE_PATH at a terminal.)  If your destination folder isn’t defined in $ROS_PACKAGE_PATH (or a sub-folder), you’ll need to add it via /opt/ros/cturtle/setup.sh (e.g., export ROS_PACKAGE_PATH=/opt/ros/cturtle/stacks:/home/username/folder).
  2. Create your package as follows:
    roscreate-pkg ladar_reporter
  3. Verify that ROS can find the package:
    rospack find ladar_reporter
  4. Build the new ROS package:
    rosmake ladar_reporter
  5. Now that the package has been created and building successfully, create a folder structure under the root of the package as follows:
    • src:  Will contain all the source files of the package.
    • src/core:  Will contain the core elements of the package including, and most importantly, the domain layer.  (See Part I for more information concerning the domain layer.)
    • src/core/message_endpoint_interfaces:  Will contain the message endpoint interfaces but not their concrete implementations.  (Consequently, the domain layer will only have knowledge of the message endpoint interfaces, decoupling it from the messaging middleware.)
    • src/application_services:  Will contain the service layer of the package.  In a nutshell, the service layer coordinates the application workflow.
    • src/message_endpoints:  Will contain the concrete classes for communicating with the ROS messaging middleware.
    • src/ui:  Will contain the UI for interacting with the package.  (This layer is not needed on all packages.)
    • test:  Will contain the test classes of our package.
    • test/core:  Will contain tests for classes within src/core.
    • test/application_services:  Will contain tests for classes within src/application_services.
    • test/message_endpoints:  Will contain tests for classes within src/message_endpoints.
    • test/message_endpoints/test_doubles:  Will contain test doubles (stubs to be exact) for testing the application services and domain layer independently from ROS.
  6. If using an IDE (e.g., eclipse), follow any additional directions at http://www.ros.org/wiki/IDEs to make the new project compatible with your IDE.

And with that, the package skeleton is now in place.  Folders have been added to represent all of the application layers that will come to fruition over the next few posts, as we see the package evolve.  (Typically, folders would only be added as needed, but this post provides a concise means to see how the end product will be structured.)

In Part III of this series in developing a well-designed ROS package, the domain elements will be added to the core layer with unit testing, accordingly.

Enjoy!
Billy McCafferty

Download the source for this article.

In previous posts, I discussed general patterns of message-based systems along with basic guidance on developing components for such systems.  While these posts may have provided basic information about their respective topics, there’s a clear difference between theory and implementation.  (The former is easier to fake.)  Accordingly, it’s time to get our hands dirty and provide concrete guidance on developing packages for Robot Operating System (ROS) using proven messaging-system and other developmental design patterns.

This post is the first in a number of posts which walks the reader through nearly every facet of developing a package for ROS.  Primary interests of this series will focus on:

  • Layering a ROS package for maintainability and clean separation of concerns,
  • Making your package as reusable (as practical) to be used with any messaging framework by introducing a clean separation between package concerns and the underlying ROS messaging framework,
  • Using separated interface to easily unit test the elements of your package in isolation of each other and of ROS, and
  • Leveraging proven design patterns to develop a solid package which provides a good balance of theoretical best practices and practical development.

A ROS package is a complete application which happens to send and receive messages via messaging middleware (e.g., ROS) to help it complete its job.  This isn’t too different from an application which simply retrieves and saves data to a database.  Accordingly, the development of the package deserves the same design considerations that a stand-alone application would should receive.  This series of blogs will walk the reader through the development of a package, taking into such considerations, appropriately.  This will be a six part series include:

At the end of this series, the reader should feel comfortable with the concepts behind designing and developing an extensible and maintainable ROS package adhering to proven design patterns and solid coding practices.

A Ladar Reporting Package

Before delving straight into implementation, it’s important to establish the context of the project to assist in guiding architectural and developmental decisions.  Accordingly, the package that will be developed will be a ladar reporting package.  The requirements of the package are simple enough:

  • The package will read laser reports coming from a laser range-finder.
  • Reports acquired from the laser range-finder will be published to a ROS topic as LaserScan messages.
  • The user may start and pause the ladar reporting process via a simple UI front-end.

Our first stop will be in examining the overall architecture of the package in order to conceptualize how the end product will be layered and developed.



Part I:  Planning the Package Architecture

When developing any application, it’s important to strike the appropriate balance between extensibility and maintainability.  We’ve all seen as many “over-architected” solutions as those that did not receive a single thought toward design.  Such applications usually meet their demise in the middle of the night when a wearied developer throws up their hands in debugging exhaustion before starting The (infamous) Rewrite.  Accordingly, when designing a package, “just enough” prefactoring should take place to architect a solution that will smoothly evolve to meet the package’s requirements without over-complicating the solution.  For the task at hand, when architecting a ROS package, there are a number of minimal architectural guidelines which should be adhered to which will lead to a extensible messaging component while being maintainable and easy to understand; a few guiding principles are as follows:

  • A domain layer should exist to encapsulate the core capabilities of the package.  Excellent guidance for developing the domain layer may be found in Eric Evan’s Domain Driven Design.  See Domain Driven Design Quickly for just that.
  • The domain layer of the package should not have knowledge concerning how to communicate with the messaging middleware directly (e.g., ROS).  This implies that the domain layer should have no direct dependencies on the messaging middleware.  This allows the domain layer to be more easily reused with another messaging middleware solution.  Additionally, keeping this clean separation of concerns facilitates the testing of the domain layer independently from its interactions with the messaging middleware.
  • An application services layer should be responsible for managing application “workflow.”  An example is accepting data generated by the domain layer and passing it on to the messaging middleware.  Even then, the application services should only communicate with the messaging middleware (e.g., ROS) via message endpoint interfaces.  Likewise, if the application services need to communicate to a database or other data source, they should do so via data repository interfaces.  This use of separated interface provides the same decoupling benefits as those described for the domain layer.  Admittedly, the application services layer is the trickiest layer to cleanly define the boundry of – it should not contain anything related to the UI (e.g., it should have no references to wxWidgets) nor should it contain any business logic.  A simple way to visualize the responsibilities of the application services layer is to see it as a “task manager.”  I.e., it’s responsible for ensuring that all steps of a given task are completed but is unaware of how to do the work itself; kind of like your manager at work, right?  The execution of the task steps themselves are then carried out by elements of the domain layer and, as we’ll see, the message endpoint concrete implementations.
  • Everything should be independently testable (and tested) from service dependencies.  Accordingly, message endpoints, and other external service dependencies, should be injected into the application services layer via dependency injection.  Doing so facilitates the testing of the application services and domain layers using test doubles.  (To keep things justifiably simpler, we will not be using an IoC container for dependency injection, but manual dependency injection instead.)

At first glance, this may appear to be a lot more than just “minimal prefactoring.”  But after more than a dozen years of professional development, and many painful lessons along the way, I can assure you that this is a solid approach to architecting your package.  With that said, I certainly encourage you and your team to discuss what architectural approach is most appropriate for the task at hand – and the capabilities of the team – before agreeing upon a particular approach.

The best way to further discuss how the architectural guidelines will be implemented in the package, is to review a UML package diagram expressing all of the layers and the direction of dependencies, accordingly:

Keep in mind that this is not a diagram for the overall message-based system; this represents how each individual ROS package is architected.  Accordingly, in the above UML package diagram, each box represents a separate library encapsulating a distinct functional concern.  The arrows represent the direction of dependencies; e.g., application_services depends on core.  Let us now review each layer in more detail, beginning from the bottom up.

Core

As described previously, the domain layer encapsulates the core capabilities of the package.  For instance, if this were a package providing SLAM capabilities, then this layer would contain the associated algorithms and logic.  In addition to domain logic, the core library contains interfaces for services which depend on external resources, such as message endpoints and (if applicable) data repositories.  Having interfaces in the core library allow both core and the application services layers to communicate with services while remaining loosely coupled to the implementation details of those services.

Application Services

As described previously, the application services layer acts as the “task manager” of the application, delegating execution responsibilities to the domain layer and services.  Note that the application services layer, similar to core, has no direct dependency on the service implementation classes, e.g., the message endpoints.  It only has knowledge of the service interfaces for remaining loosely coupled and for facilitating unit testing.

Arguably, in smaller packages and applications, an application services may not add much value and simply complicate an otherwise simpler design.  With that said, care should be taken at the beginning of a project to fully consider the pros and cons of including an application services layer before deciding to discard its use, accordingly.

Data Repositories

If the package were to retrieve and save data to a database or other external data source, data repositories would encapsulate the details of communicating with the external data source.  Note that the data repositories implement the repository interfaces defined in core.

Message Endpoints

This library contains the concrete implementations of the message endpoints.  The message endpoints are the only classes which actually know how to publish, subscribe, and otherwise communicate with the ROS messaging middleware.  Note that the message endpoints implement the endpoint interfaces defined in core.

UI

This layer contains the user interface for interacting with the package, if needed.

Tests

Finally, this library contains all of the unit tests for testing all layers of the ROS package.

This is our package architecture in a nutshell.  In the next post, we’ll begin developing each layer from Core on up to the UI, starting with the overall package structure itself.

Billy McCafferty

Including Boost.Test in Your C++ Project

datePosted on 05:08, April 20th, 2010 by Billy McCafferty

It’s certainly hard to find much fault with the libraries of Boost.  They’re easy to include, they add a terrific amount of power to the STL, and they come with extensive documentation and a thriving community to boost your efforts.  (Awkward pun intended.)  Just about the only library (so far) that I’ve had a hard time finding clear, concise, introductory materials on is Boost.Test.  Boost.Test is a terrific library for facilitating unit testing with your C++ project.  Once you get it setup in your project, Boost.Test makes it very easy to develop and organize unit tests for your project.  But while the Boost.Test documentation will make you a guru with the library, it’s quite a bit lacking in guiding you in getting it going in your project for the very first time.  Googling for direction will lead you (er…led me anyway) down a number of paths which seemed to be overly complex…hopefully this post will help a few people in a similar situation that I was in.

What follows are the fewest steps that I was able to determine for including Boost.Test in your C++ project.  My setup was using CMake 2.8 on Ubuntu 9.04.

  1. Download and install Boost following Boost’s online documentation.
  2. Create a folder for your tests, e.g., my_project_tests and include a file in it called TestRunner.cpp containing the code below.   When compiled, this “main” class invokes Boost to generate a true main() function for your unit tests and establishes the central testing module.  TestRunner.cpp won’t actually contain any tests, it simply consolidates initialization code that would otherwise be duplicated across your test files and better allows them to be run together.
    #define BOOST_TEST_DYN_LINK
    
    #define BOOST_TEST_MODULE "my_project Unit Tests"
    #include <boost/test/unit_test.hpp>
    
  3. Create a file called ExampleTests.cpp in the same folder containing the code below.  This is taken directly from the Boost.Test tutorial with the omission of the test module #define, which was done via TestRunner.cpp.  To add any more tests, you simply create new .cpp files to hold the respective tests and include a reference to the files in your CMakeLists.txt file, as described in the next step.  But first, ExampleTests.cpp:
    #include <boost/test/unit_test.hpp>
    
    int add( int i, int j ) { return i+j; }
    
    BOOST_AUTO_TEST_CASE( my_test )
    {
      // seven ways to detect and report the same error:
      BOOST_CHECK( add( 2,2 ) == 4 );        // #1 continues on error
      BOOST_REQUIRE( add( 2,2 ) == 4 );      // #2 throws on error
    
      if( add( 2,2 ) != 4 )
         BOOST_ERROR( "Ouch..." );            // #3 continues on error
    
      if( add( 2,2 ) != 4 )
        BOOST_FAIL( "Ouch..." );             // #4 throws on error
    
      if( add( 2,2 ) != 4 ) throw "Ouch..."; // #5 throws on error
    
      BOOST_CHECK_MESSAGE( add( 2,2 ) == 4,  // #6 continues on error
        "add(..) result: " << add( 2,2 ) );
      BOOST_CHECK_EQUAL( add( 2,2 ), 4 );      // #7 continues on error
    }
  4. In the folder containing TestRunner.cpp, create a CMakeLists.txt containing the code below; this assumes that the CMake version and your project name is defined in a CMakeLists.txt in a parent folder.
    # Include subdirectories for headers
    include_directories(
     "/usr/local/boost_1_42_0"
    )
    
    # Create the unit tests executable
    add_executable(
     my_project_tests
     # Key includes for setting up Boost.Test
     TestRunner.cpp
     # Just for handy reference
     ExampleTests.cpp
    )
    
    # Link the libraries
    target_link_libraries(
     my_project_tests
    
     # "mt" designates that multi-threaded is supported with this Boost library
     boost_unit_test_framework-mt
    )
    
  5. Now, simply cmake, make and run the resulting executable to run your unit tests.

Happy testing!

Billy McCafferty

1234PreviousNext

© 2011-2014 Codai, Inc. All Rights Reserved