ROS动作编程之控制小乌龟运动到目标位置

通过动作编程由client发布目标位置,然后控制小乌龟运动到目标位置,并实时反馈位置信息

1、TurtleMove_server.cpp文件

/*  
   此程序通过通过动作编程实现由client发布一个目标位置
   然后控制Turtle运动到目标位置的过程
 */
#include <ros/ros.h>
#include <actionlib/server/simple_action_server.h>
#include "learn_action/TurtleMoveAction.h"
#include <turtlesim/Pose.h> 
#include <turtlesim/Spawn.h>
#include <geometry_msgs/Twist.h>

typedef actionlib::SimpleActionServer<learn_action::TurtleMoveAction> Server;

struct Myturtle
{
    float x;
    float y;
    float theta;
}turtle_original_pose,turtle_target_pose;

ros::Publisher turtle_vel;

void posecallback(const turtlesim::PoseConstPtr& msg) 
{ 
  ROS_INFO("Turtle1_position:(%f,%f,%f)",msg->x,msg->y,msg->theta);
  turtle_original_pose.x=msg->x; 
  turtle_original_pose.y=msg->y;
  turtle_original_pose.theta=msg->theta;
 }

// 收到action的goal后调用该回调函数
void execute(const learn_action::TurtleMoveGoalConstPtr& goal, Server* as)
{
    learn_action::TurtleMoveFeedback feedback;

    ROS_INFO("TurtleMove is working.");
    turtle_target_pose.x=goal->turtle_target_x;
    turtle_target_pose.y=goal->turtle_target_y; 
    turtle_target_pose.theta=goal->turtle_target_theta;
    
    geometry_msgs::Twist vel_msgs;
    float break_flag;
    
    while(1)
    {  
        ros::Rate r(10);
        
        vel_msgs.angular.z = 4.0 * (atan2(turtle_target_pose.y-turtle_original_pose.y,
                                   turtle_target_pose.x-turtle_original_pose.x)-turtle_original_pose.theta);
        vel_msgs.linear.x = 0.5 * sqrt(pow(turtle_target_pose.x-turtle_original_pose.x, 2) +
                                      pow(turtle_target_pose.y-turtle_original_pose.y, 2)); 
        break_flag=sqrt(pow(turtle_target_pose.x-turtle_original_pose.x, 2) +
                                        pow(turtle_target_pose.y-turtle_original_pose.y, 2));
        turtle_vel.publish(vel_msgs);

        feedback.present_turtle_x=turtle_original_pose.x;
        feedback.present_turtle_y=turtle_original_pose.y;
        feedback.present_turtle_theta=turtle_original_pose.theta;
        as->publishFeedback(feedback);
        ROS_INFO("break_flag=%f",break_flag);
        if(break_flag<0.1) break;
        r.sleep();
    }
        // 当action完成后,向客户端返回结果
        ROS_INFO("TurtleMove is finished.");
        as->setSucceeded();
}

int main(int argc, char** argv)
{
    ros::init(argc, argv, "TurtleMove_server");
    ros::NodeHandle n,turtle_node;
    ros::Subscriber sub = turtle_node.subscribe("turtle1/pose",10,&posecallback); //订阅小乌龟的位置信息
    turtle_vel = turtle_node.advertise<geometry_msgs::Twist>("turtle1/cmd_vel",10);//发布控制小乌龟运动的速度
    // 定义一个服务器
        Server server(n, "TurtleMove", boost::bind(&execute, _1, &server), false);
        // 服务器开始运行
        server.start();
        ROS_INFO("server has started.");
    ros::spin();

    return 0;
}

2、TurtleMove_client.cpp文件

#include <actionlib/client/simple_action_client.h>
#include "learn_action/TurtleMoveAction.h"
#include <turtlesim/Pose.h> 
#include <turtlesim/Spawn.h>
#include <geometry_msgs/Twist.h>

typedef actionlib::SimpleActionClient<learn_action::TurtleMoveAction> Client;

struct Myturtle
{
    float x;
    float y;
    float theta;
}turtle_present_pose;

// 当action完成后会调用该回调函数一次
void doneCb(const actionlib::SimpleClientGoalState& state,
        const learn_action::TurtleMoveResultConstPtr& result)
{
    ROS_INFO("Yay! The TurtleMove is finished!");
    ros::shutdown();
}

// 当action激活后会调用该回调函数一次
void activeCb()
{
    ROS_INFO("Goal just went active");
}

// 收到feedback后调用该回调函数
void feedbackCb(const learn_action::TurtleMoveFeedbackConstPtr& feedback)
{
    ROS_INFO(" present_pose : %f  %f  %f", feedback->present_turtle_x,
                   feedback->present_turtle_y,feedback->present_turtle_theta);
}

int main(int argc, char** argv)
{
    ros::init(argc, argv, "TurtleMove_client");

    // 定义一个客户端
    Client client("TurtleMove", true);

    // 等待服务器端
    ROS_INFO("Waiting for action server to start.");
    client.waitForServer();
    ROS_INFO("Action server started, sending goal.");

    // 创建一个action的goal
    learn_action::TurtleMoveGoal goal;
    goal.turtle_target_x = 1;
    goal.turtle_target_y = 1;
    goal.turtle_target_theta = 0;

    // 发送action的goal给服务器端,并且设置回调函数
    client.sendGoal(goal,  &doneCb, &activeCb, &feedbackCb);

    ros::spin();

    return 0;
}

3、在功能包目录下创建action文件夹,并在此文件夹下创建TurtleMove.action文件

# Define the goal
float64 turtle_target_x  # Specify Turtle's target position
float64 turtle_target_y
float64 turtle_target_theta
---
# Define the result
float64 turtle_final_x
float64 turtle_final_y
float64 turtle_final_theta
---
# Define a feedback message
float64 present_turtle_x
float64 present_turtle_y
float64 present_turtle_theta

4、CMakeList.txt文件

cmake_minimum_required(VERSION 2.8.3)
project(learn_action)

find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  message_generation
  actionlib_msgs
  actionlib
)

## Generate actions in the 'action' folder
 add_action_files(
   FILES
   TurtleMove.action
 )

## Generate added messages and services with any dependencies listed here
 generate_messages(
   DEPENDENCIES
   std_msgs
   actionlib_msgs
 )

catkin_package(
 CATKIN_DEPENDS roscpp rospy std_msgs
  message_runtime
)

include_directories(
 include
  ${catkin_INCLUDE_DIRS}
)


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

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

5、package.xml文件

<?xml version="1.0"?>
<package format="2">
  <name>learn_action</name>
  <version>0.0.0</version>
  <description>The learn_action package</description>
  <maintainer email="patience@todo.todo">patience</maintainer>
  <license>TODO</license>

 <buildtool_depend>catkin</buildtool_depend>
  <build_depend>roscpp</build_depend>
  <build_depend>rospy</build_depend>
  <build_depend>std_msgs</build_depend>
  <build_depend>message_generation</build_depend>
  <build_depend>actionlib</build_depend>
  <build_depend>actionlib_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>
  <exec_depend>message_runtime</exec_depend>
  <exec_depend>actionlib</exec_depend>
  <exec_depend>actionlib_msgs</exec_depend> 


  <!-- The export tag contains other, unspecified, tags -->
  <export>
    <!-- Other tools can request additional information be placed here -->

  </export>
</package>

6、运行

1)运行小乌龟

rosrun turtlesim turtlesim_node

2)运行server

rosrun learn_action TurtleMove_server

3)运行client

rosrun learn_action TurtleMove_client

 

  • 4
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面我来为你编写一段ROS下C++控制小乌龟运动的节点。 我们假设你已经安装好ROS,并且已经安装了turtlebot3_simulations包。这个包提供了一个虚拟的小乌龟机器人模拟器,我们可以在其中进行运动控制。 首先,我们需要创建一个ROS包并在其中创建一个节点。在终端中输入以下命令: ``` $ mkdir -p ~/catkin_ws/src/turtlebot_control/src $ cd ~/catkin_ws/src/turtlebot_control $ catkin_init_workspace $ cd .. $ catkin_make $ source devel/setup.bash $ catkin_create_pkg turtlebot_control roscpp geometry_msgs $ cd ~/catkin_ws/src/turtlebot_control/src $ touch turtlebot_control.cpp ``` 上述命令创建了一个名为turtlebot_control的ROS包,并在其中创建了一个名为turtlebot_control.cpp的节点源文件。 接下来,在turtlebot_control.cpp中编写节点代码。以下是一个简单的示例: ``` #include <ros/ros.h> #include <geometry_msgs/Twist.h> int main(int argc, char** argv) { ros::init(argc, argv, "turtlebot_control"); ros::NodeHandle nh; ros::Publisher pub = nh.advertise<geometry_msgs::Twist>("/cmd_vel", 10); ros::Rate rate(10); while (ros::ok()) { geometry_msgs::Twist msg; msg.linear.x = 0.2; msg.angular.z = 0.5; pub.publish(msg); rate.sleep(); } return 0; } ``` 在这个示例中,我们创建了一个名为turtlebot_control的节点,并定义了一个名为/cmd_vel的话题,用于发布小乌龟控制指令。在主循环中,我们创建了一个geometry_msgs::Twist类型的消息,并设置了线速度和角速度。然后,我们使用ros::Publisher对象将消息发布到/cmd_vel话题中。 最后,我们使用ros::Rate对象控制节点的执行频率。在这个示例中,我们设置频率为10Hz。 接下来,我们需要编译并运行这个节点。在终端中输入以下命令: ``` $ cd ~/catkin_ws $ catkin_make $ source devel/setup.bash $ rosrun turtlebot_control turtlebot_control ``` 如果一切正常,你应该能够在虚拟小乌龟机器人模拟器中看到小乌龟按照设定的控制指令运动。 当然,这只是一个非常简单的示例。在实际开发中,你需要根据具体需求编写更复杂的控制逻辑。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值