• ROS(1)话题模型


     话题模型

    发布者

    实现发布者

    初始化ROS节点 

    ros::init(argc,argv, 名称)

    向ROS Master注册节点信息,包括发布的话题名和话题中消息类型

    ros::Publisher publisher = n.advertise<消息类型>(话题名, 消息队列 10);

    按照一定频率循环发布消息

    xx.publish(消息);

    C++代码编辑编辑完成后

    配置CMakeLists.txt

    add_executable(可执行文件名 src/xxx.cpp)  设置编译的代码和生成可执行文件

    target_link_libraries(可执行文件名 ${catkin_LIBRARIES})  设置链接库

    编译

    catkin_make

    设置环境变量

    source devel/setup.bash

    运行

    roscore

    rosrun turtlesim turtlesim_node

    rosrun 功能包名 节点名(即上方可执行文件名)

    C++实现发布者

    注意:运行前需要先编译、设置环境变量和运行

    ***直接输入rosrun 功能包名 节点执行名方式

     gedit ~/.bashrc

    在.bashrc文件的最下方,输入source ~/catkin_ws/devel/setup.bash

    重启终端,运行rosrun ...

    velocity_publisher.cpp 

    1. // 构建发布者,发布话题turtle1/cmd_vel,消息类型为geometry_msgs::Twist
    2. #include
    3. #include
    4. /**
    5. * 初始化ROS节点
    6. * 向ROS Master注册节点信息,包括发布的话题名和话题的消息类型
    7. * 创建消息数据
    8. * 按照一定频率循环发布消息
    9. */
    10. int main(int argc, char**argv)
    11. {
    12. // ROS初始化节点
    13. ros::init(argc, argv, "velocity_publisher");
    14. // 创建节点句柄
    15. ros::NodeHandle n;
    16. // 创建Publisher,发布topic为/turtle1/cmd_vel,消息类型为geometry_msgs::Twist,队列长度为10
    17. ros::Publisher turtle_vel_pub = n.advertise("/turtle1/cmd_vel", 10);
    18. // 设置循环频率
    19. ros::Rate loop_rate(10);
    20. int count = 0;
    21. while(ros::ok)
    22. {
    23. // 初始化geometry_msgs::Twist类型的消息
    24. geometry_msgs::Twist vel_msg;
    25. // 线速度为0.5
    26. vel_msg.linear.x = 0.5;
    27. // 沿z轴的角速度为0.2
    28. vel_msg.angular.z = 0.2;
    29. // 发布消息
    30. turtle_vel_pub.publish(vel_msg);
    31. ROS_INFO("Publish turtle velocity command[%0.2f m/s, %0.2f rad/s]", vel_msg.linear.x, vel_msg.angular.z);
    32. // 按照循环频率延时
    33. loop_rate.sleep();
    34. }
    35. return 0;
    36. }

    python实现发布者

    注意***:需要检查python文件属性是否是可执行

    安装python3

    sudo apt-get install python3

    通过软连接,将python链接到python3,链接一次即可

    sudo ln -s /usr/bin/python3 /usr/bin/python

    chmod 更改或分配文件和目录的权限  +为增加权限

    定位到workspace/src/功能包/scripts/

    chmod +x xxx.py

    python脚本上方添加

    #!/usr/bin/env python3
    # -*- coding:utf-8 -*-

    velocity_publisher.py 

    1. #!/usr/bin/env python3
    2. # -*- coding:utf-8 -*-
    3. import rospy
    4. from geometry_msgs.msg import Twist
    5. def velocity_publisher():
    6. print("查看是否启动")
    7. # ROS节点初始化
    8. rospy.init_node('velocity_publisher', anonymous=True)
    9. # 创建Publisher,发布topic /turtle1/cmd_vel,消息类型为geometry_msg::Twist,队列长度为10
    10. turtle_vel_pub = rospy.Publisher('/turtle1/cmd_vel', Twist, queue_size=10)
    11. # 设置循环的频率
    12. rate = rospy.Rate(10)
    13. while not rospy.is_shutdown(): // ***注意此有()
    14. # 初始化geometry_msgs::Twist类型的消息
    15. vel_msg = Twist()
    16. vel_msg.linear.x = 0.5
    17. vel_msg.angular.z = 0.3
    18. # 发布消息
    19. turtle_vel_pub.publish(vel_msg)
    20. rospy.loginfo("Publisher turtle velocity command [%0.2f m/s, %0.2f rad/s]", vel_msg.linear.x, vel_msg.angular.z)
    21. # 按照循环频率延时
    22. rate.sleep()
    23. if __name__ == '__main__':
    24. try:
    25. velocity_publisher()
    26. except rospy.ROSInterruptException:
    27. print("发布出现问题,中断错误")

    订阅者

    初始化ROS节点

    创建订阅者,订阅话题,注册回调函数

    循环等待回调函数

    回调函数在接收到订阅消息后执行

    C++实现订阅者

    pose_subscriber.cpp 

    1. /*
    2. 订阅/turtle1/pose话题,消息类型为turtlesim::pose
    3. */
    4. #include
    5. #include "turtlesim/Pose.h"
    6. // 接收到订阅消息,进入消息回调函数
    7. void poseCallback(const turtlesim::Pose::ConstPtr & msg)
    8. {
    9. // 打印消息
    10. ROS_INFO("Turtle pose: x:%0.6f, y:%0.6f", msg->x, msg->y);
    11. }
    12. int main(int argc, char **argv)
    13. {
    14. // 初始化ROS节点
    15. ros::init(argc, argv, "pose_subscriber");
    16. // 创建节点句柄
    17. ros::NodeHandle n;
    18. // 创建subscriber,订阅topic /turtle1/pose,注册回调函数
    19. ros::Subscriber pose_sub = n.subscribe("/turtle1/pose", 10, poseCallback);
    20. // 循环等待回调函数
    21. ros::spin();
    22. return 0;
    23. }

    python实现订阅者

    pose_subscriber.py 

    1. #!/usr/bin/env python3
    2. # -*- coding:utf-8 -*-
    3. import rospy
    4. from turtlesim.msg import Pose
    5. def pose_Callback(msg):
    6. rospy.loginfo("Turtle pose: x: %0.6f, y: %0.6f", msg.x, msg.y)
    7. def pose_subscribe():
    8. # 初始化ROS节点
    9. rospy.init_node('pose_subscriber', anonymous=True)
    10. # 定义发布者
    11. rospy.Subscriber("/turtle1/pose", Pose, pose_Callback)
    12. # 循环等待回调函数
    13. rospy.spin()
    14. if __name__ == '__main__':
    15. pose_subscribe()

    自定义话题发布者和订阅者

    步骤:

    1、定义msg文件

    2、package.xml中添加功能包依赖

    3、在CMakeList.txt中添加编译选项

            find_package(catkin REQUIRED roscpp rospy std_msgs geometry_msgs message_generation)

            add_message_files(FILES Person.msg)

            generate_message(DEPENDENCIES std_msgs geometry_msgs) 

            catkin_package(... CATKIN_DEPENDS message_runtime geometry_msgs roscpp rospy std_msgs)

            include_directories(include  ${catkin_INCLUDE_DIRS})

          在package.xml中添加

              catkin
              geometry_msgs
              roscpp
              rospy
              std_msgs
              message_generation
              message_runtime

              geometry_msgs
              roscpp
              rospy
              std_msgs
              message_generation
              message_runtime

              geometry_msgs
              roscpp
              rospy
              std_msgs
              message_generation
              message_runtime

    4、编译 catkin_make

    5、创建自定义话题发布者、订阅者代码

          CMakeList.txt中

            add_execte(执行节点名 xxx.cpp)

            target_link_liberaries(执行节点名 ${catkin_LIBRARIES})

            add_dependencies(执行节点名 ${PROJECT_NAME}_generate_messages_cpp})

    6、编译 catkin_make

    创建msg文件

    touch Person.msg

    注意:如果没有引入Person.h头文件,则需要在VSCode的C/C++编辑中,增加xxx/catkin_ws/**

     Person_Publisher.cpp

    1. #include
    2. #include "learning_topic/Person.h"
    3. int main(int argc, char**argv)
    4. {
    5. // 初始化节点
    6. ros::init(argc, argv, "person_publisher");
    7. // 创建节点句柄
    8. ros::NodeHandle n;
    9. // 创建发布者,发布topic名为person_info,类型为Person,队列长度为10
    10. ros::Publisher person_info_pub = n.advertise("/person_info", 10);
    11. // 设置循环频率
    12. ros::Rate loop_rate(10);
    13. int count = 0;
    14. while (ros::ok)
    15. {
    16. // 初始化learning_topic::Person类型消息
    17. learning_topic::Person person_msg;
    18. person_msg.name = "Tom";
    19. person_msg.age = 18;
    20. person_msg.sex = learning_topic::Person::male;
    21. // 发布消息
    22. person_info_pub.publish(person_msg);
    23. ROS_INFO("publish Person Info-- name:%s age:%d sex:%d", person_msg.name.c_str(), person_msg.age, person_msg.sex);
    24. // 按照循环频率延时
    25. loop_rate.sleep();
    26. }
    27. return 0;
    28. }

    Person_subscriber.cpp

    1. #include
    2. #include "learning_topic/Person.h"
    3. void personInfoCallBack(const learning_topic::Person::ConstPtr& msg)
    4. {
    5. // 接收订阅消息后进入回调函数,打印接收到的消息
    6. ROS_INFO("Subscribe Person Info: name %s age %d sex %d", msg->name.c_str(), msg->age, msg->sex);
    7. }
    8. int main(int argc, char** argv)
    9. {
    10. // 初始化ROS节点
    11. ros::init(argc, argv, "person_subscriber");
    12. // 构建节点句柄
    13. ros::NodeHandle n;
    14. // 构建订阅者,订阅topic为/person_info,消息队列为10
    15. ros::Subscriber person_info_sub = n.subscribe("/person_info", 10, personInfoCallBack);
    16. // 循环等待回调函数
    17. ros::spin();
    18. return 0;
    19. }

    python代码

    1. #!/usr/bin/env python3
    2. # -*- coding:utf-8 -*-
    3. import rospy
    4. from learning_topic.msg import Person
    5. def info_publisher():
    6. # 初始化ROS节点
    7. rospy.init_node('person_publisher', anonymous=True)
    8. # 构建Publisher,topic为 /person_info,类型为Person,队列大小为10
    9. person_info_pub = rospy.Publisher("/person_info", Person, queue_size=10)
    10. # 设置循环频率
    11. rate = rospy.Rate(10)
    12. while not rospy.is_shutdown():
    13. # 初始化learning_topic功能包中Person类型消息
    14. person_msg = Person()
    15. person_msg.name = 'Tom'
    16. person_msg.age = 10
    17. person_msg.sex = Person.male
    18. # 发布消息
    19. person_info_pub.publish(person_msg)
    20. rospy.loginfo("Publish person message [%s, %d, %d]", person_msg.name, person_msg.age, person_msg.sex)
    21. # 按照循环频率延时
    22. rate.sleep()
    23. if __name__ == '__main__':
    24. try:
    25. info_publisher()
    26. except rospy.ROSInterruptException:
    27. print("执行错误,中断运行")
    1. #!/usr/bin/env python3
    2. # -*- coding:utf-8 -*-
    3. import rospy
    4. from learning_topic.msg import Person
    5. def personInfoCallBack(msg):
    6. # 收到消息,显示数据
    7. rospy.loginfo("Person subscribe get name:%s age:%d sex:%d]", msg.name, msg.age, msg.sex)
    8. def person_subscribe():
    9. # 初始化节点
    10. rospy.init_node('person_subscriber', anonymous=True)
    11. # 构建订阅者,订阅topic /person_info,消息类型为Person
    12. rospy.Subscriber("/person_info", Person, personInfoCallBack)
    13. # 循环等待回调函数
    14. rospy.spin()
    15. if __name__ == '__main__':
    16. person_subscribe()

  • 相关阅读:
    Python函数详解(四)——Python函数参数使用注意事项
    【统计机器学习】线性回归模型
    GitHub-使用 Git工具 创建密钥id_rsa.pub
    iptables和容器Docker命令详细解析--看完秒懂
    雪花算法记录
    机器学习——机器学习概述
    【EI会议征稿】第八届能源系统、电气与电力国际学术会议(ESEP 2023)
    递归算法学习——图像渲染,岛屿的数量,最大的岛屿
    Spring AOP复习与回顾
    新闻主题分类任务——torchtext 库进行文本分类
  • 原文地址:https://blog.csdn.net/jiangyangll/article/details/133555122