mkdir -p catkin_ws/src
cd catkin_ws
catkin_make
Python3
catkin_make -DPYTHON_EXECUTABLE=/usr/bin/python3 -DPYTHON_INCLUDE_DIR=/usr/include/python3.7m -DPYTHON_LIBRARY=/usr/lib/libpython3.7m.so
$ . devel/setup.bash
$ echo $ROS_PACKAGE_PATH
/home/wangq/Projects/ROS/catkin/catkin_ws/src:/opt/ros/melodic/share
$ cd catkin_ws/src
$ catkin_create_pkg beginner_tutorials std_msgs rospy roscpp
Usage:
# In a catkin workspace
$ catkin_make [make_targets] [-DCMAKE_VARIABLES=...]
$ catkin_make --source my_src
$ catkin_make install --source my_src # (optionally)
$ cd catkin_ws
$ catkin_make
$ roscd beginner_tutorials
$ mkdir msg
$ echo "int64 num" > msg/Num.msg
Add dependencies into packages.xml
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
Add message_generation into CMakeLists.txt
# Do not just add this to your CMakeLists.txt, modify the existing text to add message_generation before the closing parenthesis
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
message_generation
)
Export the message runtime dependency
catkin_package(
...
CATKIN_DEPENDS message_runtime ...
...)
Uncomment it by removing the # symbols and then replace the stand in Message*.msg files with your .msg file, such that it looks like this:
add_message_files(
FILES
Num.msg
)
Now we must ensure the generate_messages() function is called.
generate_messages(
DEPENDENCIES
std_msgs
)
Now you can generate new messages:
$ roscd beginner_tutorials
$ cd ../..
$ catkin_make install
$ cd -
Check the generated messages:
$ rosmsg show beginner_tutorials/Num
int64 num
Generated:
- The C++ message header file will be generated in ~/catkin_ws/devel/include/beginner_tutorials/
- The Python script will be created in ~/catkin_ws/devel/lib/python2.7/dist-packages/beginner_tutorials/msg
- The lisp file appears in ~/catkin_ws/devel/share/common-lisp/ros/beginner_tutorials/msg/.
$ roscd beginner_tutorials
$ mkdir srv
Create by copying from an example:
$ roscp rospy_tutorials AddTwoInts.srv srv/AddTwoInts.srv
$ cat srv/AddTwoInts.srv
int64 a
int64 b
---
int64 sum
Make sure messages are enabled in package.xml
Make sure messages/services are enabled in CMakeLists.txt
Service:
add_service_files(
FILES
AddTwoInts.srv
)
$ rossrv show beginner_tutorials/AddTwoInts
int64 a
int64 b
---
int64 sum
Add 'beginner_tutorials/src/talker.cpp' and 'beginner_tutorials/src/listener.cpp'
Modify CMakeLists.txt accordingly.
$ rosrun beginner_tutorials talker (C++)
$ rosrun beginner_tutorials talker.py (Python)
Writing a Simple Publisher and Subscriber
// define the service callback
bool add(beginner_tutorials::AddTwoInts::Request &req,
beginner_tutorials::AddTwoInts::Response &res)
{
...
}
int main(int argc, char **argv)
{
// declare a handle
ros::NodeHandle n;
// create the service
ros::ServiceServer service = n.advertiseService("add_two_ints", add);
}
Writing a Simple Service and Client
// declare a handle
ros::NodeHandle n;
// create service client with handle
ros::ServiceClient client = n.serviceClient<beginner_tutorials::AddTwoInts>("add_two_ints");
// declare service
beginner_tutorials::AddTwoInts srv;
srv.request.a = atoll(argv[1]);
srv.request.b = atoll(argv[2]);
if (client.call(srv)) {
// success
}else {
// failure
}
CMakeLists.txt
add_executable(add_two_ints_server src/add_two_ints_server.cpp)
target_link_libraries(add_two_ints_server ${catkin_LIBRARIES})
add_dependencies(add_two_ints_server beginner_tutorials_gencpp)
add_executable(add_two_ints_client src/add_two_ints_client.cpp)
target_link_libraries(add_two_ints_client ${catkin_LIBRARIES})
add_dependencies(add_two_ints_client beginner_tutorials_gencpp)
Create 'beginner_tutorial/action/Fibonacci.action'
#goal definition
int32 order
---
#result definition
int32[] sequence
---
#feedback
int32[] sequence
Change 'CMakeLists.txt'
find_package(catkin REQUIRED COMPONENTS actionlib_msgs)
add_action_files(
DIRECTORY action
FILES Fibonacci.action
)
generate_messages(
DEPENDENCIES actionlib_msgs std_msgs # Or other packages containing msgs
)
catkin_package(
CATKIN_DEPENDS actionlib_msgs
)
Change 'package.xml'
<build_depend>actionlib_msgs</build_depend>
<build_depend>actionlib</build_depend>
<exec_depend>actionlib</exec_depend>
<exec_depend>actionlib_msgs</exec_depend>
Writing a Simple Action Server using the Execute Callback
Create 'src/fibonacci_server.cpp'
// declare action server
actionlib::SimpleActionServer<beginner_tutorials::FibonacciAction> as_;
// declare action feedback
beginner_tutorials::FibonacciFeedback feedback_;
// declare action result
beginner_tutorials::FibonacciResult result_;
// declare action callback
void executeCB(const beginner_tutorials::FibonacciGoalConstPtr &goal)
{
...
// construct feedback
feedback_.sequence.clear();
feedback_.sequence.push_back(0);
feedback_.sequence.push_back(1);
...
// publish feedback
as_.publishFeedback(feedback_);
// construct result
result_.sequence = feedback_.sequence;
as_.setSucceeded(result_);
}
// initialize action server and register action callback
as_(nh_, name, boost::bind(&FibonacciAction::executeCB, this, _1), false)
Change 'CMakeLists.txt'
add_executable(fibonacci_server src/fibonacci_server.cpp)
target_link_libraries(
fibonacci_server
${catkin_LIBRARIES}
)
add_dependencies(
fibonacci_server
${beginner_tutorials_EXPORTED_TARGETS}
)
Writing a Simple Action Client
Create 'src/fibonacci_client.cpp'
// declare client
actionlib::SimpleActionClient<beginner_tutorials::FibonacciAction> ac("fibonacci", true);
// wait for the action server to start
ac.waitForServer();
// send a goal to the action
beginner_tutorials::FibonacciGoal goal;
goal.order = 20;
ac.sendGoal(goal);
//wait for the action to return
bool finished_before_timeout = ac.waitForResult(ros::Duration(30.0));
// get action state
actionlib::SimpleClientGoalState state = ac.getState();
Change 'CMakeLists.txt'
add_executable(fibonacci_client src/fibonacci_client.cpp)
target_link_libraries(
fibonacci_client
${catkin_LIBRARIES}
)
add_dependencies(
fibonacci_client
${beginner_tutorials_EXPORTED_TARGETS}
)
ros::Rate
ros::Timer