1

I have been facing linking issues when including various ROS packages and Drake as libraries, and have narrowed the issue down to VTK.

It seems that ROS(noetic) PCL depends on VTK 7.1.0 whereas Drake depends on VTK 9.1.0 after running ldd:

linux-vdso.so.1 (0x00007fffa88ea000)
libdrake.so => /opt/drake/lib/libdrake.so (0x00007f644589d000)
libpcl_io.so.1.10 => /lib/x86_64-linux-gnu/libpcl_io.so.1.10 (0x00007f64455d7000)
libvtkCommonCore-7.1.so.7.1p => /lib/x86_64-linux-gnu/libvtkCommonCore-7.1.so.7.1p (0x00007f644528b000)
libvtkFiltersGeneral-7.1.so.7.1p => /lib/x86_64-linux-gnu/libvtkFiltersGeneral-7.1.so.7.1p (0x00007f6444f41000)
libvtkRenderingCore-7.1.so.7.1p => /lib/x86_64-linux-gnu/libvtkRenderingCore-7.1.so.7.1p (0x00007f6444c30000)
libvtkRenderingOpenGL2-7.1.so.7.1p => /lib/x86_64-linux-gnu/libvtkRenderingOpenGL2-7.1.so.7.1p (0x00007f6444907000)
libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f6444725000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f6444533000)
libdrake_lcm.so => /opt/drake/lib/libdrake_lcm.so (0x00007f644451a000)
libdrake_marker.so => /opt/drake/lib/libdrake_marker.so (0x00007f6444517000)
libvtksys-9.1.so.1 => /opt/drake/lib/libvtksys-9.1.so.1 (0x00007f64444c2000)
libvtkfmt-9.1.so.1 => /opt/drake/lib/libvtkfmt-9.1.so.1 (0x00007f644449b000)
libvtkkissfft-9.1.so.1 => /opt/drake/lib/libvtkkissfft-9.1.so.1 (0x00007f6444493000)
libvtkloguru-9.1.so.1 => /opt/drake/lib/libvtkloguru-9.1.so.1 (0x00007f6444459000)
...

My CMakeLists.txt is defined as:

cmake_minimum_required(VERSION 3.10)
project(my_project)

find_package(catkin REQUIRED COMPONENTS
  roscpp
  pcl_ros
)
find_package(drake CONFIG REQUIRED PATHS /opt/drake)

catkin_package(
  CATKIN_DEPENDS roscpp pcl_ros
  DEPENDS drake
)

include_directories(${catkin_INCLUDE_DIRS})

add_executable(my_test test.cpp)
target_link_libraries(my_test drake::drake ${catkin_LIBRARIES})

and package.xml as

....
<buildtool_depend>catkin</buildtool_depend>
  <depend>roscpp</depend>
  <depend>pcl_ros</depend>
</package>

Simply including vtk headers causes immediate an segmentation fault:

#include "drake/systems/framework/diagram_builder.h"

#include <vtkPolyData.h>
 
int main() {
    drake::systems::DiagramBuilder<double> builder;
    return 0;
}
Bilal
  • 3,191
  • 4
  • 21
  • 49
alvin
  • 137
  • 7

2 Answers2

2

That's correct -- VTK's library symbols are not version-namespaced, so you cannot load two different VTK versions into the same process, even for two completely independent uses. This is not unique to Drake; it's generally true about VTK.

The only challenge with Drake is that (1) Drake's pre-compiled binaries are built against a specific version of VTK that differs from ROS PCL's VTK, and (2) even for a Drake source build, Drake doesn't make it very easy to change which version of VTK will be linked. Unlike Eigen or spdlog or fmt, Drake's VTK dependency is not designed to be end-user-serviceable.

To avoid problems like this, Drake is actively working on linking VTK privately. Follow #16502 for updates. ETA for the fix should be within the next month or two.

In the meantime, there are not many good work-arounds.

The only easy one is to carefully link to only the parts of PCL that do not depend on VTK. For example, the PCL KDTree does not use VTK (should be safe), but the PCL IO does use VTK (will segfault). If your problem is only over-linking, then fixing your build to link fewer unnecessary things might resolve it.

The other work-around is to put a process boundary between your Drake-using code and PCL-with-VTK-using-code, with some kind of a message channel inbetween. That is, rework your code to only ever load Drake in some programs, and PCL in others, and never the two shall meet.

Hopefully, the Drake feature 16502 will be resolved soon, making this all moot.

jwnimmer-tri
  • 1,994
  • 2
  • 5
  • 6
  • Do you think think an approach [like this](https://stackoverflow.com/questions/69800043/how-to-avoid-linking-unnecessary-static-libraries-with-cmake) could work? Suppose I define an interface library, my_interface, that links drake. Next, I define a test file that links PRIVATE with my_interface, but NOT drake. I would expect that ldd only shows my_interface.so and not drake or its dependencies. This isn't the case however... why is that? When trying that post's solution but modified for library linking, I just get that the original my_interface functions are undefined. – alvin Oct 11 '22 at 00:25
  • I don't know catkin or cmake so I can't really help there. The possible overlinking would be with `pcl_ros` though, not libdrake. You need your final linker command to _only_ have things like `-lpcl_kdtree` on the linker command line, and _not_ have things like `-lpcl_io`. I can only imagine that catkin `pcl_ros` induces too many dependencies. – jwnimmer-tri Oct 11 '22 at 03:57
0

As of tonight's nightly build (20221117 or greater) or the next stable release (v1.11.0 or newer), Drake will use Ubuntu's build of VTK 9.1 when running on Ubuntu 22.04 (aka "Jammy"). In case you can run a version of ROS on Ubuntu 22.04, hopefully it would use a compatible VTK 9.1 and PCL would work.

jwnimmer-tri
  • 1,994
  • 2
  • 5
  • 6