瓜大无人船使用踩坑记
Don't get suckered in by the comments - they can be terribly misleading. Debug only the code. —— Dave Storer
libusb
Checking for one of the modules 'libusb' CMake Error at /usr/share/cmake-3.5
None of the required 'libusb' found
解决方案
-
下载libusb
-
编译及安装
进入目录,shell下依次执行下列命令。
-
执行:
./configure
提示:
configure: error: “udev support requested but libudev not installed”
解决:
sudo apt-get install libudev-dev
-
执行:
make
提示:
‘aclocal-1.14’ is missing on your system.
解决:
sudo apt-get install automake sudo apt-get install libtool sudo autoreconf -ivf make
-
安装:
sudo make install
libusb-1.0.a 和 libusb-1.0.so 被安装到 /usr/local/lib/ 目录
libusb.h 被安装到 /usr/local/include/libusb-1.0/ 目录
-
-
确认安装libusb包后,xxx包空间,catkin_make还是找不到libusb???
主要原因如下:
查看/usr/local/lib,安装的libusb的二进制文件名称为 libusb-1.0.so
查看joystick_drivers中的CMakeLists.txt中
pkg_search_module(LIBUSB REQUIRED libusb)
,libusb应该修改成libusb-1.0,这样才能与/usr/local/lib相符
geographic_msgs
【Debug】:ros :Could not find a package configuration file provided by "geographic_msgs"
详细描述:
Could not find the required component 'geographic_msgs'. The following CMake error indicates that you either need to install the package with the same name or change your environment so that it can be found.
CMake Error at /opt/ros/kinetic/share/catkin/cmake/catkinConfig.cmake:83 (find_package):
Could not find a package configuration file provided by "geographic_msgs"
with any of the following names:
geographic_msgsConfig.cmake
geographic_msgs-config.cmake
Add the installation prefix of "geographic_msgs" to CMAKE_PREFIX_PATH or
set "geographic_msgs_DIR" to a directory containing one of the above files.
If "geographic_msgs" provides a separate development package or SDK, be
sure it has been installed.
解决方案
sudo apt-get install ros-kinetic-geographic-msgs
libgps
ros No package 'libgps' found‘
解决方案
sudo apt-get install libgps-dev
自定义消息编译时提示找不到.h头文件
在我们拥有多个package的时候,我们定义了一个消息或者服务,并在代码中使用了这个消息或者服务。如果是单独编译这个包,编译通过。但是如果是多个包一起编译,就会出现找不到相关头文件的错误。
原因: 编译时未按照严格顺序进行编译
解决办法:在使用自定义消息或者服务的包中,修改CMakeLists.txt,增加如下内容
add_dependencies(some_target ${${PROJECT_NAME}_EXPORTED_TARGETS})
作用:让编译器知道,编译some_target时,需要注意编译顺序
PS3 Controller & usb.h
sixpair.c:23:17: fatal error: usb.h: No such file or directory.
include <usb.h>
Compilation terminated
解决方案
sudo apt-get install libusb-dev
CMakeList编写
一、 概述
CMake构建系统通过ROS包中的CMakeList.txt来构建软件包。互相依赖的包都包含一个或者多个CMakeList.txt来描述如何编译代码和如何安装。在catkin 项目中,CMakeList.txt 符合标准的vanilla CMakeList.txt 格式,但稍微有点不同。
二、 整体结构和命令一览
在编写CMakeLists.txt时必须遵循特定的格式,否则软件包将无法正确构建和编译。一个完整的ROS下CMakeList.txt由下面内容组成
- 所需CMake版本(cmake_minimum_required)
- 软件包名称(project())
- 查找构建所需的其他CMake / Catkin软件包(find_package())
- 启用Python模块支持(catkin_python_setup())
- 消息/服务/动作生成器(add_message_files(),add_service_files(),add_action_files())
- 生成消息/服务/动作等自定义消息(generate_messages())
- 指定包的构建信息输出(catkin_package())
- 要建立的库/可执行文件(add_library()/ add_executable()/ target_link_libraries())
- 测试(catkin_add_gtest())
- 安装规则(install())
三、 CMake版本
CMakeLists.txt文件必须以CMake的版本开头。下面表示的是Catkin需要2.8.3或更高的版本。
cmake_minimum_required(VERSION 2.8.3)
四、 软件包名称
继而需要指定CMake工程名,一般取作包名。例如我们的项目名叫做robot_brain
project(robot_brain)
而在CMake中,可以在CMake文本中使用变量${PROJECT_NAME}来引用项目名称。
五、 查找相关的CMake包
接下来我们要用find_package指令来指定在构建项目过程中依赖了哪些其他的包,在ROS中,catkin必备依赖,所以雷打不打地我们写上catkin REQUIRED:
find_package(catkin REQUIRED)
在此基础上,如果我们还需要依赖其他包(或者组件),我们就在 上述的包后面继续添加包(组件)名即可:
find_package(catkin REQUIRED COMPONENTS nodelet)
或者可以写成
find_package(catkin REQUIRED)
find_package(nodelet REQUIRED)
值得注意一点的是:这里添加的包用于构建包使用,而不是添加运行时依赖项。
你也可以做:
find_package(catkin REQUIRED)
find_package(nodelet REQUIRED)
如何写,看个人习惯吧,如果不考虑篇幅,其实我更喜欢把所有包(组件)列成一列,直观。在普通的CMakeLists.txt中是没有find_package()的,那么,catkin中的这个语句有啥作用呢?
5.1 那find_package()作何用?
如果CMake通过find_package找到一个包,则会自动生成有关包所在路径的CMake环境变量,环境变量描述了包中头文件的位置,源文件的位置,包所依赖的库以及这些库的路径。
这些变量名称以< PACKAGE NAME >_< PROPERTY >的形式出现:
- < NAME >_FOUND - 如果找到库,则设置为true,否则为false
- < NAME > _INCLUDE_DIRS或<NAME> _INCLUDES - 包导出的包含路径
- < NAME > _LIBRARIES或<NAME> _LIBS - 由包导出的库
- < NAME > _DEFINITIONS - ?
- ...
5.2为啥Catkin包是组件形式?
实际上,Catkin的包并不是catkin的真正组成部分。而catkin采用CMake的组件功能,主要是为了节省打字时间。
将Catkin的包作为一种组件看待是很有好处的,当你找到包的时候,各种以catkin为前缀的添加到CMakeLists.txt中了。以前述nodelet包为例:
find_package(catkin REQUIRED COMPONENTS nodelet)
catkin执行到这个语句时,就会导出的nodelet的include路径,库等也添加到catkin前缀的变量中。例如,catkin_INCLUDE_DIRS不仅包含catkin的include路径,还包含了nodelet,这在后面会用到。
当然,我们可以只选择找nodelet的:
find_package(nodelet)
很可惜这样的做法会令nodelet路径,库等不会被添加到catkin变量中,从而生成了例如nodelet_INCLUDE_DIRS,nodelet_LIBRARIES这样的变量等。
5.3Boost库
如果使用C ++和Boost,则需要用find_package()来找Boost库,并指定Boost中的组件。 举个栗子,如果想使用Boost线程,就可以写成:
find_package(Boost REQUIRED COMPONENTS thread)
六、catkin_package()
catkin_package()是一个catkin提供的CMake宏,用于将catkin特定的信息信息输出到构建系统上,用于生成pkg配置文件以及CMake文件。
这个命令必须在add_library()或者add_executable()之前调用,该函数有5个可选参数:
- INCLUDE_DIRS - 导出包的include路径
- LIBRARIES - 导出项目中的库
- CATKIN_DEPENDS - 该项目依赖的其他catkin项目
- DEPENDS - 该项目所依赖的非catkin CMake项目。
- CFG_EXTRAS - 其他配置选项
举个栗子:
catkin_package(
INCLUDE_DIRS include
LIBRARIES ${PROJECT_NAME}
CATKIN_DEPENDS roscpp nodelet
DEPENDS eigen opencv)
这表示包文件夹中的文件夹“include”是导出头文件的地方。 ${PROJECT_NAME}根据project中的内容生成,此处是rrobot_brain。“roscpp”+“nodelet”是用来构建/运行此程序包的catkin包,而“eigen”+“opencv”是用于构建/运行此程序包的非catkin包。
七、指定构建目标
构建目标可以有多种形式,但通常主要有以下两种:
- 执行文件目标 - 可以运行的程序
- 库目标 - 可在构建和/或运行时给可执行目标使用的库
7.1目标命名
值得重点关注的是,catkin中的构建目标的名称必须是唯一的,但是,但构建目标命名的唯一性只能在CMake内部进行。可以使用set_target_properties()函数将目标重命名为其他目标:
再举个栗子:
set_target_properties(rviz_image_view
PROPERTIES OUTPUT_NAME image_view
PREFIX "")
这时就将rviz_image_view的名称更改为image_view了。
7.2自定义输出目录
一般情况下,令输出目标目录保持默认就可以了,但有时遇到一些特定情况就得因地制宜。再再举个栗子,一个包含了Python bindings的库必须防止在不同的文件夹,才能够被导入Python中,因此可以通过下述方式进行:
set_target_properties(python_module_library
PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_PYTHON_DESTINATION})
7.3包含路径和库路径
在生成目标之前,请记得先写好包含路径和库路径,不然编译会失败。
- 包括路径 - 头文件
- 库路径 - 构建对象需要用到的库
include_directories(<dir1>,<dir2>,...,<dirN>)
link_directories(<dir1>,<dir2>,...,<dirN>)
7.3.1 include_directories()
include_directories()中的参数应该是调用find_package调用时生成的* _INCLUDE_DIRS变量。 如果使用catkin和Boost,那么include_directories()调用应该如下所示:
include_directories(include ${Boost_INCLUDE_DIRS} ${catkin_INCLUDE_DIRS})
第一个参数“include”表示包中的include /目录也是路径的一部分。
7.3.2 link_directories()
link_directories()函数可用于添加额外的库路径,但通常不推荐这样做,因为 所有catkin和CMake软件包在find_packaged时都会自动添加链接信息。 只需写target_link_libraries()中就可以了。但真要写,就按照下面那样来写:
link_directories(~/my_libs)
7.4 可执行目标
要指定必须构建的可执行目标,我们必须使用add_executable()CMake函数。
add_executable(myProgram
src/main.cpp
src/some_file.cpp)
构建myProgram的目标可执行文件,3个源文件构建:src / main.cpp,src / some_file.cpp和src / another_file.cpp。
7.5 库目标
add_library() 用于指定要构建的库。
add_library(${PROJECT_NAME} ${${PROJECT_NAME}_SRCS})
7.6 target_link_libraries()
target_link_libraries()来指定可执行目标链接的库。 通常在add_executable()调用之后完成。 如果找不到ros,则添加$ {catkin_LIBRARIES}。
target_link_libraries(<executableTargetName>, <lib1>, <lib2>, ... <libN>)
add_executable(foo src/foo.cpp)
add_library(moo src/moo.cpp)
target_link_libraries(foo moo) -- This links foo against libmoo.so
请注意,在大多数情况中不需要使用link_directories(),因为find_package()自动拉入。
八、消息、服务和响应
消息(.msg),服务(.srv)和响应(.action)文件在ROS包构建和使用之前需要一个特殊的预处理器构建步骤。 这些宏的要点是生成编程语言特定的文件,以便可以利用其选择的编程语言中的消息,服务和动作。 构建系统将使用生成器(例如gencpp,genpy,genlisp等)生成绑定。
提供了三个宏来分别处理消息,服务和响应:
- add_message_files
- add_service_files
- add_action_files
而在之后必须在下面写下面宏,catkin时候会在devel的include文件夹中生成对应的头文件:
generate_messages()
8.1 使用条件
为了能够正常生成相应的文件,这些宏必须在catkin_package()宏之前,
find_package(catkin REQUIRED COMPONENTS ...)
add_message_files(...)
add_service_files(...)
add_action_files(...)
generate_messages(...)
catkin_package(...)`
在catkin_package()宏中写上CATKIN_DEPENDS message_runtime
catkin_package(
...
CATKIN_DEPENDS message_runtime ...
...)
并且在find_package()写上message_generation组件:
find_package(catkin REQUIRED COMPONENTS message_generation)
package.xml文件中加上
<build_depend>message_generation</build_depend>
<run_depend>message_runtime</run_depend>
如果构建的对象依赖于其他需要构建消息/服务/响应的构建对象,则需要向目标catkin_EXPORTED_TARGETS添加明确的依赖关系,以便它们以正确的顺序构建。 这种情况比较常用,除非您的包真的不使用ROS的任何部分。 但这种依赖关系不能自动传递。 (some_target是由add_executable()设置的目标的名称):
add_dependencies(some_target${catkin_EXPORTED_TARGETS})
如果需要构建消息或服务的包以及使用这些消息和/或服务的可执行文件,则需要为自动生成的消息目标创建明确的依赖关系,以便以正确的顺序构建它们。 (some_target是由add_executable()设置的目标的名称):
add_dependencies(some_target ${${PROJECT_NAME}_EXPORTED_TARGETS})
如果您的catkin包满足上述两个条件,则需要添加以下两个依赖关系,即:
add_dependencies(some_target ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
8.2 例子
现在有两个依赖于std_msgs和sensor_msgs的消息MyMessage1.msg和MyMessage2.msg,还有一个自定义服务MyService.srv, message_program是使用这些消息和服务的指令,以及生成不使用自定义消息、服务的程序do_not_use_local_messages_programcatkin包,那么CMakeLists.txt应该写成:
######## 构建时依赖项 find_package(catkin REQUIRED COMPONENTS message_generation std_msgs
######## 声明要构建哪些消息
add_message_files(FILES
MyMessage1.msg
MyMessage2.msg)######## 声明构建哪些服务
add_service_files(FILES
MyService.srv)######## 声明生成上述消息、服务需要依赖的消息以及服务
generate_messages(DEPENDENCIES
std_msgs
sensor_msgs)######## 声明运行时依赖项
catkin_package(CATKIN_DEPENDS
message_runtime
std_msgs sensor_msgs)######## 声明构建生成的可执行文件名称以及依赖项
add_executable(message_program src/main.cpp)
add_dependencies(message_program \({\){PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
######## 声明构建不需要使用自定义消息、服务的可执行文件
add_executable(does_not_use_local_messages_program src/main.cpp)
add_dependencies(does_not_use_local_messages_program ${catkin_EXPORTED_TARGETS})
如果要构建响应,则在包中“action”目录中创建有一个名为“MyAction.action”的文件,则必须将actionlib_msgs添加到使用catkin进行find_package的组件列表中,然后在CMakeList.txt中加上下面两行:
add_action_files(FILES
MyAction.action)
此外,该包必须具有对actionlib_msgs的构建依赖。
九、启用Python模块支持
如果catkin包使用一些Python模块,您应该创建一个setup.py文件,并在调用catkin_python_setup()之后调用generate_messages()和catkin_package()。
十、单位测试
有一个catkin-specific宏用于处理名为catkin_add_gtest()的基于gtest的单元测试。
catkin_add_gtest(myUnitTest test / utest.cpp)
十一、可选步骤:指定可安装的目标
构建后,构建目标通常被放置在catkin工作区中。但有时候我们希望将目标安装到系统其他地方(有关安装路径的信息可以在REP 122中找到),以便其他人或本地文件夹可以使用它们来测试。换句话说,如果你想要做一个“make install”的代码,你需要指定目标应该生成到哪里。
这是使用CMake install()函数作为参数完成的:
目标 - 目标是安装
ARCHIVE DESTINATION - 静态库和DLL(Windows).lib存根
LIBRARY DESTINATION - 非DLL共享库和模块
RUNTIME DESTINATION - 可执行目标和DLL(Windows)样式共享库
举个栗子:
install(TARGETS ${PROJECT_NAME}
ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
除了这些标准目标,一些文件必须安装到特殊文件夹。即一个包含Python绑定的库必须安装到不同的文件夹中才能在Python中导入:
install(TARGETS python_module_library
ARCHIVE DESTINATION ${CATKIN_PACKAGE_PYTHON_DESTINATION}
LIBRARY DESTINATION ${CATKIN_PACKAGE_PYTHON_DESTINATION}
)
11.1 安装Python可执行脚本
对于Python代码,安装规则看起来是不同的,因为没有使用add_library()和add_executable()函数,以便CMake确定哪些文件是目标以及它们是什么类型的目标。 而是在您的CMakeLists.txt文件中使用以下内容:
catkin_install_python(PROGRAMS scripts/myscript
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION})
有关安装python脚本和模块的详细信息以及文件夹布局的最佳做法,请参见catkin手册。
如果您只安装Python脚本并且不提供任何模块,则不需要创建上述setup.py文件,也不需要调用catkin_python_setup()。
11.2 安装头文件
标题文件也必须安装到“include”文件夹中,这通常是通过安装整个文件夹的文件来完成的(可选地,按文件名模式过滤,不包括SVN子文件夹)。 这可以通过如下所示的安装规则完成:
install(DIRECTORY include/{CATKIN_PACKAGE_INCLUDE_DESTINATION}
PATTERN ".svn" EXCLUDE
)
或者如果包含的子文件夹与包名称不匹配:
install(DIRECTORY include/
DESTINATION ${CATKIN_GLOBAL_INCLUDE_DESTINATION}
PATTERN ".svn" EXCLUDE
)
11.3 安装roslaunch文件或其他资源
其他资源(如启动文件)可以安装到
$ {CATKIN_PACKAGE_SHARE_DESTINATION
install(DIRECTORY launch/
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/launch
PATTERN ".svn" EXCLUDE)
参考文章:
1.ROS中的CMakeLists.txt
2.catkinCMakeLists.txt
bluetooth.h
.../joystick_drivers-master/wiimote/include/wiimote/wiimote_controller.h:49:10: fatal error: bluetooth/bluetooth.h: No such file or directory
#include <bluetooth/bluetooth.h> // libbluetooth.so
^~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
turtlebot2/joystick_drivers-master/wiimote/CMakeFiles/wiimote_node.dir/build.make:62: recipe for target 'turtlebot2/joystick_drivers-master/wiimote/CMakeFiles/wiimote_node.dir/src/wiimote_controller.cpp.o' failed
make[2]: *** [turtlebot2/joystick_drivers-master/wiimote/CMakeFiles/wiimote_node.dir/src/wiimote_controller.cpp.o] Error 1
make[2]: *** Waiting for unfinished jobs....
解决方案
sudo apt-get install libbluetooth-dev
cwiid.h
/joystick_drivers-master/wiimote/include/wiimote/wiimote_controller.h:52:10: fatal error: cwiid.h: No such file or directory
#include <cwiid.h> // libcwiid.so
^~~~~~~~~
compilation terminated.
turtlebot2/joystick_drivers-master/wiimote/CMakeFiles/wiimote_node.dir/build.make:62: recipe for target 'turtlebot2/joystick_drivers-master/wiimote/CMakeFiles/wiimote_node.dir/src/wiimote_controller.cpp.o' failed
make[2]: *** [turtlebot2/joystick_drivers-master/wiimote/CMakeFiles/wiimote_node.dir/src/wiimote_controller.cpp.o] Error 1
CMakeFiles/Makefile2:44715: recipe for target 'turtlebot2/joystick_drivers-master/wiimote/CMakeFiles/wiimote_node.dir/all' failed
make[1]: *** [turtlebot2/joystick_drivers-master/wiimote/CMakeFiles/wiimote_node.dir/all] Error 2
make[1]: *** Waiting for unfinished jobs....
解决方案1
(未测试的解决方案)
sudo apt-get install libcwiid-dev
解决方案2
【已测试但效果未知(报错,但多次重复后编译结束)】
-
下载
-
编译安装
aclocal autoconf ./configure make sudo make install
注意:
-
当执行./configure时,出现如下错误configure: error: flex not found
$ ./configure checking for gcc... gcc checking whether the C compiler works... yes checking for C compiler default output file name... a.out checking for suffix of executables... checking whether we are cross compiling... no checking for suffix of object files... o checking whether we are using the GNU C compiler... yes checking whether gcc accepts -g... yes checking for gcc option to accept ISO C89... none needed checking for gawk... no checking for mawk... mawk checking for flex... no checking for lex... no configure: error: flex not found
应安装flex:
sudo apt-get install flex
-
提示error: bison not found
应安装bison
sudo apt-get install bison byacc
-
aclocal与autoconf
下载三个包:autoconf-2.68.tar.bz2、automake-1.11.1.tar.bz2、m4-1.4.14.tar.bz2,注意安装顺序。
-
su - root
-
tar xjf XXXXX.tar.bz2
-
cd m4/
-
./configure make make install
-
cd autoconf/
-
./configure make make install
-
cd automake/
-
./configure make make install
-
exit
-
特别注意:
编译安装m4-1.4.16.tar.gz,出现问题:
./configure
make
报错提示:
error: 'gets' undeclared here (not in a function)
解决办法:
gedit lib/stdio.in.h
查找字段:gets is a security hole
将_GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead"); 字段和他之前的注释 /* 一块注释掉,如下
/* It is very rare that the developer ever has full control of stdin,
so any use of gets warrants an unconditional warning. Assume it is
always declared, since it is required by C89.
#undef gets
_GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead"); */
再添加如下内容:
#if defined(__GLIBC__) && !defined(__UCLIBC__) && !__GLIBC_PREREQ(2, 16)
_GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead");
#endif
再重新编译安装
make
make install
附注:
查看是否安装成功cwiid.h的方法:
$ whereis cwiid.h
cwiid: /usr/local/etc/cwiid /usr/local/lib/cwiid
后记
在苦逼实验中,烂怂无人船上发生的奇葩问题都会被记录在此。
现在的泪就是当年脑袋进的水。