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

Plug-in Organization?

asked 2012-10-10 10:49:57 -0600

Dustin gravatar image

updated 2012-10-10 17:44:16 -0600

jbohren gravatar image

I just got my plug-in to work! I used a layout very similar to that found in the plug-in tutorial. However I put the function definitions into a cpp file. This resulted in the following error upon executing my node.

bin/quad_control: symbol lookup error: /home/dustin/ros_workspace/quad_control \
/lib/libquad_controllers.so: undefined symbol: \
_ZN20quad_controller_base14QuadControllerC2Ev

I found that if I moved the function definitions for the base class into the associated h file all works well. Which brings me to my question. Is there an alternative, possibly better, method for handling this issue?

edit retag flag offensive close merge delete

Comments

What does your CMakeLists.txt look like?

jbohren gravatar image jbohren  ( 2012-10-10 16:55:42 -0600 )edit

The only line relevant to the plug-in would be

rosbuild_add_library(quad_controllers src/quad_controllers_plugins.cpp)

Note that my base class function definitions were in src/quad_controllers_base.cpp but are now in include/quad_control/src/quad_controllers_base.h per the above.

Dustin gravatar image Dustin  ( 2012-10-10 17:02:35 -0600 )edit

1 Answer

Sort by ยป oldest newest most voted
2

answered 2012-10-10 17:43:54 -0600

jbohren gravatar image

So your program is failing when the constructor of your base class, quad_controller_base::QuadController gets called on instantiation of the derived class that you've dynamically loaded. It sounds like it's failing because this constructor is defined in the .so instead of the executable, and linking across that boundary is causing a problem.

Regardless of the above issue, I don't think this is what you want to be doing. Assuming you're trying to make it so that you can dynamically load different quadcopter controllers via pluginlib, a good pattern is to make this interface (base class) defined in a header file so that dependencies can use it. Then they dynamically load derived classes via pluginlib.

This way, someone else can implement their own controller from quad_controller_base and define it in their own plugin, and dynamically load that as well. If you defined the base class constructor in this library, then the user-defined controllers wouldn't really be "peers" with the default controllers that you provide in your package.

Consider the following scenario:

  • Someone builds a controller manager for quadcopters
    • This depends only on quad_controller_base.h
  • One person's application wants to use the controller manager with your default controllers
    • This depends on: libquad_controller_manager.so,
    • This loads libquad_controllers.so at runtime via pluginlib
  • Another person's application wants to use the controller manager with additional controllers
    • This depends on: libquad_controller_manager.so,
    • This loads libquad_controllers.so at runtime via pluginlib
    • This loads libmy_sweet_controller.so at runtime via pluginlib

This way, none of these different programs need to know anything except the interface at compile time, and then they can load whatever collection of controllers that are defined at runtime. This is compared to achieving the same behavior only with static linking, whereby the controller manager would need to be dependent on the packages that contain your default controllers AND my sweet controller. @tfoote likes to refer to it as "flipping the dependency tree."

Hope this helps.

edit flag offensive delete link more

Question Tools

Stats

Asked: 2012-10-10 10:49:57 -0600

Seen: 269 times

Last updated: Oct 10 '12