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

这篇具有很好参考价值的文章主要介绍了ROS:古月居第一次作业(话题与服务编程、动作编程、TF编程)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一.话题与服务编程

话题与服务编程:通过代码新生一只海龟,放置在(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

结果:

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

二.动作编程

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

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编程

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

ROS:古月居第一次作业(话题与服务编程、动作编程、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();//此处不能设置为ros::Time::now(),两者是不同的,可以看下面参考网址
        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})

运行:文章来源地址https://www.toymoban.com/news/detail-472150.html

roscore

rosrun demo_tf tf_listener

rosrun demo_tf tf_broadcaster

到了这里,关于ROS:古月居第一次作业(话题与服务编程、动作编程、TF编程)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • shell第一次作业

    1、判断当前磁盘剩余空间是否有20G,如果小于20G,则将报警邮件发送给管理员,每天检查次磁盘剩余空间。 2、判断web服务是否运行    1、查看进程的方式判断该程序是否运行,    2、通过查看端口的方式判断该程序是否运行,如果没有运行,则启动该服务并配置防火墙规

    2024年02月09日
    浏览(43)
  • java第一次作业(一)

    知识点: 考查java的输入格式以及for循环 java格式 注意Main与main 代码: 知识点: for循环 数组 /输入数组 /数组比大小 代码: 知识点: println与print区别:println是输完之后转行 重点: 多重for循环 代码: 知识点: 调用函数 booean函数 重点: Scanner输入 代码: 知识点: 最后又有

    2024年03月25日
    浏览(63)
  • 网络安全第一次作业

    1、什么是防火墙 防火墙是一种网络安全系统,它根据预先确定的安全规则监视和控制传入和传出的网络流量。其主要目的是阻止对计算机或网络的未经授权的访问,同时允许合法通信通过。 防火墙可以在硬件、软件或两者的组合中实现,并且可以配置为根据各种条件(如

    2024年02月07日
    浏览(48)
  • 数据库第一次作业

    1.创建一个英雄表 create table t_hero (      id int primary key auto_increment,      name varchar(10) unique not null,      gender char(5) check (gender in (\\\'男\\\',\\\'女\\\')),      grade char(5) default \\\'5星\\\',      `groups` char(5) check (`groups` in (\\\'毁灭\\\',\\\'巡猎\\\',\\\'智识\\\',\\\'存护\\\',\\\'虚无\\\',\\\'丰饶\\\')),      tel char(11)   default \\\'

    2024年01月18日
    浏览(54)
  • Python第一次作业练习

     输入:101 -成绩不及格/输入错误(超过100)​ 输入:87 -成绩良好      

    2024年02月09日
    浏览(37)
  • java第一次作业(二)

     思路: 运用expression的字符串输出 重点: expression输出 代码: 知识点: expression输出 思路: 充分运用两个for循环,一个掌控行数,一个掌控输出的数字 代码: 知识点: 输入 数字所占空格 换行 思路: 这种复杂的配凑问题,不要去想枚举去解,充分利用for循环语句 像这题

    2024年04月11日
    浏览(76)
  • web集群第一次作业

     目录 一. 简述静态网页和动态网页的区别 二. 简述 Web1.0 和 Web2.0 的区别 三. 安装tomcat8,配置服务启动脚本,部署jpress应用。 1. 首先,两者的 页面资源特征 不同: 静态网页处理文件类型有.html、.jpg、.gif、.mp4、.swf、.avi、.wmv、.flv等,而动态网页后缀常见为.asp、.aspx、.php、

    2024年02月04日
    浏览(38)
  • oop第一次博客作业

    前言 这学期刚刚接触面向对象程序设计,使用的是java语言。在此之前只接触过c语言。以我目前的学习进程来看二者的差别更多体现在面向对象的其中一个基本特性上,即封装性。在c语言中几乎所有内容都是公开的,java可以有效得规避这点。 学习的知识点 1.知道了类间关系

    2024年04月22日
    浏览(38)
  • 记第一次大作业:校园导航系统

    大二迎来了人生中的第一次大作业,因为上个学期转专业过来,学C的基础不扎实,凑巧这学期又初识了Java,可以算是我第一门系统学习的语言,本来是想用Java进行设计的,没想到我们的数据结构老师十分的坚持,一定要用C语言进行实现,那就没办法啦,就借着这个机会对

    2024年02月09日
    浏览(44)
  • 【网络应用与安全】第一次作业

    登录账号 登录个人账号,可以通过图形界面和命令两种方式。 图形界面:当前用户 logout ,切换用户,如果备选用户中没有自己的用户名,点击 not listed ,之后输入用户名和密码登录即可。 命令:使用 su your_username 方式,回车输入密码即可切换。 修改密码 操作步骤 输入

    2024年02月07日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包