ROS学习1

ROS学习

ros 新手学习:推荐b站故月居 和 奥特学院

两个学习链接:https://www.guyuehome.com/34657

https://www.ncnynl.com/archives/201701/1279.html

ROS构建工作空间

//一般在 /home/caros/ 下面添加ros工作空间
mkdir -p ~/catkin_ws/src
// mkdir 创建文件夹, -p参数 可以迭代创建,也就是可以创建多级目录  
// catkin_ws为工作空间的文件夹,可以自己取名,ws为sorkspace的缩写

cd catkin_ws
catkin_make
// catkin_make命令在catkin 工作空间中是一个非常方便的工具。如果你查看一下当前目录应该能看到'build'和'devel'这两个文件夹。在'devel'文件夹里面你可以看到几个setup.sh文件。source这些文件中的任何一个都可以将当前工作空间设置在ROS工作环境的最顶层,想了解更多请参考catkin文档。

source devel/setup.bash
//这步是激活环境,而这个setup.bash的作用是让一些ROS* 开头的命令可以使用。



ROS 构建catkin包

//首先回到 /catkin_ws/src目录下
cd ~/catkin_ws/src/

//创建catkin包  !!!! 这一步极为关键,ros中运行程序和c++不一样,所有的程序必须创建包才能运行
catkin_create_pkg [包的名字] [依赖的ros库] [依赖的ros库] [...]
//eg :catkin_create_pkg helloword rospy roscpp std_msgs

创建包之后,包里面就自动有了CMakeLists.txt 和 package.xml 。这两个文件很关键!!!

ROS发布者Publish的编程实现

ros如何实现一个发布者:

  • 初始化ROS节点
  • 向ROS Master 注册节点信息,包括发布的话题名和话题中的消息类型
  • 创建消息数据
  • 按照一定频率循环发布消息
#include <ros/ros.h> //导入ROS系统包含核心公共头文件
#include <std_msgs/String.h> //导入std_msgs/String消息头文件,这个是由std_msgs包的string.msg文件自动生成。std_msgs这是标准的消息包,可参考std_msgs ,更多的标准消息定义,可参考msg

#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"); //初始化ROS,指定节点名称为“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);  //发布一个消息类型为std_msgs/String,命名为chatter的话题。定义消息队列大小为1000,即超过1000条消息之后,旧的消息就会丢弃。
  ros::Rate loop_rate(10); //指定发布消息的频率,这里指10Hz,也即每秒10次。通过 Rate::sleep()来处理睡眠的时间来控制对应的发布频率。

  /**
   * A count of how many messages we have sent. This is used to create
   * a unique string for each message.
   */
  int count = 0;
  //默认roscpp会植入一个SIGINT处理机制,当按下Ctrl-C,就会让ros::ok()返回false,那循环就会结束。
  //ros::ok() 返回false的几种情况:
  //SIGINT收到(Ctrl-C)信号
  //另一个同名节点启动,会先中止之前的同名节点
  //ros::shutdown()被调用
  //所有的ros::NodeHandles被销毁
  while (ros::ok())
  {
    /**
     * This is a message object. You stuff it with data, and then publish it.
     */
    std_msgs::String msg; //实例化消息msg, 定义字符串流“hello world”并赋值给ss, 最后转成为字符串赋值给msg.data

    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(); //根据之前ros::Rate loop_rate(10)的定义来控制发布话题的频率。定义10即为每秒10次
    ++count;
  }


  return 0;
}

配置CMakeLists.txt

//添加到# Install ##正上方
add_executable(helloworld(可执行二进制程序的名字) (包含的文件)src/helloworld.cpp)
target_link_libraries(helloworld(可执行二进制程序的名字)  ${catkin_LIBRARIES})

ROS订阅者Subscriber的编程实现

如何实现一个订阅者:

  • 初始化ROS节点;
  • 订阅需要的话题
  • 循环等待话题消息,接受到消息后进入回调函数
  • 在回调函数中出完成消息的处理
cd learning_topic/src/
touch velocity_publisher.cpp
//代码
/**
 * 该例程将订阅/turtle1/pose话题,消息类型turtlesim::Pose
 */
 
#include <ros/ros.h>
#include "turtlesim/Pose.h"
 
// 接收到订阅的消息后,会进入消息回调函数
void poseCallback(const turtlesim::Pose::ConstPtr& msg)
{
    // 将接收到的消息打印出来
    ROS_INFO("Turtle pose: x:%0.6f, y:%0.6f", msg->x, msg->y);
}
 
int main(int argc, char **argv)
{
    // 初始化ROS节点
    ros::init(argc, argv, "pose_subscriber");
 
    // 创建节点句柄
    ros::NodeHandle n;
 
    // 创建一个Subscriber,订阅名为/turtle1/pose的topic,注册回调函数poseCallback
    ros::Subscriber pose_sub = n.subscribe("/turtle1/pose", 10, poseCallback);
 
    // 循环等待回调函数
    ros::spin();
 
    return 0;
}

编译并运行订阅者

//配置CMakeLists.txt
add_executable(pose_subscriber src/pose_subscriber.cpp)
target_link_libraries(pose_subscriber ${catkin_LIBRARIES})

ROS 接收2个消息,并同步

ROS消息的转换

msgs_PointCloud2 转换为 pcl点云数据

 //输入的数据为sensor_msgs::PointCloud2::ConstPtr& pointCloud_
pcl::PCLPointCloud2 pcl_pc2;  //声明pcl pointcloud2
pcl_conversions::toPCL(*pointCloud_,pcl_pc2);  //ros pointcloud2 转 pcl pointcloud2
pcl::PointCloud<pcl::PointXYZI>::Ptr temp_cloud(new pcl::PointCloud<pcl::PointXYZI>); //声明pcl pointxyz
pcl::fromPCLPointCloud2(pcl_pc2,*temp_cloud);  //pcl pointcloud2 转 pcl pointxyz
// 利用了ros包 <pcl_conversions/pcl_conversions.h>  <pcl_ros/transforms.h>

msgs_Image 转换为cv::Mat

cv_bridge::CvImagePtr cv_ptr = cv_bridge::toCvCopy(image_,sensor_msgs::image_encodings::TYPE_8UC3);
//利用了 ros包  <cv_bridge/cv_bridge.h>

//cv::Mat 转 msgs_Image
sensor_msgs::ImagePtr msgsImage = 
cv_bridge::CvImage(std_msgs::Header(), "bgr8", image1).toImageMsg();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值