ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
0

Trouble loading Custom Controller with Suscriber

asked 2020-12-07 23:31:53 -0500

ofx gravatar image

updated 2020-12-13 18:56:03 -0500

jayess gravatar image

Hi!

I have been trying to implement my own controller for a 6 wheel robot. I have been using various examples to implement the code, notably the Valkyrie and Packt tutorials, as well as the diff_drive_controller. I am running ROS_Melodic on Ubuntu 18.04 on a Jetson TX2. Using gazebo for the robot simulation.

When adding the suscribe line "sub_command_ = n.subscribe("/ground_truth/state", 1, &Controller_6202::ground_truth_Callback, this);" , the launch file fails to load the controller with the error:

[ERROR] [1607403971.165081452, 0.381000000]: Could not load class 'controller_6202_ns/Controller_6202': Failed to load library /home/polyorbite/catkin_ws/devel/lib//libcontroller_6202_lib.so. Make sure that you are calling the PLUGINLIB_EXPORT_CLASS macro in the library code, and that names are consistent between this macro and your XML. Error string: Could not load library (Poco exception = /home/polyorbite/catkin_ws/devel/lib//libcontroller_6202_lib.so: undefined symbol: _ZN18controller_6202_ns15Controller_620221ground_truth_CallbackERKN5boost10shared_ptrIKN8nav_msgs9Odometry_ISaIvEEEEE) [ERROR] [1607403971.165271469, 0.381000000]: Could not load controller 'controller_6202_name' because controller type 'controller_6202_ns/Controller_6202' does not exist

This is the cpp file implementation for the callback

//Ground_truth_Callback
void ground_truth_Callback(const nav_msgs::Odometry::ConstPtr& msg)
{

    [...]
}   
//Controller initialization
bool Controller_6202::init(hardware_interface::EffortJointInterface* hw, ros::NodeHandle &n)
{
    effortJointHandles.clear();

    //Retrieve the joint object to control
    std::vector<std::string> jointNames;


    if(n.getParam("joints", jointNames))
    {   
        if(hw)
        {
            for(unsigned int i=0; i < jointNames.size(); ++i)
            {
                //Ici, les roues gauches sont aux positions 0 à 3
                effortJointHandles.push_back(hw->getHandle(jointNames[i]));
            }

            buffer_command_effort.resize(effortJointHandles.size(), 0.0);
            buffer_current_positions.resize(effortJointHandles.size(), 0.0);
            buffer_current_velocities.resize(effortJointHandles.size(), 0.0);
            buffer_current_efforts.resize(effortJointHandles.size(), 0.0);
      }
      else
      {
          ROS_ERROR("Effort Joint Interface is empty in hardware interace.");
          return false;
      }
   }
   else
   {
      ROS_ERROR("No joints in given namespace: %s", n.getNamespace().c_str());
      return false;
   }

//Suscribe to ground truth
sub_command_ = n.subscribe("/ground_truth/state", 1, &Controller_6202::ground_truth_Callback, this);

return true;
}

When the suscribe line is removed, there is no error and the controller seems to work fine (without the subscription to the ground truth of course.

sub_command_ and ground_truth_Callback have both been defined in the .h file:

#pragma once

#include <controller_interface/controller.h>
#include <hardware_interface/joint_command_interface.h>
#include <pluginlib/class_list_macros.h>
#include <ros/node_handle.h>

#include <iostream>
#include <nav_msgs/Odometry.h>
#include <tf/tf.h>

namespace controller_6202_ns {

    class Controller_6202: public controller_interface::Controller<hardware_interface::EffortJointInterface>
    {
    public:
        //Controller_6202();
        //virtual ~Controller_6202();
        bool init(hardware_interface::EffortJointInterface* hw, ros::NodeHandle &n);
        void update(const ros::Time& time, const ros::Duration& period);
        void starting(const ros::Time& time);
        void stopping(const ros::Time& time);

        void ground_truth_Callback(const nav_msgs::Odometry::ConstPtr& msg);
        double * getTorque(const ros::Duration& period);

    private:
        std::vector<hardware_interface::JointHandle> effortJointHandles;
        std::vector<double> buffer_command_effort;
        std::vector<double> buffer_current_positions;
        std::vector<double> buffer_current_velocities;
        std::vector<double> buffer_current_efforts;
        //double u;
        //double v;
        //double r;
        ros::Subscriber sub_command_;
    };
}

My package.xml has these included:

    <buildtool_depend>catkin</buildtool_depend>
  <build_depend>controller_interface</build_depend>
  <build_depend>pluginlib</build_depend>
  <build_depend>roscpp</build_depend>
  <build_depend>nav_msgs</build_depend>
  <build_depend>std_msgs</build_depend>

  <build_export_depend>controller_interface</build_export_depend>
  <build_export_depend>pluginlib</build_export_depend>
  <build_export_depend>roscpp</build_export_depend>
  <build_export_depend>nav_msgs</build_export_depend>
  <build_export_depend>std_msgs</build_export_depend>

  <exec_depend>controller_interface</exec_depend>
  <exec_depend>pluginlib</exec_depend>
  <exec_depend>roscpp</exec_depend>

  <exec_depend>std_msgs</exec_depend>
  <exec_depend>nav_msgs</exec_depend>

  <!-- The export tag contains other, unspecified, tags -->
  <export>
        <controller_interface plugin="${prefix}/controller_plugins.xml" />

  </export>

CMakeLists ... (more)

edit retag flag offensive close merge delete

Comments

This is a linker error. Are you linking to all required libraries?

gvdhoorn gravatar image gvdhoorn  ( 2020-12-08 04:05:51 -0500 )edit

What do you mean by linking to all required libraries? I have added the packages "std_msgs" and "nav_msgs" to both CMakeLists.txt (find_package) and package.xml (build_depend and exec_depend)

ofx gravatar image ofx  ( 2020-12-08 09:55:14 -0500 )edit

@ofx can you please update your question with your CMakeLists.txt file?

jayess gravatar image jayess  ( 2020-12-13 17:37:36 -0500 )edit

Updated! I have just tried changing the message type to geometry_msg_twist, and it does not work either, with the message changed to:

libcontroller_6202_lib.so: undefined symbol: _ZN18controller_6202_ns15Controller_620221ground_truth_CallbackERKN13geometry_msgs6Twist_ISaIvEEE)
ofx gravatar image ofx  ( 2020-12-13 18:48:57 -0500 )edit

1 Answer

Sort by » oldest newest most voted
1

answered 2020-12-14 01:03:56 -0500

mgruhler gravatar image

The implementation for you Callback is missing the class prefix:

//Ground_truth_Callback
void ground_truth_Callback(const nav_msgs::Odometry::ConstPtr& msg)

should be

//Ground_truth_Callback
void Controller_6202::ground_truth_Callback(const nav_msgs::Odometry::ConstPtr& msg)

This is why the linker reports and undefined symbol. It is looking inside the class, but there is no implementation of the function.

edit flag offensive delete link more

Comments

Can't believe I missed it! Thanks it works now.

ofx gravatar image ofx  ( 2020-12-14 08:53:41 -0500 )edit

Question Tools

1 follower

Stats

Asked: 2020-12-07 23:31:53 -0500

Seen: 92 times

Last updated: Dec 14 '20