ROS:古月居第一次作业(话题与服务编程、动作编程、TF编程)

news2024/12/23 3:41:42

一.话题与服务编程

话题与服务编程:通过代码新生一只海龟,放置在(5,5)点,命名为“turtle2”;通过代码订阅turtle2的实时位置并打印在终端;控制turtle2实现旋转运动;

demo_turtle.launch

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

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

demo_turtle.cpp

#include <ros/ros.h>
#include <turtlesim/Spawn.h>//创建turtle2
#include <turtlesim/Pose.h>//订阅turtle的位姿信息
#include <geometry_msgs/Twist.h>//发布速度信息

ros::Publisher pub;

//回调函数打印turtle2的position
void poseCallback(const turtlesim::PoseConstPtr &msg){
     ROS_INFO("turtle2: X=[%.2f], Y=[%.5f]",msg->x,msg->y);
}

int main(int argc,char** argv){
     ros::init(argc,argv,"create_turtle2");
     ros::NodeHandle node;
     //通过服务调用,产生第二只乌龟turtle2
     ros::service::waitForService("spawn");
     ros::ServiceClient add_turtle=node.serviceClient<turtlesim::Spawn>("spawn");
     turtlesim::Spawn srv;
     srv.request.x=5;//初始化机器人位置
     srv.request.y=5;
     srv.request.name="turtle2";
     add_turtle.call(srv);
     ROS_INFO("turtle2 already!");

     //订阅乌龟位姿信息
     ros::Subscriber sub=node.subscribe("/turtle2/pose",10,&poseCallback);

     ROS_INFO("publish vel_cmd!");
     //发布速度信息
     pub=node.advertise<geometry_msgs::Twist>("/turtle2/cmd_vel",10);
     ros::Rate r(10.0);
     while(ros::ok()){
          //发布速度信息
          geometry_msgs::Twist twist;
          twist.angular.z=0.5;
          twist.linear.x=0.5;
          pub.publish(twist);
          ros::spinOnce();
          r.sleep();
     }
     return 0;
}

CMakeList.txt

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

运行:

roslaunch demo_tf demo_turtle.launch
rosrun demo_tf demo_turtle

结果:

二.动作编程

动作编程:客户端发送一个运动目标,模拟机器人运动到目标位置的过程,包含服务端和客户端的代码实现,要求带有实时位置反馈。

demo_Client_move.cpp

#include <ros/ros.h>
#include <actionlib/client/simple_action_client.h>
#include "demo_tf/moveAction.h"

typedef actionlib::SimpleActionClient<demo_tf::moveAction> Client;

//当action完成后会调用该回调函数一次
void doneCb(const actionlib::SimpleClientGoalState& state,const demo_tf::moveResultConstPtr& result){
     ROS_INFO("Yay! start moving!");
     ros::shutdown();
}
//当action激活后会调用该回调函数一次
void activeCb(){
     ROS_INFO("Goal just went active");
}
//收到feedback后调用该回调函数
void feedbackCb(const demo_tf::moveFeedbackConstPtr& feedback){
     ROS_INFO("percent_complete: X=[%f], Y=[%f], theta=[%f]",feedback->present_turtle_x,feedback->present_turtle_y,feedback->present_turtle_theta);
}
int main(int argc,char** argv){
     ros::init(argc, argv, "Client");
     //定义一个客户端
     Client client("move_client",true);
     //等待服务器端
     ROS_INFO("waitint for action server to start.");
     client.waitForServer();
     ROS_INFO("action server started, sending goal");
     //创建一个action的goal
     demo_tf::moveGoal goal;
     goal.turtle_target_x=6.5;
     goal.turtle_target_y=0;
     goal.turtle_target_theta=0;
     //发送action的goal给服务器,并且设置回调函数
     client.sendGoal(goal,&doneCb,&activeCb,&feedbackCb);
     ros::spin();
     return 0;
}

demo_Service_move.cpp

#include <ros/ros.h>
#include <actionlib/server/simple_action_server.h>
#include "demo_tf/moveAction.h"
#include <turtlesim/Pose.h>
#include <geometry_msgs/Twist.h>

typedef actionlib::SimpleActionServer<demo_tf::moveAction> Server;
//创建发布者
ros::Publisher pub;
//记录机器人位置
struct pos{
     float x;
     float y;
     float theta;
}origin_pos,target_pos;
//订阅小乌龟pose
void poseCallBack(const turtlesim::PoseConstPtr& msg){
     //打印每一次turtle的位姿
     ROS_INFO("Turtle origin position: [%f], [%f], [%f]",msg->x,msg->y,msg->theta);
     origin_pos.x=msg->x;
     origin_pos.y=msg->y;
     origin_pos.theta=msg->theta;
}
//收到action的goal后调用该回调函数
void execute(const demo_tf::moveGoalConstPtr& goal,Server* as){
     ros::Rate r(10);
     demo_tf::moveFeedback feedback;
     ROS_INFO("Turtle goal position: X=[%f], Y=[%f], theta=[%f]",goal->turtle_target_x,goal->turtle_target_y,goal->turtle_target_theta);
     target_pos.x=goal->turtle_target_x;
     target_pos.y=goal->turtle_target_y;
     target_pos.theta=goal->turtle_target_theta;
     geometry_msgs::Twist vel_msgs;
     while(ros::ok()){
          //发布速度指令
          vel_msgs.linear.x = 0.1; 
          vel_msgs.angular.z = 0.; 
 		pub.publish(vel_msgs);
          //发布反馈信息(当前机器人位置)
          feedback.present_turtle_x=origin_pos.x;
          feedback.present_turtle_y=origin_pos.y;
          feedback.present_turtle_theta=origin_pos.theta;
          as->publishFeedback(feedback);
          //判断是否到达目标点
          if(target_pos.x<=origin_pos.x&&target_pos.y<=origin_pos.y&&target_pos.theta<=origin_pos.theta){
               //发布速度指令
               vel_msgs.linear.x = 0.; 
               vel_msgs.angular.z = 0.; 
 		     pub.publish(vel_msgs);
               break;
          } 
          else
               r.sleep();
     }
     as->setSucceeded();
}
int main(int argc,char** argv){
     ros::init(argc,argv,"Server");
     ros::NodeHandle n,node_server;
     //订阅小乌龟的位置信息
     ros::Subscriber sub=node_server.subscribe("turtle1/pose",10,&poseCallBack);
     //申请发布速度
     pub=node_server.advertise<geometry_msgs::Twist>("turtle1/cmd_vel",10);
     //定义一个服务器 "move_client"为客户端名称(要注意对应)
     Server server(n,"move_client",boost::bind(&execute,_1,&server),false);
     ROS_INFO("waiting_Server");
     //服务器开始运行
     server.start();
     ROS_INFO("start_Server");
     ros::spin();
     return 0;
}

debug.launch 

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

CMakeList.txt

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

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

运行:

roslaunch demo_tf demo_turtle.launch
rosrun demo_tf demo_Client_move

三.TF编程

广播并监听机器人你的坐标变换,已知激光雷达和机器人底盘的坐标关系,求解激光雷达数据在底盘坐标系下的坐标值。

tf_broadcaster.cpp

/*
     发布tf变换
*/
#include <ros/ros.h>
#include <tf/transform_broadcaster.h>

int main(int argc,char** argv){
     ros::init(argc,argv,"tf_nroadcaster");
     ros::NodeHandle node;
     static tf::TransformBroadcaster br;
     while(ros::ok()){
          //初始化tf数据,设定变换矩阵,也就是激光雷达在底盘坐标系下转换
          //laser_word*word_base=laser_base=transform
          tf::Transform transform;
          transform.setOrigin(tf::Vector3(0.1,0.1,0.2));
          transform.setRotation(tf::Quaternion(0,0,0,2));
          //广播base_link和base_laser坐标系之间的tf数据
          br.sendTransform(tf::StampedTransform(transform,ros::Time::now(),"base_link","base_laser"));
     }
     return 0;
}

tf_listener.cpp

/*
*/
#include <ros/ros.h>
#include <tf/transform_listener.h>
#include <geometry_msgs/PointStamped.h>

int main(int argc, char *argv[])
{
    ros::init(argc, argv, "tf_listener");
    ros::NodeHandle n;
    //创建监听者
    tf::TransformListener listener;
    ros::Rate rate(10.0);
    while (ros::ok())
    {
        geometry_msgs::PointStamped laser_point;
        laser_point.header.frame_id="base_laser";
        laser_point.header.stamp=ros::Time();
        laser_point.point.x=0.3;
        laser_point.point.y=0.0;
        laser_point.point.z=0.0;
        try{
            listener.waitForTransform("base_link","base_laser",ros::Time(0),ros::Duration(3.0));
            geometry_msgs::PointStamped base_point;
            listener.transformPoint("base_link",laser_point,base_point);
            ROS_INFO("base_laser: (%.2f, %.2f. %.2f) -----> base_link: (%.2f, %.2f, %.2f) at time %.2f",
                laser_point.point.x, laser_point.point.y, laser_point.point.z,
                base_point.point.x, base_point.point.y, base_point.point.z, base_point.header.stamp.toSec());
        }catch(tf::TransformException& ex){
            ROS_ERROR("Received an exception trying to transform a point from \"base_laser\" to \"base_link\": %s", ex.what());
        }
        rate.sleep();
    }
    
    return 0;
}

CMakeLists.txt

find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  tf
)

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

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

运行:

roscore

rosrun demo_tf tf_listener

rosrun demo_tf tf_broadcaster

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

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

相关文章

智能出行更安全,亚马逊云科技携手木卫四助汽车客户安全合规出海

木卫四&#xff08;北京&#xff09;科技有限公司在汽车网络安全领域拥有独特专业知识&#xff0c;其融合人工智能算法的安全检测引擎可以不依赖车辆中安装的代理软件&#xff0c;只需几周即可快速部署实施&#xff0c;是汽车网络安全领域的技术领先者。 在亚马逊云科技初创团…

消息中间件之ActiveMq安装

文章目录 前言安装下载地址安装 使用控制台调整配置文件 前言 2023年年中了&#xff0c;又遇到了老朋友activeMq&#xff0c;上次接触activeMq还是在15年的时候&#xff0c;系统中用到了这个消息中间件。 阔别8年之久&#xff0c;竟然又用到了这个老家伙&#xff01; 安装 要…

【6.05 代随_48day】 打家劫舍、打家劫舍 II、打家劫舍 III

打家劫舍、打家劫舍 II、打家劫舍 III 打家劫舍1.方法图解步骤代码 打家劫舍 II1.方法代码 打家劫舍 III图解步骤代码 打家劫舍 力扣连接&#xff1a;198. 打家劫舍&#xff08;中等&#xff09; 1.方法 确定dp数组&#xff08;dp table&#xff09;以及下标的含义 dp[i]&am…

如何利用 Electron 快速开发一个桌面端应用

前言 一直以来都有听说利用electron可以非常便捷的将网页应用快速打包生成为桌面级应用&#xff0c;并且可以利用 electron 提供的 API 调用原生桌面 API 一些高级功能&#xff0c;于是这次借着论证环信 Web 端 SDK 是否可以在 electron 生成的桌面端正常稳定使用&#xff0c;…

基于国产器件的KCF跟踪算法实现与验证

在国产的FT-M6678 DSP上实现KCF算法是我研究生期间的主要工作&#xff0c;KCF算法的原理与实现已经在之前的文章以及我的Gitee仓库中有部分介绍。这里主要介绍DSP与上位机通信的方式&#xff0c;以及XDMA Linux驱动的使用。具体的设计细节可以看我的毕业设计补充材料。 SRIO与…

SpringBoot 使用validator进行参数校验(实例操作+注意事项+自定义参数校验)

一、实例操作 ①、引入依赖 <dependency><groupId>org.hibernate</groupId><artifactId>hibernate-validator</artifactId><version>6.0.4.Final</version></dependency> ②、创建实体类 package com.springboot.entity;im…

蓝桥杯2022年第十三届决赛真题-出差

题目描述 A 国有 N 个城市&#xff0c;编号为 1 . . . N。小明是编号为 1 的城市中一家公司的员工&#xff0c;今天突然接到了上级通知需要去编号为 N 的城市出差。 由于疫情原因&#xff0c;很多直达的交通方式暂时关闭&#xff0c;小明无法乘坐飞机直接从城市 1 到达城市 N&a…

【教学类-10-03】20230603《空心图案3*2-单元格不重复》( 随机图案拼贴)(中班主题)

作品展示&#xff1a; 背景需求&#xff1a; 最近在做小课题结题资料&#xff0c;看到之前做过的几个学具项目&#xff0c;其中的空心图案拼贴画很不错&#xff08;中班上学期做过&#xff09;想到中6班的孩子还没有玩过&#xff0c;就想再打印一套学具&#xff08;中班下学期…

chat聊天系统消息消费时遇到的问题及优化思路(二)

1、前言 考虑下面几个条件下如何提升kafka的消费速度 消息要求严格有序&#xff0c;如chat聊天消息业务处理速度慢&#xff0c;如处理一条数据需要100ms分片不合理&#xff0c;如有的分区很闲&#xff0c;有的分区消息数量积压 2、解决方案 1、顺序问题 关于消息消费时存在…

leetcode701. 二叉搜索树中的插入操作(java)

二叉搜索树中的插入操作 leetcode701. 二叉搜索树中的插入操作题目描述 递归解题解题思路代码演示 二叉树专题 leetcode701. 二叉搜索树中的插入操作 原题链接&#xff1a; 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;https://leetcode.cn/problem…

保护您的邮件安全:Exchange Reporter Plus 助您全面监控与审计

引言&#xff1a; 在当今数字化时代&#xff0c;电子邮件已成为我们日常生活和工作中不可或缺的沟通工具。然而&#xff0c;随着电子邮件的广泛使用&#xff0c;邮件安全也成为一个备受关注的议题。为了保护组织的敏感信息和防止数据泄露&#xff0c;我们需要一种强大的解决方…

go 并发/并行/协程/sync锁读写锁

下面来介绍几个概念&#xff1a; 进程/线程&#xff1a; 进程是程序在操作系统中的一次执行过程&#xff0c;系统进行资源分配和调度的一个独立单位。线程是进程的一个执行实体&#xff0c;是 CPU 调度和分派的基本单位&#xff0c;它是比进程更小的能独立运行的基本单位。一…

APO AI一款基于GPT-4.0的AI聊天工具

APO AI APO AI是一款为用户提供AI聊天机器人功能的软件&#xff0c;用户在这里可以免费使用ChatGP3.5和ChatGPT4.0&#xff0c;这里的用户可以和AI机器人自由聊天&#xff0c;非常有趣的人工智能对话&#xff0c;并且AI还能代替你写文章、脚本、代码、文案等等。 测试GPT4.0 …

python数据可视化--matplotlib库

目录 python数据可视化--matplotlib库0、前言1、饼图2、直方图3、折线图4、散点图5、柱状图6、箱线图7、极坐标图8、步阶图9、谱图10、功率密度图11、相干谱图 python数据可视化–matplotlib库 0、前言 在进行数据分析的过程中&#xff0c;正所谓“一图胜千言”&#xff0c;一…

java并发编程:重排序与happens-before介绍

文章目录 什么是重排序&#xff1f;顺序一致性模型与JMM的保证数据竞争与顺序一致性顺序一致性模型JMM中同步程序的顺序一致性效果JMM中未同步程序的顺序一致性效果 happens-before什么是happens-before?天然的happens-before关系 什么是重排序&#xff1f; 计算机在执行程序…

代码随想录算法训练营第四十八天|198.打家劫舍|213.打家劫舍II|337.打家劫舍III

LeetCode198.打家劫舍 动态规划五部曲&#xff1a; 1&#xff0c;确定dp数组&#xff08;dp table&#xff09;以及下标的含义&#xff1a;dp[i]&#xff1a;考虑下标i&#xff08;包括i&#xff09;以内的房屋&#xff0c;最多可以偷窃的金额为dp[i]。 2&#xff0c;确定递…

【初识Spring框架】

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔&#x1f93a;&#x1f93a;&#x1f93a; 目录 1. Spring框架是什么&#xff1f; 2. IOC 容器…

[Flink] Flink On Yarn(yarn-session.sh)启动错误

在Flink上启动 yarn-session.sh时出现 The number of requested virtual cores for application master 1 exceeds the maximum number of virtual cores 0 available in the Yarn Cluster.错误。 版本说明&#xff1a; Hadoop&#xff1a; 3.3.4 Flink&#xff1a;1.17.1 问题…

锐捷AC的部署实例

进行锐捷AC部署时&#xff0c;遇到了一些问题&#xff0c;遂记录下来&#xff0c;如若大家在项目过程中遇到类似问题可以对照解决。 写在前面&#xff08;锐捷AC的基础配置&#xff09; ac-controller //配置AC的capwap源地址信息&#xff0c;国家码等…

[操作系统]1.计算机系统概述

写在前面:这篇是为了复习基础知识准备的,而不是根据学校的教材走的,所以叙述有些出入的地方请见谅,该系列旨在快速梳理操作系统的基础知识和一些常见的问题点,知识框架来自于王道操作系统,后续有机会的话会继续补充 1.操作系统的基本概念 一个计算机系统可以自上而下分成四个…