本文根据柴长坤老师的《机器人操作系统入门》6.2和6.3节进行操作,我也是刚开始学这门课。由于小弟电脑之前装了Clion,就顺手用它进行开发,其中如果有问题的话,可以和我进行交流哈。
本文参考了这几个博文:
https://blog.csdn.net/chenjun15/article/details/89305462
https://www.jetbrains.com/help/clion/ros-setup-tutorial.html
https://sychaichangkun.gitbooks.io/ros-tutorial-icourse163/content/
我在~/code 下建立了ros_ws/src,详细如下:
mkdir -p ros_ws/src
cd ros_ws
catkin_make
cd src
catkin_create_pkg topic_try roscpp rospy std_msgs
cd ~/code/ros_ws
source ./devel/setup.bash
在topic_try文件夹下新建一个msg文件夹,在topic/msg下创建文件gps.msg。该msg文件内容如下所示:
string state
float32 x
float32 y
完成后切记要在CMakeLists.txt和package.xml里添加内容。
CMakeLists.txt添加内容如下:
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
message_generation #需要添加的地方
)
add_message_files(
FILES
gps.msg
)
generate_messages(
DEPENDENCIES
std_msgs
)
package.xml改动内容如下:
message_generation
message_runtime
#或者用讲义上的代码,两个之中选一个就好
message_runtime
改动完内容后,在一开始打开的terminal里输入:
catkin_make
编译完成后,gps.h文件应该会出现在/ros_ws/devel/include/topic_try 里。
按照clion的操作指南是如是进行的:
sh ~/download/clion-2019.1.3/bin/clion.sh #bin文件夹左边是clion在系统的位置
打开clion后,按open选项,然后选择package(topic_try)下的CMakeLists.txt文件,并选择Open as Project
打开后,在project tree的topic_try的src文件夹右键新建2个C++ Source File talker.cpp和listener.cpp
为了方便后续编程时能使用自动填充功能,先做好CMakeLists.txt的内容修改。
添加如下内容,个人觉得直接在最下方添加内容而不是去掉注释:
add_executable(talker src/talker.cpp)
add_dependencies(talker topic_try_generate_messages_cpp)
target_link_libraries(talker
${catkin_LIBRARIES}
)
add_executable(listener src/listener.cpp)
add_dependencies(listener topic_try_generate_messages_cpp)
target_link_libraries(listener
${catkin_LIBRARIES}
)
这边小弟我就遇到一个问题了,talker.cpp里没法include gps.h文件,然后我就用了一个很蠢的办法在CMakeLists.txt里更改一句话:
include_directories(
include
${catkin_INCLUDE_DIRS}
"~/code/ros_ws/devel/include"
)
完成后再按Reload Changes,这样就能成功include gps.h文件了。
talker.cpp的代码如下:
#include
#include
int main(int argc,char **argv)
{
ros::init(argc,argv,"talker"); //解析参数,命名节点
ros::NodeHandle nh;//创建句柄,实例化node
topic_try::gps msg;//创建gps消息
msg.x = 1.0;
msg.y = 1.0;
msg.state = "working";
ros::Publisher pub = nh.advertise("gps_info",1);//创建publisher
ros::Rate loop_rate(1.0);//定义循环发布的频率
while(ros::ok())
{
msg.x = 1.03 * msg.x;
msg.y = 1.01 * msg.y;
ROS_INFO("Talker:GPS:x = %f,y = %f",msg.x,msg.y);//输出当前的msg
pub.publish(msg);
loop_rate.sleep();//根据定义的发布频率,sleep
}
return 0;
}
listener.cpp代码如下:
#include
#include // msg的头文件,生成一个包含msg的类
#include // ros提供的32位浮点数类型
void gpsCallback(const topic_try::gps::ConstPtr &msg){
std_msgs::Float32 distance; // distance 是一个结构体,内存存放在distance.data中
distance.data = sqrt(pow(msg->x,2) + pow(msg->y,2));
ROS_INFO("Listener: distance from origin = %f, State = %s", distance.data, msg->state.c_str());
}
// main函数规矩,第一个参数是参数个数,第二个参数是具体参数值
int main(int argc, char** argv){
ros::init(argc, argv, "listener"); // 解析参数,命名节点node
ros::NodeHandle nh; // 创建node句柄,实例化node
// 参数含义:topic名字, 队列长度L通常为1, 回调函数
ros::Subscriber sub = nh.subscribe("gps_info", 1, gpsCallback);
// 反复调用当前可以触发的回调函数,阻塞
// 还有一种只调用一次回调函数的方法:ros::spinOnce();
ros::spin();
return 0;
}
完事后在右上角锤子右边分别选择talker和listener进行编译,编译完成后,另外打开一个terminal,输入:
roscore
然后在Clion上运行talker.cpp和listener.cpp,然后就会出结果了!