## repository: https://code.ros.org/svn/wg-ros-pkg <<PackageHeader(pr2_controller_interface)>> <<TableOfContents(3)>> == The controller interface == To implement a real time controller, your controller needs to inherit from the `pr2_controller_interface::Controller` base class. The base class contains * four methods you need to implement: init, starting, update and stopping, and * one method you can call: getController. The base class looks like this: {{{ #!cplusplus block=controller namespace pr2_controller_interface { class Controller { public: virtual bool init(pr2_mechanism_model::RobotState *robot, ros::NodeHandle &n); virtual void starting(); virtual void update(); virtual void stopping(); bool getController(const std::string& name, int sched, ControllerType*& c); }; } }}} The image below gives the flowchart that shows in what order these four methods are called (more details in the text below). {{attachment:controllers.png||width=550}} === Initializing the controller === The `init` method is executed in '''non-realtime'''. <<CodeRef(controller, 6, 7)>> The `init` method is called when you load a controller, to initialize the controller. Note that initializing a controller is independent of starting it: the initialization can be done any amount of time before starting the controller. The `init` method takes two arguments: * '''robot''': this is a `pr2_mechanism_model::RobotState` that describes the robot model (see [[pr2_mechanism_model]]). The model provides access to the robot joints (actuators, encoders, etc.), and contains a kinematic/dynamic description of the robot mechanism. * '''n''': this `ros::NodeHandle` is the "namespace" of the controller. In the namespace of this node handle, the controller can read configuration from the parameter server, advertise topics, etc. The `init` method returns if the initialization was successful or not. If the initialization fails, the controller will get unloaded by [[pr2_controller_manager]]. Make sure to always use `ROS_ERROR("explanation");` to inform the user why your controller failed to initialize. A controller can only be initialized once. If you want to re-initialize a controller, you first need to unload it, and then load it again. === Starting the controller === The `starting` method is executed in '''hard realtime'''. <<CodeRef(controller, 8, 8)>> The starting method is called once every time a controller is started, by the [[pr2_controller_manager|controller manager]]. Starting is executed in the same cycle as the first update call, right before this update call. The `starting` method initializes the controller right before the first time update is called. The [[pr2_controller_manager|controller manager]] is allowed to re-start a controller at a later time, without having to unload/load the controller. === Updating the controller === The `update` method is executed in '''hard realtime'''. <<CodeRef(controller, 9, 9)>> The `update` method of every controller is called periodically by [[pr2_controller_manager]] at a frequency of 1000 Hz. This means that the execution time of all controllers combined cannot take more than 1 mili-second. In the update loop, the real control work is done. === Stopping the controller === The `stopping` method is executed in '''hard realtime'''. <<CodeRef(controller, 10, 10)>> The `stopping` method is called once every time a controller is stopped. Stopping is executed in the same cycle as the last update call, right after this update call. The `stopping` method does not return anything, it is not allowed to fail. === Requesting a pointer to another controller === The `getController` method is executed in '''non-realtime'''. <<CodeRef(controller, 12, 14)>> The `getController` method allows a controller to get a pointer to another controller. This is used to create a "chain" of controllers, where each controller sends its output to the next controller, '''in realtime'''. This system is a poor replacement of the non-realtime ROS communication. The `getController` method takes three arguments: * '''name''': a string with the name of the controller you would like to get a pointer to. * '''sched''': An int (ENUM) this specifies if the requested controller should be executed before or after your controller. Possible values are `pr2_controller_interface:BEFORE_ME` and `pr2_controller_interface::AFTER_ME`. * '''c''' This is a pointer to the controller you requested, with the type matching the type of the requested controller. The type is also the template argument for the `getController` method. ## AUTOGENERATED DON'T DELETE ## CategoryPackage ## CategoryPackageWG ## controller interface controller interface ## controller interface controller interface ## controller interface controller interface ## controller interface controller interface ## controller interface controller interface ## controller interface controller interface ## controller interface controller interface ## controller interface controller interface ## controller interface controller interface ## controller interface controller interface ## controller interface controller interface ## controller interface controller interface ## controller interface controller interface ## controller interface controller interface