1.创建标准catkin工作空间
mkdir mycatkin
cd mycatkin
mkdir build devel src
catkin_make
source devel/setup.bash
2.创建一个catkin程序包
mkdir src/modular_lib_pkg
Add bare-bones Catkin CMakeLists.txt
and package.xml
files to make yourdirectory a valid package:
src/modular_lib_pkg/CMakeLists.txt
# Declare the version of the CMake API for forward-compatibility
cmake_minimum_required(VERSION 2.8)
# Declare the name of the CMake Project
project(modular_lib_pkg)
# Find Catkin
find_package(catkin REQUIRED)
# Declare this project as a catkin package
catkin_package()
src/modular_lib_pkg/package.xml
<package>
<!-- Package Metadata -->
<name>modular_lib_pkg</name>
<maintainer email="you@example.com">Your Name</maintainer>
<description>
A ROS tutorial on modularity.
</description>
<version>0.0.0</version>
<license>BSD</license>
<!-- Required by Catkin -->
<buildtool_depend>catkin</buildtool_depend>
</package>
3.Separating Functionality into a Library
Create the Library Code
The header with the declaration of our say_hello()
function is as follows:
modular_lib_pkg/include/modular_lib_pkg/hello_world.h
// Inclusion guard to prevent this header from being included multiple times
#ifndef __MODULAR_LIB_PKG_HELLO_WORLD_H
#define __MODULAR_LIB_PKG_HELLO_WORLD_H
//! Broadcast a hello-world message over ROS_INFO
void say_hello();
#endif
The source file with the definition of say_hello()
is as follows:
modular_lib_pkg/src/hello_world.cpp
// Include the ROS C++ APIs
#include <ros/ros.h>
void say_hello() {
ROS_INFO_STREAM("Hello, world!");
}
Now that we’ve written the code for the library, we can add a rule to theCMakeLists.txt
file to actually build it. Note that just like in the ROS C++hello-world tutorial9, we need to add a dependency onroscpp
in order to use ROS. This is just like adding an executable with theadd_executable()
CMake command: instead, we useadd_library()
:
src/modular_lib_pkg/CMakeLists.txt
# Declare the version of the CMake API for forward-compatibility
cmake_minimum_required(VERSION 2.8)
# Declare the name of the CMake Project
project(modular_lib_pkg)
# Find and get all the information about the roscpp package
find_package(roscpp REQUIRED)
# Find Catkin
find_package(catkin REQUIRED)
# Declare this project as a catkin package
catkin_package()
# Add the headers from roscpp
include_directories(${roscpp_INCLUDE_DIRS})
# Define a library target called hello_world
add_library(hello_world src/hello_world.cpp)
target_link_libraries(hello_world ${roscpp_LIBRARIES})
Also, now that we’re using the roscpp
package, we need to list itas a build- and run-dependency of our package:
src/modular_lib_pkg/package.xml
<package>
<!-- Package Metadata -->
<name>modular_lib_pkg</name>
<maintainer email="you@example.com">Your Name</maintainer>
<description>
A ROS tutorial on modularity.
</description>
<version>0.0.0</version>
<license>BSD</license>
<!-- Required by Catkin -->
<buildtool_depend>catkin</buildtool_depend>
<!-- Package Dependencies -->
<build_depend>roscpp</build_depend>
<run_depend>roscpp</run_depend>
</package>
cd mycatkin
catkin_make4.建立节点
modular_lib_pkg/src/hello_world_node.cpp
// Include the ROS C++ APIs
#include <ros/ros.h>
// Include the declaration of our library function
#include <modular_lib_pkg/hello_world.h>
// Standard C++ entry point
int main(int argc, char** argv) {
// Initialize ROS
ros::init(argc, argv, "hello_world_node");
ros::NodeHandle nh;
// Call our library function
say_hello();
// Wait for SIGINT/Ctrl-C
ros::spin();
return 0;
}
To build this node, just add an appropriate add_executable()
call to thebottom of the package’sCMakeLists.txt
:
add_executable(hello_world_node src/hello_world_node.cpp)
target_link_libraries(hello_world_node ${roscpp_LIBRARIES})
5.编译节点
At this point, you can try to build hello_world_node
with catkin_make
, but youwill see the following error:
[100%] Building CXX object modular_lib_pkg/CMakeFiles/hello_world_node.dir/src/hello_world_node.cpp.o
/tmp/src/modular_lib_pkg/src/hello_world_node.cpp:5:42: fatal error: modular_lib_pkg/hello_world.h: No such file or directory
compilation terminated.
The compiler is complaining about modular_lib_pkg/hello_world.h
notexisting, but weknow it exists! The problem isn’t that the file doesn’texist, but rather that we haven’t told the compiler where to look for it.
In the same way that we added the header search paths for roscpp
, we alsoneed to add our own local include directory where we put our own headers. To doso, just add the relative path tosrc/modular_lib_pkg/include
to theexistinginclude_directories()
command inCMakeLists.txt
:
include_directories(include ${roscpp_INCLUDE_DIRS)
Building the Node (and getting a linker error)
At this point, you can try to build hello_world_node
with catkin_make
again, but you will see another error:
[100%] Building CXX object modular_lib_pkg/CMakeFiles/hello_world_node.dir/src/hello_world_node.cpp.o
Linking CXX executable /tmp/foo/devel/lib/modular_lib_pkg/hello_world_node
CMakeFiles/hello_world_node.dir/src/hello_world_node.cpp.o:hello_world_node.cpp:function main: error: undefined reference to 'say_hello()'
collect2: ld returned 1 exit status
This time, hello_world_node.cpp
is compiled successfully, but thelinkerreports an error that thesay_hello()
function is undefined. The declarationwas found in thehello_world.h
header file, otherwise it wouldn’t havecompiled, still the definition fromhello_world.cpp
was missing.
In order to resolve this, in addition to linking against ${roscpp_LIBRARIES}
,we also linkhello_world_node
against thehello_world
target so that itssymbols are defined for the linker. This is done by addinghello_world
to theexistingtarget_link_libraries()
command like the following:
target_link_libraries(hello_world_node ${roscpp_LIBRARIES} hello_world)
The following CMakeLists.txt
file contains both this and the previousmodifications:
src/modular_lib_pkg/CMakeLists.txt
# Declare the version of the CMake API for forward-compatibility
cmake_minimum_required(VERSION 2.8)
# Declare the name of the CMake Project
project(modular_lib_pkg)
# Find and get all the information about the roscpp package
find_package(roscpp REQUIRED)
# Find Catkin
find_package(catkin REQUIRED)
# Declare this project as a catkin package
catkin_package()
# Add the local headers and the headers from roscpp
include_directories(include ${roscpp_INCLUDE_DIRS})
# Define a library target called hello_world
add_library(hello_world src/hello_world.cpp)
target_link_libraries(hello_world ${roscpp_LIBRARIES})
# Define an executable target called hello_world_node
add_executable(hello_world_node src/hello_world_node.cpp)
target_link_libraries(hello_world_node ${roscpp_LIBRARIES} hello_world)
catkin_make
rosrun modular_lib_pkg hello_world_node
问题:
[rosrun] Couldn't find executable named hello_world_node below /home/hsn/mycatkin/src/modular_lib_pkg
解决:
cd mycatkin
source devel/setup.bash
其他问题:
roscore
或者sudo apt-get update
参考:http://jbohren.com/articles/modular-ros-packages/