ROS:VScode开发话题(msg)、服务(srv)、动作(action)、TF,解决 无法打开源文件

news2024/11/22 5:39:51

一.解决 无法打开源文件

出错原因:系统没有找到.h文件对应的路径。

在编写完msg、srv、action文件后,要进行编译(catkin_make) .

编译之后,msg、srv、action会生成相应的.h文件

其对应的.h文件目录在devel/include/功能包下,如下:

 解决方法:将.h文件目录加入json文件中即可。

"${workspaceFolder}/devel/include",

 然后保存json文件,就好了。

二.话题

1.案例一

talker.cpp

#include "ros/ros.h"
#include <sstream>
#include "std_msgs/String.h"

int main(int argc, char** argv){
    //ROS结点初始化
    ros::init(argc, argv, "talker");
    //创建节点句柄
    ros::NodeHandle nh;
    //创建一个publisher,发布名为chatter的topic,消息类型为std_msgs,队列长度为1000
    ros::Publisher chatter_pub=nh.advertise<std_msgs::String>("chatter",1000);
    //设置循环频率
    ros::Rate loop_Rate(10);
    int count=0;
    while(ros::ok()){
        //初始化std_msgs::String类型的消息
        std_msgs::String msg;
        std::stringstream ss;
        ss<<"hello world:"<<count;
        msg.data=ss.str();
        //发布消息
        ROS_INFO("%s",msg.data.c_str());
        chatter_pub.publish(msg);
        //回调函数:执行一次回调函数,在这里其实没什么用
        ros::spinOnce();
        //按照循环频率延时
        loop_Rate.sleep();
        ++count;
    }
    return 0;
}

listener.cpp

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

//接收到topic后,会进入回调函数
void chatterCallback(const std_msgs::String::ConstPtr& msg){
    //打印topic信息
    ROS_INFO("I heard [%s]",msg->data.c_str());
}

int main(int argc,char **argv){
    //初始化ros节点
    ros::init(argc,argv,"listener");
    //创建节点句柄
    ros::NodeHandle nh;
    //创建一个subscribler,订阅topic为“chatter”,注册回调函数chatterCallback
    ros::Subscriber sub=nh.subscribe("chatter",1000,chatterCallback);
    //循环等待执行回调函数
    ros::spin();
    return 0;
}

CMakeList.txt

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

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

2.案例二:自定义msg文件

创建名为msg的文件夹

定义msg文件,name、sex、age是变量,unknow、male、female是常量:

Person.msg

# 变量
string name
uint8 sex
uint8 age
#常量
uint8 unknow=0
uint8 male=1
uint8 female=2

package.xml 添加功能包依赖:

  <!--添加功能包依赖:msg、srv-->
  <build_depend>std_msgs</build_depend>
  <exec_depend>std_msgs</exec_depend>
  <build_depend>message_generation</build_depend>
  <exec_depend>message_runtime</exec_depend>

其中:部分ROS版本中 exec_depend需要改为run_depend

CMakeLists.txt添加编译选项:

find_package(catkin REQUIRED COMPONENTS
  message_generation
)
add_message_files(
  FILES
  Person.msg
)
generate_messages(
  DEPENDENCIES
  std_msgs
)
catkin_package(
 CATKIN_DEPENDS geometry_msgs roscpp std_msgs message_runtime
)

 之后catkin_make

查看自己定义的msg

rosmsg show Person

三.服务

创建名为srv的文件夹

定义srv文件,a、b是请求数据,sum是服务数据,也就是a、b传给服务器,服务器相加sum传给客户端:

AddTwoInts.srv

#客户端
int64 a
int64 b
---
#服务器
int64 sum

package.xml 添加功能包依赖:

  <!--添加功能包依赖:msg、srv-->
  <build_depend>std_msgs</build_depend>
  <exec_depend>std_msgs</exec_depend>
  <build_depend>message_generation</build_depend>
  <exec_depend>message_runtime</exec_depend>

其中:部分ROS版本中 exec_depend需要改为run_depend

CMakeLists.txt添加编译选项:

find_package(catkin REQUIRED COMPONENTS
  message_generation
)
add_service_files(
  FILES
  AddTwoInts.srv
)
catkin_package(
 CATKIN_DEPENDS geometry_msgs roscpp std_msgs message_runtime
)

查看自己定义的srv文件:

rossrv show AddTwoInts.srv 

client.cpp

#include <cstdlib>
#include "ros/ros.h"
#include "robot_setup_tf/AddTwoInts.h"

int main(int argc,char** argv){
    //ROS节点初始化
    ros::init(argc,argv,"add_two_ints_client");
    //从终端命令行获取两个加数
    if(argc!=3){
        ROS_INFO("usage: add_two_ints_client X Y");
        return 1;
    }
    //创建节点句柄
    ros::NodeHandle nh;
    //创建一个client,请求add_two_service
    //service消息类型是robot_setup_tf::AddTwoInts
    ros::ServiceClient client=nh.serviceClient<robot_setup_tf::AddTwoInts>("add_two_ints");
    //创建robot_setup_tf::AddTwoInts类型的消息对象
    robot_setup_tf::AddTwoInts srv;
    srv.request.a=atoll(argv[1]);
    srv.request.b=atoll(argv[2]);
    //发布service请求,等待加法运算
    if(client.call(srv)){
        ROS_INFO("Sum=%ld",(long int)srv.response.sum);
    }else{
        ROS_INFO("Failed to call service add_two_ints");
        return 1;
    }
    return 0;
}

server.cpp 

#include "ros/ros.h"
#include "robot_setup_tf/AddTwoInts.h"

//回调函数,client传进a、b,完成加法后返回给sum
bool add(robot_setup_tf::AddTwoInts::Request  &req, robot_setup_tf::AddTwoInts::Response &res)
{
    res.sum=req.a+req.b;
    ROS_INFO("request: x=%ld, y=%ld",(long int)req.a,(long int)req.b);
    ROS_INFO("response: sum=%ld",(long int)res.sum);
    return true;
}
int main(int argc,char** argv){
    //ROS节点初始化
    ros::init(argc,argv,"add_two_ints_server");
    //创建节点句柄
    ros::NodeHandle nh;
    //创建一个名为"add_two_ints"的server,注册回调函数为add()
    ros::ServiceServer service=nh.advertiseService("add_two_ints",add);
    //循环等待回调函数
    ROS_INFO("Ready to add two ints");
    ros::spin();
    return 0;
}

CMakeList.txt

add_executable(server src/server.cpp)
target_link_libraries(server ${catkin_LIBRARIES})
add_dependencies(server ${PROJECT_NAME}_gencpp)

add_executable(client src/client.cpp)
target_link_libraries(client ${catkin_LIBRARIES})
add_dependencies(client ${PROJECT_NAME}_gencpp)

运行:

roscore
rosrun robot_setup_tf server
rosrun robot_setup_tf client 4 5

四.动作

创建名为action文件夹

创建action文件

DoDishes.action

#goal,定义目标信息,客户端
uint8 dishwasher_id
#Specify which dishwasher we want to use
---
#result,定义结果信息,服务器
uint8 total_dishes_cleaned
---
#feedback,定义周期反馈的消息
float32 percent_complete

package.xml添加功能包依赖

  <!--添加功能包依赖:action-->
  <build_depend>actionlib</build_depend>
  <build_depend>actionlib_msgs</build_depend>
  <exec_depend>actionlib</exec_depend>
  <exec_depend>actionlib_msgs</exec_depend>

CMakeLists.txt添加编译选项:

find_package(catkin REQUIRED COMPONENTS
  actionlib_msgs
  actionlib
)
add_action_files(
  FILES
  DoDishes.action
)
generate_messages(
  DEPENDENCIES
  actionlib_msgs
)

DoDishes_Client.cpp

#include <actionlib/client/simple_action_client.h>
#include "robot_setup_tf/DoDishesAction.h"

typedef actionlib::SimpleActionClient<robot_setup_tf::DoDishesAction> Client;
//当action完成后会调用该回调函数一次
void doneCb(const actionlib::SimpleClientGoalState& state,const robot_setup_tf::DoDishesResultConstPtr& result){
    ROS_INFO("Yay!The dishes are now clean");
    ros::shutdown();
}
//当action激活后会调用该回调函数一次
void activeCb(){
    ROS_INFO("Goal just went active");
}
//收到feedback后调用该回调函数
void feedbackCb(const robot_setup_tf::DoDishesFeedbackConstPtr& feedback){
    ROS_INFO("percent_complete: %f",feedback->percent_complete);
}
int main(int argc,char** argv){
    ros::init(argc,argv,"do_dishes_client");
    //定义一个客户端
    Client client("do_dishes",true);
    //等待服务器端
    ROS_INFO("Waiting for action server to start.");
    client.waitForServer();
    ROS_INFO("Action server started,sending goal.");
    //创建一个action的goal
    robot_setup_tf::DoDishesGoal goal;
    goal.dishwasher_id=1;
    //发送action的goal给服务器端,并且设置回调函数
    client.sendGoal(goal,&doneCb,&activeCb,&feedbackCb);
    ros::spin();
    return 0;
}

DoDishes_Server.cpp

#include "ros/ros.h"
#include <actionlib/server/simple_action_server.h>
#include "robot_setup_tf/DoDishesAction.h"

typedef actionlib::SimpleActionServer<robot_setup_tf::DoDishesAction> Server;

//收到action的goal后调用该回调函数
void execute(const robot_setup_tf::DoDishesGoalConstPtr& goal,Server* as){
    ros::Rate r(1);
    robot_setup_tf::DoDishesFeedback feedback;
    ROS_INFO("Dishwasher %d is working.",goal->dishwasher_id);
    //假设洗盘子的进度,并且按照1hz的频率发布进度feedback
    for(int i=1;i<=10;i++){
        feedback.percent_complete=i*10;
        as->publishFeedback(feedback);
        r.sleep();
    }
    //当action完成后,向客户端返回结果
    ROS_INFO("Dishwasher %d finish working.",goal->dishwasher_id);
    as->setSucceeded();
}
int main(int argc,char** argv){
    ros::init(argc,argv,"do_dishes_server");
    ros::NodeHandle n;
    //定义一个服务器
    Server server(n,"do_dishes",boost::bind(&execute,_1,&server),false);
    //服务器开始运行
    server.start();
    ros::spin();
    return 0;
}

CMakeList.txt

add_executable(DoDishes_Client src/DoDishes_Client.cpp)
target_link_libraries( DoDishes_Client ${catkin_LIBRARIES})
add_dependencies(DoDishes_Client ${${PROJECT_NAME}_EXPORTED_TARGETS})

add_executable(DoDishes_Server src/DoDishes_Server.cpp)
target_link_libraries( DoDishes_Server ${catkin_LIBRARIES})
add_dependencies(DoDishes_Server ${${PROJECT_NAME}_EXPORTED_TARGETS})

五.TF编程:小乌龟跟随

turtle_tf_broadcaster.cpp

 /*
  该例程产生tf数据,并计算、发布turtle2的速度指令
 */

#include <ros/ros.h>
#include <tf/transform_broadcaster.h>
#include <turtlesim/Pose.h>

std::string turtle_name;

void poseCallback(const turtlesim::PoseConstPtr& msg)
{
        // 创建tf的广播器
        static tf::TransformBroadcaster br;

        // 根据乌龟当前的位姿,设置相对于世界坐标系的坐标变换
        tf::Transform transform;
        transform.setOrigin( tf::Vector3(msg->x, msg->y, 0.0) );
        tf::Quaternion q;  
        q.setRPY(0, 0, msg->theta);
        transform.setRotation(q);

        // 发布坐标变换
        br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "world", turtle_name));
}

int main(int argc, char** argv)
{
    // 初始化ROS节点
        ros::init(argc, argv, "my_tf_broadcaster");
        // 输入参数作为海龟的名字
        if (argc != 2)
        {
                ROS_ERROR("need turtle name as argument");
                return -1;
        }
        turtle_name = argv[1];
        // 订阅海龟的位姿话题
        ros::NodeHandle node;
        ros::Subscriber sub = node.subscribe(turtle_name+"/pose", 10, &poseCallback);
    // 循环等待回调函数
        ros::spin();
        return 0;
};

turtle_tf_listener.cpp

/**
 * 该例程监听tf数据,并计算、发布turtle2的速度指令
 */

#include <ros/ros.h>
#include <tf/transform_listener.h>
#include <geometry_msgs/Twist.h>
#include <turtlesim/Spawn.h>

int main(int argc, char** argv)
{
        // 初始化ROS节点
        ros::init(argc, argv, "my_tf_listener");

    // 创建节点句柄
        ros::NodeHandle node;

        // 请求产生turtle2
        ros::service::waitForService("/spawn");
        ros::ServiceClient add_turtle = node.serviceClient<turtlesim::Spawn>("/spawn");
        turtlesim::Spawn srv;
        add_turtle.call(srv);

        // 创建发布turtle2速度控制指令的发布者
        ros::Publisher turtle_vel = node.advertise<geometry_msgs::Twist>("/turtle2/cmd_vel", 10);

        // 创建tf的监听器
        tf::TransformListener listener;

        ros::Rate rate(10.0);
        while (node.ok())
        {
                // 获取turtle1与turtle2坐标系之间的tf数据
                tf::StampedTransform transform;
                try
                {
                        //在tf树中查找等待"/turtle2", "/turtle1"是否存在对应变换,超时时间ros::Duration(3.0),如果不设置超时时间,可能会一直卡死
                        listener.waitForTransform("/turtle2", "/turtle1", ros::Time(0), ros::Duration(3.0));
                        listener.lookupTransform("/turtle2", "/turtle1", ros::Time(0), transform);
                }
                catch (tf::TransformException &ex)
                {
                        ROS_ERROR("%s",ex.what());
                        ros::Duration(1.0).sleep();
                        continue;
                }

                // 根据turtle1与turtle2坐标系之间的位置关系,发布turtle2的速度控制指令
                geometry_msgs::Twist vel_msg;
                vel_msg.angular.z = 4.0 * atan2(transform.getOrigin().y(),
                                                        transform.getOrigin().x());
                vel_msg.linear.x = 0.5 * sqrt(pow(transform.getOrigin().x(), 2) +
                                                      pow(transform.getOrigin().y(), 2));
                turtle_vel.publish(vel_msg);

                rate.sleep();
        }
        return 0;
};

tf_demo.launch

<launch>
    <!--海龟仿真器-->
    <node pkg="turtlesim" type="turtlesim_node" name="sim"/>

    <!--键盘控制-->
    <node pkg="turtlesim" type="turtle_teleop_key" name="teleop" output="screen"/>

    <!--两只海龟的tf广播-->
    <node pkg="my_tf" type="turtle_tf_broadcaster" args="/turtle1" name="turtle1_tf_broadcaster"/>
    <node pkg="my_tf" type="turtle_tf_broadcaster" args="/turtle2" name="turtle2_tf_broadcaster"/>

    <!--监听tf广播,并且控制turtle2移动--> 
    <node pkg="my_tf" type="turtle_tf_listener" name="listener"/>
</launch>

CMakeLists.txt

find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  tf
  turtlesim
)

add_executable(turtle_tf_broadcaster src/turtle_tf_broadcaster.cpp)
target_link_libraries(turtle_tf_broadcaster ${catkin_LIBRARIES})

add_executable(turtle_tf_listener src/turtle_tf_listener.cpp)
target_link_libraries(turtle_tf_listener ${catkin_LIBRARIES})

运行:

roslaunch my_tf tf_demo.launch

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/618563.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python解决坐标系两点之间有多少种走法问题

问题&#xff1a;在坐标系中第一象限内的点P&#xff08;x,y&#xff09; x<6&#xff0c;y<6. 到终点&#xff08;5,5&#xff09;有多少种走法&#xff1f;并显示出现所经过的点坐标 限制条件&#xff1a;从起点坐标只能向上或者向右走。其中&#xff08;4,3&…

从零开始学习JavaScript:轻松掌握编程语言的核心技能⑥

从零开始学习JavaScript&#xff1a;轻松掌握编程语言的核心技能⑥ 1. JavaScript 对象2. JavaScript 类3. JavaScript prototype&#xff08;原型对象&#xff09;4. prototype 继承5. JavaScript Number 对象5.1 JavaScript 数字 6. JavaScript 字符串&#xff08;String&…

某麦网apk抢票接口加密参数分析(一)

某麦网apk抢票接口加密参数分析&#xff08;一&#xff09; 当下的一些火爆活动&#xff0c;如音乐节、演唱会等需要购买门票的活动&#xff0c;常常会引发一些网络抢票软件的出现。 而某麦网也不例外&#xff0c;很多人使用抢票软件来抢购某些活动的门票。 为了防止这种情况…

基于决策树的泰坦尼克号数据集回归预测

目录 1、作者介绍2、决策树算法2.1 决策树原理2.1.1 基本原理2.1.2 节点的概念 2.2 构建决策树2.3 决策树优缺点 3、实验设计3.1 数据集简介3.2 代码实现3.3 运行结果 4、参考链接 1、作者介绍 任正福&#xff0c;男&#xff0c;西安工程大学电子信息学院&#xff0c;2022级研…

【大数据工具】Kafka伪分布式、分布式安装和Kafka-manager工具安装与使用

Kafka 安装 Kafka 安装包下载地址&#xff1a;https://archive.apache.org/dist/kafka/ 1. Kafka 伪分布式安装 1. 上传并解压 Kafka 安装包 使用 FileZilla 或其他文件传输工具上传 Kafka 安装包&#xff1a;kafka_2.11-0.10.0.0.tgz解压安装包 [rootbigdata software]# …

为什么添加缓存要在释放锁之前?

为什么加缓存要放在释放锁之前&#xff1f; 线程拿到锁会去查缓存是否有数据&#xff0c;又因为我们向redis存入缓存数据是在释放锁之后 那么释放锁之后&#xff0c;下一个线程查缓存&#xff0c;上一个线程并未存入完成。此时就会出现查询多次数据库的情况&#xff0c;锁失效…

chatgpt赋能python:Python如何重复运行——让你的代码运行更高效

Python如何重复运行——让你的代码运行更高效 Python作为一种非常流行的编程语言&#xff0c;在程序员中间被广泛使用。无论是从事科学计算、数据分析还是网页爬虫&#xff0c;都离不开Python。但是&#xff0c;如果你只会最基础的Python语法&#xff0c;你可能会花费更多的时…

《三维存储芯片技术》----学习记录(一)

第1章 NAND存储器的生态 1.1 存储器行业变迁 可以说近10年是整个存储行业历史上变化最大的10年。 1.1.1 NAND及存储器供应商的整合 如图1.1所示&#xff0c;过去6年中&#xff0c;全球存储器95%的供应集中到5家厂商。 图片来源于《三维存储芯片技术》 1.1.2 NAND技术发展 …

行业应用|立仪光谱共焦位移传感器在玻璃方面的检测

项目&#xff1a;玻璃管管壁单边测厚 行业应用|立仪光谱共焦位移传感器在玻璃方面的检测 行业应用|立仪光谱共焦位移传感器在玻璃方面的检测 检测方案 用D35A7镜头对玻璃管管壁进行单边测厚&#xff0c;取三个点静态测量厚度并记录重复性。 1、采用D35A7R2S35镜头对玻璃管管…

springboot+vue企业设备管理系统

解决的思路&#xff1a; &#xff08;1&#xff09;通过进行需求分析&#xff0c;建立用例模型&#xff0c;上网查找资料&#xff0c;摸清业务流程。 &#xff08;2&#xff09;通过运用vue 技术进行界面的设计&#xff0c;上网搜集符合所做管理系统的相关图片&#xff0c;使用…

springboot 配置文件密码加密处理

一、修改pom文件 <dependency> <groupId>com.github.ulisesbocchio</groupId> <artifactId>jasypt-spring-boot-starter</artifactId> <version>3.0.4</version> </dependency> 二、在启动类中加上注解 EnableEncryptableProp…

开源实时位置共享服务Hauk

【勘误】&#xff1a;在上文 『事务与项目跟踪软件Jira』 一文中&#xff0c;老苏错误的将 4G 内存写成了 4M&#xff0c;感谢网友 纸飞机 和 cwz 的指正。虽然老苏确实用过 4M 内存的机器&#xff0c;但那是20 多年前的事情了。 什么是 Hauk &#xff1f; Hauk 是一个完全开源…

Mysql数据库入门基础篇--mysql基本了解

【Mysql数据库入门基础篇--mysql基本了解 &#x1f53b;一、Mysql5.7 VS Mysql8.0 详解1.1 ⛳字符编码1.2 ⛳用户的创建与授权1.3 ⛳ 认证插件1.4 ⛳ 隐藏索引1.5 ⛳ 持久化设置1.6 ⛳ 通用表达式&#xff08;Common Table Expressions&#xff09;1.7 ⛳ 性能提升1.8 ⛳ 参数变…

chatgpt赋能python:Python如何输出在同一行

Python如何输出在同一行 在Python编程中&#xff0c;有时候我们需要将多个输出放在同一行中。这篇文章将介绍几种方法来实现这个任务&#xff0c;并给出一些例子来帮助你更好地理解。 方法一&#xff1a;使用print函数 Python中的print函数默认会在每个输出之间换行。但是&a…

【大数据工具】HBase 集群搭建与基本使用

HBase 集群搭建 HBase 安装包下载地址&#xff1a;https://archive.apache.org/dist/hbase/ 安装 HBase 的前提&#xff1a; ZooKeeper 集群 OKHadoop 集群 OK 1. HBase 集群安装 1. 将 HBase 软件包上传至 Hadoop0 解压并重命名 使用 FileZilla 将 hbase-1.3.1-bin.tar.g…

pytorch中Dataloader读取数据太慢的问题

文章目录 pytorch中Dataloader读取数据太慢的问题1. 方法2. 方法3. 解决方法&#xff1a;提取加载数据 pytorch中Dataloader读取数据太慢的问题 数据读取的速度远远大于GPU训练的速度&#xff0c;导致整个训练流程中有大部分时间都在等待数据发送到GPU&#xff0c;在资源管理器…

七年磨一剑!苹果王炸产品Vision Pro诞生,未来已来

这是第一款「不见却可透见」的苹果产品 等了整整七年&#xff01;2023年6月5日&#xff0c;WWDC23大会上&#xff0c;苹果发布首款头显Vision Pro&#xff0c;Vision Pro 可以算是苹果公司自 2015 年 Apple Watch 首次亮相以来最大的硬件产品发布&#xff0c;或许它会彻底改变数…

【深度学习】BERT变种—百度ERNIE 1.0

ERNIE: Enhanced Representation through Knowledge Integration是百度在2019年4月的时候&#xff0c;基于BERT模型&#xff0c;做的进一步优化&#xff0c;在中文的NLP任务上得到了state-of-the-art的结果。 ERNIE 是百度开创性提出的基于知识增强的持续学习语义理解框架&…

苹果又一黑科技产品 Apple Vision Pro,正式问世!

公众号关注 “GitHubDaily” 设为 “星标”&#xff0c;每天带你逛 GitHub&#xff01; 在电影《钢铁侠》中&#xff0c;托尼通过简单的手势动作&#xff0c;配合空间中的虚拟界面&#xff0c;成功将贾维斯创造出来。 当时片中的这个镜头&#xff0c;让无数科幻迷为之疯狂&…

pyspark数据输入

学习目标&#xff1a; 现在只需要知道PDD是一个数据集。 【运行实例&#xff08;1&#xff09;】&#xff1a; from pyspark import SparkConf, SparkContext # conf:创建对象&#xff1b;Sparkconf&#xff1a;创建入口&#xff1b;setMaster&#xff1a;运行方式&#xff1…