Main Application#

The specific use case application, also known as the decisional program, must adhere to certain rules to integrate with the RVC Framework.

Main Application Development#

This RVC Component is centered around the motion controller aspect of the RVC Framework. The workflow, in a high-level detail, is as follows:

  • An API message, output rvc_messages, is received.

  • The active grasp plugin computes the pre-grasp and grasp pose for the gripper, also known as the Tool Center Point (TCP).

  • A State machine or an equivalent programmatic approach is used to decide actions and, if applicable, move the robot to the pre-grasp and then grasp positions, activating the gripper via the selected RVCMotionController::RVCMotionControllerInterface based plugin.

State Machine Snippet#

The ROS2 node that implements the decisional process needs to load two plugins according to ROS2 parameters. These parameters can be loaded via a launcher, command line, or yaml file.

Example in C++#

#include "rvc_dynamic_motion_controller_use_case/state_machine.hpp"

#include "rvc_motion_controller_interface/rvc_motion_controller_interface.hpp"
#include "rvc_grasp_interface/rvc_grasp_interface.hpp"
#include <pluginlib/class_loader.hpp>

int main(int argc, char ** argv)
{
    rclcpp::init(argc, argv);

    auto stateMachine = std::make_shared<StateMachine>();

    stateMachine->declare_parameter<std::string>("motion_controller",
        "RVCMotionController::Moveit2ServoMotionController");
    stateMachine->declare_parameter<std::string>("grasp_plugin", "RVCControl::NonOrientedGrasp");
    std::string motionControllerName = stateMachine->get_parameter("motion_controller").as_string();
    std::string graspPluginName = stateMachine->get_parameter("grasp_plugin").as_string();

    pluginlib::ClassLoader<RVCMotionController::RVCMotionControllerInterface> motionControllerLoader(
        "rvc_motion_controller_interface", "RVCMotionController::RVCMotionControllerInterface");
    std::shared_ptr<RVCMotionController::RVCMotionControllerInterface> motionController;
    pluginlib::ClassLoader<RVCControl::RVCGraspInterface> graspLoader("rvc_grasp_interface",
        "RVCControl::RVCGraspInterface");
    std::shared_ptr<RVCControl::RVCGraspInterface> graspPlugin;

    motionController = motionControllerLoader.createSharedInstance(motionControllerName);

    if (!motionController->init(stateMachine))
    {
        return 1;
    }

    graspPlugin = graspLoader.createSharedInstance(graspPluginName);

    if (!graspPlugin->init(stateMachine))
    {
        return 1;
    }

    bool ret = stateMachine->init(motionController.get(), graspPlugin.get());

    if (ret)
    {
        rclcpp::spin(stateMachine);
    }

    rclcpp::shutdown();

    return 0;
}

This application will create an instance of a “StateMachine” class, inheriting from rclcpp::Node from ROS2 framework [TODO: link], and passing the smart pointers of the grasp and motion controller Interface instances.

For Example

#include "rclcpp/rclcpp.hpp"

class StateMachine : public rclcpp::Node
{
private:

    /// @brief internal run function to be called on a fixed timer to handle the state machine
    void run(void);
public:
    /// @brief Constructor, parameterless
    StateMachine();
    bool init(RVCMotionControllerInterface *motionController, RVCControl::RVCGraspInterface *graspPlugin);
};

where init will store the interface references and start the state machine internal processing.

Two more practical example are redistributed with rvc_dynamic_motion_controller_use_case and rvc_static_motion_controller_use_case state_machine.cpp and .hpp