Software Design

Servo Clock

To maximize the number of ways the servo thread can be instantiated (e.g., via ROS::Timer, std::chrono::high_resolution_clock, Orocos RTT, RTAI, Xenomai, etc.), we employ a ServoClock interface.  It defines the interface for all servo threads:


Instances of ServoClock that implement the details are located in rapid_servo_clock_library and are dynamically loaded via ROS’ pluginlib.

Robot Interface

To maximize the number of robots that RAPid can be used with, we employ a RobotInterface interface.  It defines the interface for interacting with the robot:


#include "ros/ros.h"

namespace rapid {

// Forward declarations
class RTControlModel;
class RobotState;
class Command;

 * The top-level definition of a RAPid robot interface.  This class specifies the
 * methods that all robot interface clases must implement.
class RobotInterface
     * The constructor.

     * The destructor.
    virtual ~RobotInterface();

     * Initializes this robot interface.
     * \param[in] nh The ROS node handle to use during the initialization
     * process.
     * \param[in] model The robot model.
     * \return Whether the initialization was successful.
    virtual bool init(ros::NodeHandle & nh, RTControlModel * model);

     * Obtains the current state of the robot.
     * \param[in] time The current time.
     * \param[out] latestRobotState The variable in which to store the latest robot state.
     * \param[in] block Whether to block waiting for message to arrive.
     * \return Whether the read was successful.
    virtual bool read(const ros::Time & time, RobotState & latestRobotState, bool block = false) = 0;

     * Sends a command to the robot.
     * \param[in] time The current time.
     * \param[in] command The command to send to the robot.
     * \return Whether the write was successful.
    virtual bool write(const ros::Time & time, const Command & command) = 0;

     * Whether the controller is initialized.
    bool initialized;

     * The name of the controller.  This is useful for creating a ROS node handle.
    std::string controllerName;

     * The robot control model.
    RTControlModel * model;

     * For receiving Odometry information
    std::unique_ptr odometryStateReceiver;

} // namespace rapid


Instances of RobotInterface that implement the details are located in rapid_robot_interface_library and are dynamically loaded via ROS’ pluginlib.

Reception of Odometry Data

The odometry data is received by the RobotInterface and can be generalized to receive the data from other transport layers like shared memory.

Here is the super-class of all odometry state receivers:


It currently has one child class that obtains odometry data via a ROS topic:


Josh will implement another child class called OdometryStateReceiverSM.hpp that obtains the data from shared memory.

RobotInterface.hpp now contains a pointer to an OdometryStateReceiver.  Child classes of RobotInterface (i.e., RobotInterfaceROSTopic, RobotInterfaceSM, and RobotInterfaceUDP) can instantiate any type of OdometryStateReceiver to obtain odometry information.

RobotInterfaceROSTopic, RobotInterfaceSM, and RobotInterfaceUDP contains the following: 

  1. At the end of init(...), they instantiate a OdometryStateReceiverROSTopic object.  This can be changed to instead instantiate a OdometryStateReceiverSM.
  2. The read(...) method calls odometryStateReceiver->getOdometry(...)