ros入门(话题编程cpp版和python版)

准备好的空的工作空间

.
├── build
├── devel
└── src
   	├── beginner_tutorials
    │   ├── include
    │   ├── src
    │   ├── package.xml
    │   └── CMakeLists.txt
    └── CMakeLists.txt -> /opt/ros/melodic/share/catkin/cmake/toplevel.cmake

#如果你运行了catkin_make,那么build和devel内将会生存许多文件,此处我隐藏了
#此处的beginner_tutorials即为ros包,其下文件在你建立时就自动生成了
$ catkin_create_pkg beginner_tutorials std_msgs rospy roscpp

重点在于此处
beginner_tutorials
    ├── include
    ├── src
    ├── package.xml
    └── CMakeLists.txt

说明

1、全文代码来自:http://wiki.ros.org/cn/ROS/Tutorials

2、先跑成功代码,再理解代码

3、大家可以使用类似vscode的ide开发,文件目录看起来将会清晰很多

4、版本ubuntu18.04.1+ROS Melodic

msg创建和直接使用(如果涉及的话,自行修改Num.msg)

1、在~/catkin_ws/src/beginner_tutorials/下:
2、
创建文件夹 $ mkdir msg
写入:$ echo “int64 num” > msg/Num.msg
3、修改CMakeLists.txt (使用notepadqq打开并调整语言为cmake方便查看)

  • 在find_packag函数添加message_generation #利用find_packag函数增加对message_generation的依赖
    第10行
find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  message_generation
)
  • 找到add_message_files()代码块,去掉注释符号#,用你的Num.msg文件替代Message*.msg: #设置运行依赖
    第51行
add_message_files(
  FILES
  Num.msg
)
  • 找到generate_messages()代码块,去掉注释符号#: #确保CMake知道在什么时候重新配置我们的project
    第72行
generate_messages(
	DEPENDENCIES
	std_msgs
)

4、修改package.xml (使用notepadqq打开并调整语言为yml方便查看)
在下列代码后

  <buildtool_depend>catkin</buildtool_depend>
  <build_depend>roscpp</build_depend>
  <build_depend>rospy</build_depend>
  <build_depend>std_msgs</build_depend>
  <build_export_depend>roscpp</build_export_depend>
  <build_export_depend>rospy</build_export_depend>
  <build_export_depend>std_msgs</build_export_depend>
  <exec_depend>roscpp</exec_depend>
  <exec_depend>rospy</exec_depend>
  <exec_depend>std_msgs</exec_depend>

添加

  <build_depend>message_generation</build_depend>
  <exec_depend>message_runtime</exec_depend>

#构建时需要"message_generation",运行时需要"message_runtime"。

5、在~/catkin_ws/下:$ catkin_make #重新编译
6、测试运行:$ rosmsg show beginner_tutorials/Num
返回:int64 num

cpp版

1、在~/catkin_ws/src/beginner_tutorials/src/下新建文件talker.cpp
2、写入:

#include "ros/ros.h"
#include "std_msgs/String.h"

#include <sstream>

/**
 * This tutorial demonstrates simple sending of messages over the ROS system.
 */
int main(int argc, char **argv)
{
  /**
   * The ros::init() function needs to see argc and argv so that it can perform
   * any ROS arguments and name remapping that were provided at the command line. For programmatic
   * remappings you can use a different version of init() which takes remappings
   * directly, but for most command-line programs, passing argc and argv is the easiest
   * way to do it.  The third argument to init() is the name of the node.
   *
   * You must call one of the versions of ros::init() before using any other
   * part of the ROS system.
   */
  ros::init(argc, argv, "talker");

  /**
   * NodeHandle is the main access point to communications with the ROS system.
   * The first NodeHandle constructed will fully initialize this node, and the last
   * NodeHandle destructed will close down the node.
   */
  ros::NodeHandle n;

  /**
   * The advertise() function is how you tell ROS that you want to
   * publish on a given topic name. This invokes a call to the ROS
   * master node, which keeps a registry of who is publishing and who
   * is subscribing. After this advertise() call is made, the master
   * node will notify anyone who is trying to subscribe to this topic name,
   * and they will in turn negotiate a peer-to-peer connection with this
   * node.  advertise() returns a Publisher object which allows you to
   * publish messages on that topic through a call to publish().  Once
   * all copies of the returned Publisher object are destroyed, the topic
   * will be automatically unadvertised.
   *
   * The second parameter to advertise() is the size of the message queue
   * used for publishing messages.  If messages are published more quickly
   * than we can send them, the number here specifies how many messages to
   * buffer up before throwing some away.
   */
  ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);

  ros::Rate loop_rate(10);

  /**
   * A count of how many messages we have sent. This is used to create
   * a unique string for each message.
   */
  int count = 0;
  while (ros::ok())
  {
    /**
     * This is a message object. You stuff it with data, and then publish it.
     */
    std_msgs::String msg;

    std::stringstream ss;
    ss << "hello world " << count;
    msg.data = ss.str();

    ROS_INFO("%s", msg.data.c_str());

    /**
     * The publish() function is how you send messages. The parameter
     * is the message object. The type of this object must agree with the type
     * given as a template parameter to the advertise<>() call, as was done
     * in the constructor above.
     */
    chatter_pub.publish(msg);

    ros::spinOnce();

    loop_rate.sleep();
    ++count;
  }


  return 0;
}

3、在~/catkin_ws/src/beginner_tutorials/src/下新建文件listener.cpp
4、写入:

#include "ros/ros.h"
#include "std_msgs/String.h"

/**
 * This tutorial demonstrates simple receipt of messages over the ROS system.
 */
void chatterCallback(const std_msgs::String::ConstPtr& msg)
{
  ROS_INFO("I heard: [%s]", msg->data.c_str());
}

int main(int argc, char **argv)
{
  /**
   * The ros::init() function needs to see argc and argv so that it can perform
   * any ROS arguments and name remapping that were provided at the command line. For programmatic
   * remappings you can use a different version of init() which takes remappings
   * directly, but for most command-line programs, passing argc and argv is the easiest
   * way to do it.  The third argument to init() is the name of the node.
   *
   * You must call one of the versions of ros::init() before using any other
   * part of the ROS system.
   */
  ros::init(argc, argv, "listener");

  /**
   * NodeHandle is the main access point to communications with the ROS system.
   * The first NodeHandle constructed will fully initialize this node, and the last
   * NodeHandle destructed will close down the node.
   */
  ros::NodeHandle n;

  /**
   * The subscribe() call is how you tell ROS that you want to receive messages
   * on a given topic.  This invokes a call to the ROS
   * master node, which keeps a registry of who is publishing and who
   * is subscribing.  Messages are passed to a callback function, here
   * called chatterCallback.  subscribe() returns a Subscriber object that you
   * must hold on to until you want to unsubscribe.  When all copies of the Subscriber
   * object go out of scope, this callback will automatically be unsubscribed from
   * this topic.
   *
   * The second parameter to the subscribe() function is the size of the message
   * queue.  If messages are arriving faster than they are being processed, this
   * is the number of messages that will be buffered up before beginning to throw
   * away the oldest ones.
   */
  ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);

  /**
   * ros::spin() will enter a loop, pumping callbacks.  With this version, all
   * callbacks will be called from within this thread (the main one).  ros::spin()
   * will exit when Ctrl-C is pressed, or the node is shutdown by the master.
   */
  ros::spin();

  return 0;
}

5、在 ~/catkin_ws/src/beginner_tutorials/CMakeLists.txt 文件末尾加入几条语句:

## Build talker and listener
include_directories(include ${catkin_INCLUDE_DIRS})

add_executable(talker src/talker.cpp)
target_link_libraries(talker ${catkin_LIBRARIES})
add_dependencies(talker beginner_tutorials_generate_messages_cpp)

add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})
add_dependencies(listener beginner_tutorials_generate_messages_cpp)

6、回到~/catkin_ws/下:
$ catkin_make

#会生成两个可执行文件(exe/二进制), talker 和 listener, 默认存储到~/catkin_ws/devel/lib/ 中.

7、运行测试
开一个终端:$ roscore

再开一个终端:$ rosrun beginner_tutorials talker
返回:

[ INFO] [1581865490.444930807]: hello world 0
[ INFO] [1581865490.545128438]: hello world 1
[ INFO] [1581865490.645065811]: hello world 2
[ INFO] [1581865490.745070716]: hello world 3
[ INFO] [1581865490.845138578]: hello world 4
[ INFO] [1581865490.945071648]: hello world 5
[ INFO] [1581865491.045091994]: hello world 6
[ INFO] [1581865491.145070603]: hello world 7
[ INFO] [1581865491.245145005]: hello world 8
[ INFO] [1581865491.345067172]: hello world 9
[ INFO] [1581865491.445034335]: hello world 10
……

再开一个终端:$ rosrun beginner_tutorials listener
返回:(不从hello world 1开始是因为你开启listener手速不够快)

[ INFO] [1581865578.794471324]: I heard: [hello world 3]
[ INFO] [1581865578.894540946]: I heard: [hello world 4]
[ INFO] [1581865578.994505421]: I heard: [hello world 5]
[ INFO] [1581865579.094627608]: I heard: [hello world 6]
[ INFO] [1581865579.194470014]: I heard: [hello world 7]
[ INFO] [1581865579.294641536]: I heard: [hello world 8]
[ INFO] [1581865579.394334407]: I heard: [hello world 9]
[ INFO] [1581865579.494577127]: I heard: [hello world 10]
……

要是运行失败,可以尝试在开启的终端内先运行source ~/catkin_ws1/devel/setup.bash(无返回)

先稍微理解一下node和topic

运行:$ rqt_graph
在这里插入图片描述
node_name1:/talker
node_name2:/listener
topic:/chatter

ros的话题命令,查看所有操作:$ rostopic -h

命令返回
$ rostopic listtopic_name列表/话题列表
$ rostopic echo [topic_name]topic_msg/话题内的消息
$ rostopic type [topic_name]msg_type/消息的数据类型
$ rostopic pub [-1] <topic_name> <msg_type> [-r 1] – [args] [args]向topic发布消息

$ rosmsg show [msg_type] #查看具体的数据类型
可以键入:$ rostopic type [topic_name]|rosmsg show #直接查看具体的数据类型

ros的节点命令,查看所有操作:$ rosnode -h

命令返回
$ rosnode listnode_name列表/正在运行的节点列表
$ rosnode info [node_name]节点信息

$ rosrun [package_name] [node_name] [__name:=new_name] #运行node

python版

可以把程序放在一起问题不大,我还是放在src下

1、在~/catkin_ws/src/beginner_tutorials/src/下新建文件talker.py
2、
修改权限为可执行:$ chmod +x talker.py
写入:

#!/usr/bin/env python
# license removed for brevity
import rospy
from std_msgs.msg import String

def talker():
    pub = rospy.Publisher('chatter', String, queue_size=10)
    rospy.init_node('talker', anonymous=True)
    rate = rospy.Rate(10) # 10hz
    while not rospy.is_shutdown():
        hello_str = "hello world %s" % rospy.get_time()
        rospy.loginfo(hello_str)
        pub.publish(hello_str)
        rate.sleep()

if __name__ == '__main__':
    try:
        talker()
    except rospy.ROSInterruptException:
        pass

1、在~/catkin_ws/src/beginner_tutorials/src/下新建文件listener.py
2、
修改权限为可执行:$ chmod +x listener.py
写入:

#!/usr/bin/env python
import rospy
from std_msgs.msg import String

def callback(data):
    rospy.loginfo(rospy.get_caller_id() + "I heard %s", data.data)
    
def listener():

    # In ROS, nodes are uniquely named. If two nodes with the same
    # name are launched, the previous one is kicked off. The
    # anonymous=True flag means that rospy will choose a unique
    # name for our 'listener' node so that multiple listeners can
    # run simultaneously.
    rospy.init_node('listener', anonymous=True)

    rospy.Subscriber("chatter", String, callback)

    # spin() simply keeps python from exiting until this node is stopped
    rospy.spin()

if __name__ == '__main__':
    listener()

6、回到~/catkin_ws/下:
$ catkin_make

#python为解释型语言不生成可执行文件,本身的py文件权限改成可执行就行了

7、运行测试
开一个终端:$ roscore

再开一个终端:$ rosrun beginner_tutorials talker.py
返回:

[INFO] [1581868522.071705]: hello world 1581868522.07
[INFO] [1581868522.171934]: hello world 1581868522.17
[INFO] [1581868522.272094]: hello world 1581868522.27
[INFO] [1581868522.372026]: hello world 1581868522.37
[INFO] [1581868522.471961]: hello world 1581868522.47
[INFO] [1581868522.572049]: hello world 1581868522.57
[INFO] [1581868522.671977]: hello world 1581868522.67
[INFO] [1581868522.771972]: hello world 1581868522.77
[INFO] [1581868522.871970]: hello world 1581868522.87
[INFO] [1581868522.971982]: hello world 1581868522.97
[INFO] [1581868523.071908]: hello world 1581868523.07
[INFO] [1581868523.171972]: hello world 1581868523.17
……

再开一个终端:$ rosrun beginner_tutorials listener.py
返回:(不从hello world 1开始是因为你开启listener手速不够快)

[INFO] [1581868522.075153]: /listener_28996_1581868519984I heard hello world 1581868522.07
[INFO] [1581868522.174737]: /listener_28996_1581868519984I heard hello world 1581868522.17
[INFO] [1581868522.275262]: /listener_28996_1581868519984I heard hello world 1581868522.27
[INFO] [1581868522.375315]: /listener_28996_1581868519984I heard hello world 1581868522.37
[INFO] [1581868522.475189]: /listener_28996_1581868519984I heard hello world 1581868522.47
[INFO] [1581868522.575409]: /listener_28996_1581868519984I heard hello world 1581868522.57
[INFO] [1581868522.675172]: /listener_28996_1581868519984I heard hello world 1581868522.67
[INFO] [1581868522.775182]: /listener_28996_1581868519984I heard hello world 1581868522.77
[INFO] [1581868522.875275]: /listener_28996_1581868519984I heard hello world 1581868522.87
[INFO] [1581868522.975219]: /listener_28996_1581868519984I heard hello world 1581868522.97
[INFO] [1581868523.075204]: /listener_28996_1581868519984I heard hello world 1581868523.07
[INFO] [1581868523.175072]: /listener_28996_1581868519984I heard hello world 1581868523.17
……

要是运行失败,可以尝试在开启的终端内先运行source ~/catkin_ws1/devel/setup.bash(无返回)

再稍微理解一下node和topic

关闭所有节点,重新开始:
$ roscore
$ rosrun beginner_tutorials talker.py
$ rosrun beginner_tutorials listener #cpp
$ rosrun beginner_tutorials listener.py #python

运行:$ rqt_graph
在这里插入图片描述

node_name1:/talker_29082_1581868746325
node_name2:/listener #cpp
node_name3:/listener_29105_1581868754753 #python
topic:/chatter

至此,你的工作空间变成如下:

.
├── build
├── devel
│   ├── cmake.lock
│   ├── env.sh
│   ├── lib
│   │   ├── beginner_tutorials
│   │   │   ├── listener
│   │   │   └── talker
│   │   └── pkgconfig
│   │       └── beginner_tutorials.pc
│   ├── local_setup.bash
│   ├── local_setup.sh
│   ├── local_setup.zsh
│   ├── setup.bash
│   ├── setup.sh
│   ├── _setup_util.py
│   ├── setup.zsh
│   └── share
└── src
    ├── beginner_tutorials
    │   ├── CMakeLists.txt
    │   ├── include
    │   │   └── beginner_tutorials
    │   ├── package.xml
    │   └── src
    │       ├── listener.cpp
    │       ├── listener.py
    │       ├── talker.cpp
    │       └── talker.py
    └── CMakeLists.txt -> /opt/ros/melodic/share/catkin/cmake/toplevel.cmake

#build和devel内有很多文件,此处我隐藏了,可以看到~/catkin_ws/devel/lib/
#有talker.cpp和listener.cpp编译生成的可执行文件talker和listener
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值