将海康威视相机封装成ROS节点时,如何管理相机SDK繁多的动态库?

问题

海康威视的相机SDK,包含大量的动态库,如果在它之上开发Linux应用程序,则不但编译时要链接那些动态库,运行时也要确保那些动态库存放在/lib/usr/lib等目录,或存放在环境变量LD_LIBRARY_PATH里指定自定义目录下,否则程序一运行就会报错,找不到动态库。

  • 编译时的链接问题好解决,将动态库都放到源码的lib目录下即可。
  • 运行时的加载库问题不好解决, 不论是将动态库拷贝到系统目录,还是设置环境变量,都很不方便,而且容易忘。

上述不便在更换开发调试环境时尤其显著,想象下,你将代码check到另一台机器上,编译通过,但运行报错,很影响效率啊!

ROS的解决方案

对于普通程序,或许上面的麻烦只能通过安装程序来解决,但ROS有更好的方法。

节点代码目录结构

以我之前开发的qp_camera_server节点举例,该节点将相机封装成ROS节点,并向外暴露若干ROS服务,例如拍照设置预置点调用预置点等,这样机器人主控节点就可以导航到巡检点后,调它来拍照了。

qp_camera_server/
├── CMakeLists.txt
├── include
│   └── HCNetSDK.h
├── launch
│   ├── infra_cam.launch
│   └── vis_cam.launch
├── lib
│   ├── HCNetSDKCom
│   │   ├── libHCAlarm.so
│   │   ├── libHCCoreDevCfg.so
│   │   ├── libHCDisplay.so
│   │   ├── libHCGeneralCfgMgr.so
│   │   ├── libHCIndustry.so
│   │   ├── libHCPlayBack.so
│   │   ├── libHCPreview.so
│   │   ├── libHCVoiceTalk.so
│   │   ├── libStreamTransClient.so
│   │   ├── libSystemTransform.so
│   │   ├── libanalyzedata.so
│   │   ├── libiconv.so.2
│   │   └── libiconv2.so
│   ├── libAudioRender.so
│   ├── libHCCore.so
│   ├── libNPQos.so
│   ├── libPlayCtrl.so
│   ├── libSuperRender.so
│   ├── libcrypto.so
│   ├── libcrypto.so.1.0.0
│   ├── libhcnetsdk.so
│   ├── libhpr.so
│   ├── libssl.so
│   └── libssl.so.1.0.0
├── package.xml
└── src
    └── qp_cam_server.cpp

节点CMakeLists.txt配置

这块的配置主要是方便catkin_make连接动态库,但也对后面的运行有帮助。改动主要是新增2条cmake指令:

  1. 额外增加一个link_directories指令,指示编译器可在哪些目录搜索动态库
  2. 增加一个target_link_libraries指令,指示编译器需要连接哪些动态库
cmake_minimum_required(VERSION 2.8.3)
project(qp_camera_server)

## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTS
  qp_bot_msgs
  roscpp
  std_msgs
)

###################################
## catkin specific configuration ##
###################################
catkin_package(

)

###########
## Build ##
###########

## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
 include
  ${catkin_INCLUDE_DIRS}
)

## Specify directories of libraries
link_directories(
    lib
    lib/HCNetSDKCom
)

## Declare a C++ executable
## With catkin_make all packages are built within a single CMake context
## The recommended prefix ensures that target names across packages don't collide
 add_executable(${PROJECT_NAME} src/qp_cam_server.cpp)
 
 ## Add cmake target dependencies of the executable
## same as for the library above
 add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

## Specify libraries to link a library or executable target against
 target_link_libraries(${PROJECT_NAME}
   ${catkin_LIBRARIES}
   hcnetsdk
   HCCore
   AudioRender
   crypto
   hpr
   NPQos
   PlayCtrl
   ssl
   SuperRender

   analyzedata
   HCAlarm
   HCCoreDevCfg
   HCDisplay
   HCGeneralCfgMgr
   HCIndustry
   HCPlayBack
   HCPreview
   HCVoiceTalk
   iconv2
   StreamTransClient
   SystemTransform
 )

用ROS命令启动节点

工程用catkin_make编译通过后,直接用rosrun命令启动节点即可,不会有找不到动态库的报错

rosrun qp_camera_server qp_camera_server

上面rosrun命令的第一个参数是ROS包名,第二个参数是ROS可执行程序名ROS节点名不显式指定的话跟第二个参数相同。

作为对比,如果执行

/path/to/qp_camera_server

则会报找不到动态库之类的错误。

总结

为何会这样?
猜测rosrun命令作为启动器,在启动可执行程序前,将CMakeLists.txt里指定的动态库搜索路径添加到环境变量LD_LIBRARY_PATH里了,所以操作系统加载可执行程序时就能找到动态库了。

这样做还有个好处,系统可以存在多个版本的动态库,互不影响。

你可能感兴趣的:(机器人,cmake,ROS,海康威视,相机)