0
$\begingroup$

Rosanswers logo

I am trying to work through the simple plugin example (http://wiki.ros.org/pluginlib/Tutorials/Writing%20and%20Using%20a%20Simple%20Plugin) but cannot get it to build for ROS2.

Trying to use https://docs.ros.org/en/foxy/Guides/Ament-CMake-Documentation.html and the details in the tutorial, but I have limited CMake experience and cannot get it to build. Are there available examples that use ROS2?

Any help would be greatly appreciated.

EDIT

Been trying to piece together a few different resources and have got things to build, but now the library can't be found so I must be doing something wrong.

The plugin failed to load for some reason. Error: %sCould not find library corresponding to plugin 

I've set up two packages, once containing the base class and one containing the plugins

Folder structure

src
-controller
 -include
  -Controller.h
 -src
  -ControlFramework.cpp
 CMakeLists.txt
 package.xml
-linear_controller
 -include
  -LinearController1.h
  -LinearController2.h
 -src
  -LinearController1.cpp
  -LinearController2.cpp
 CMakeLists.txt
 linear_controller_plugins.xml
 package.xml

Base Class

Controller.h

#pragma once

namespace control_base
{
    class Controller
    {
    public:
        Controller() {};
        virtual ~Controller() {};

        virtual bool initialize(double p, double i, double d) = 0;
        virtual double computeFeedback(double error) = 0;
    };
}

ControlFramework.cpp

#include <iostream>
#include <pluginlib/class_loader.hpp>
#include <controller/Controller.h>


using namespace std;

int main(int argc, char** argv)
{
  pluginlib::ClassLoader<control_base::Controller> poly_loader("linear_controller", "control_base::Controller");

  try
  {
    std::shared_ptr<control_base::Controller> triangle = poly_loader.createSharedInstance("control_plugins::LinearController1");
    triangle->initialize(10.0, 0.0, 0.0);

    std::shared_ptr<control_base::Controller> square = poly_loader.createSharedInstance("control_plugins::LinearController2");
    square->initialize(5.0, 0.0, 0.0);

    cout << "Triangle area: %.2f" << triangle->computeFeedback(2.0);
    cout << "Square area: %.2f" << square->computeFeedback(2.0);
  }
  catch(pluginlib::PluginlibException& ex)
  {
    cout << "The plugin failed to load for some reason. Error: %s" << ex.what();
  }

  return 0;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.5)
project(controller)

# Default to C++14
if(NOT CMAKE_CXX_STANDARD)
  set(CMAKE_CXX_STANDARD 14)
endif()

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()

# find dependencies
find_package(ament_cmake REQUIRED)
find_package(pluginlib REQUIRED)

#Include directories
include_directories(
  include
)

set(plugins_dependencies
  pluginlib
)

add_executable(${PROJECT_NAME} 
  src/ControlFramework.cpp
)
ament_target_dependencies(${PROJECT_NAME} ${plugins_dependencies})


install(TARGETS ${PROJECT_NAME}
  DESTINATION lib/${PROJECT_NAME}
)

install(DIRECTORY include/
  DESTINATION include/
)

ament_package()

package.xml

<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
  <name>controller</name>
  <version>0.0.0</version>
  <description>TODO: Package description</description>
  <maintainer email="[email protected]">angus</maintainer>
  <license>TODO: License declaration</license>

  <buildtool_depend>ament_cmake</buildtool_depend>
  
  <depend>pluginlib</depend>

  <test_depend>ament_lint_auto</test_depend>
  <test_depend>ament_lint_common</test_depend>

  <export>
    <build_type>ament_cmake</build_type>
  </export>
</package>

Plugin Package

LinearController1.h

#pragma once

#include <pluginlib/class_list_macros.hpp>
#include <controller/Controller.h>                      // Inheriting the base class

namespace control_plugins
{
  class LinearController1 : public control_base::Controller {
  public:
    LinearController1() {};                               // Constructor
                                                          // No destructor!
    bool initialize(double p, double i, double d);         
    double computeFeedback(double error);

  private:
    double _p_gain{0};
    double _i_gain{0};
    double _d_gain{0};
  };
}

LinearController1.cpp

#include <linear_controller/LinearController1.h>

namespace control_plugins 
{
  bool LinearController1::initialize(double p, double i, double d)
  {
    _p_gain = p;
    _i_gain = i;
    _d_gain = d;

    return true;
  }

  double LinearController1::computeFeedback(double error)
  {
    return error*_p_gain;
  }
}

PLUGINLIB_EXPORT_CLASS(control_plugins::LinearController1, control_base::Controller)

CMakeLists.txt

cmake_minimum_required(VERSION 3.5)
project(linear_controller)

# Default to C++14
if(NOT CMAKE_CXX_STANDARD)
  set(CMAKE_CXX_STANDARD 14)
endif()

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()

#Find dependencies
find_package(ament_cmake REQUIRED)
find_package(pluginlib REQUIRED)
find_package(controller REQUIRED)

include_directories(
  include
  ../controller/include
)

set(plugins_dependencies
  pluginlib
  controller
)

add_library(${PROJECT_NAME}
  src/LinearController1.cpp
  src/LinearController1.cpp
)
ament_target_dependencies(${PROJECT_NAME} ${plugins_dependencies})

install(TARGETS ${PROJECT_NAME}
  ARCHIVE DESTINATION lib
  LIBRARY DESTINATION lib
  RUNTIME DESTINATION lib
)
install(DIRECTORY include/
  DESTINATION include/
)
install(FILES linear_controller_plugins.xml
  DESTINATION share
)

ament_export_include_directories(include)
ament_export_libraries(${PROJECT_NAME})
pluginlib_export_plugin_description_file(linear_controller linear_controller_plugins.xml)

ament_package()

package.xml

<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
  <name>linear_controller</name>
  <version>0.0.0</version>
  <description>TODO: Package description</description>
  <maintainer email="[email protected]">angus</maintainer>
  <license>TODO: License declaration</license>

  <buildtool_depend>ament_cmake</buildtool_depend>

  <depend>pluginlib</depend>
  <depend>controller</depend>




  <test_depend>ament_lint_auto</test_depend>
  <test_depend>ament_lint_common</test_depend>

  <export>
    <build_type>ament_cmake</build_type>
    <controller plugin="${prefix}/linear_controller_plugins.xml" />
  </export>
</package>

linear_controller_plugins.xml

<library path="/liblinear_controller">
  <class type="control_plugins::LinearController1" base_class_type="control_base::Controller">
    <description>LinearController1 for control</description>
  </class>
  <class type="control_plugins::LinearController2" base_class_type="control_base::Controller">
    <description>LinearController2 for control</description>
  </class>
</library>

Originally posted by GusBus on ROS Answers with karma: 63 on 2021-06-11

Post score: 2

$\endgroup$

1 Answer 1

0
$\begingroup$

Rosanswers logo

So Using the diff_drive_controller I made quite a few changes to get things working:

Created Separate packages for plugins, base and executable: linear_controller (Contains Plugins) controller (Contains Base Class) control_framework (Contains Executable)

I then got the controller CMake to look very similar tot he controller_interface CMake and treated it as an exported library

One error I had in the code that I think was actually a large part of the problem was:

pluginlib::ClassLoader<control_base::Controller> ctrl_loader("linear_controller", "control_base::Controller");

Changed to name the right package containing the base class:

pluginlib::ClassLoader<control_base::Controller> ctrl_loader("controller", "control_base::Controller");

Thanks for the help and pointing me in the right direction!


Originally posted by GusBus with karma: 63 on 2021-06-14

This answer was ACCEPTED on the original site

Post score: 0

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.