#基于ROS的编队控制

前言

研究生新生,着手研究编队控制。本文为一个记录:在ROS自带的小乌龟环境下实现基于领航者的三角形编队控制。


提示:以下是本篇文章正文内容,下面案例可供参考

一、基于领航者-跟随者的编队控制方法实现

步骤1.根据领航者的位姿信息和目标队形,计算跟随平衡车的理想坐标和方位角:

在本例中方位角设定相等于领航者的方位角,理想坐标为领航者左右两侧靠后

步骤2,由跟随者当前实际位姿信息和所求理想位姿信息,计算其坐标误差和方位角误差:
相对误差模型
如图所示,在全局坐标系中 p D i = [ x D i y D i φ D i ] T p_{D i}=\left[\begin{array}{lll} x_{D i} & y_{D i} & \varphi_{D i} \end{array}\right]^{T} pDi=[xDiyDiφDi]T表示i号跟随者的期望位姿信息
p F i = [ x F i y F i φ F i ] T p_{F i}=\left[\begin{array}{lll} x_{F i} & y_{F i} & \varphi_{F i} \end{array}\right]^{T} pFi=[xFiyFiφFi]T表示i号跟随机器人的实际位姿信息;
由平面几何关系可得
x e = Δ x cos ⁡ ( φ F i ) + Δ y sin ⁡ ( φ F i ) y e = Δ y cos ⁡ ( φ F i ) − Δ x sin ⁡ ( φ F i ) φ e = φ D i − φ F i \begin{aligned} x_{e} &=\Delta x \cos \left(\varphi_{F i}\right)+\Delta y \sin \left(\varphi_{F i}\right) \\ y_{e} &=\Delta y \cos \left(\varphi_{F i}\right)-\Delta x \sin \left(\varphi_{F i}\right) \\ \varphi_{e} &=\varphi_{D i}-\varphi_{F i} \end{aligned} xeyeφe=Δxcos(φFi)+Δysin(φFi)=Δycos(φFi)Δxsin(φFi)=φDiφFi
通过设计合适的控制律使得误差为0,即可实现编队控制。
步骤3.构建运动学控制器,前人已实现 v F i = v D i cos ⁡ ( φ e ) + k 2 x e w F i = w D i + k 1 v D i y e + k 3 sin ⁡ ( φ e ) \begin{gathered} v_{F i}=v_{D i} \cos \left(\varphi_{e}\right)+k_{2} x_{e} \\ w_{F i}=w_{D i}+k_{1} v_{D i} y_{e}+k_{3} \sin \left(\varphi_{e}\right) \end{gathered} vFi=vDicos(φe)+k2xewFi=wDi+k1vDiye+k3sin(φe)

二、在小乌龟仿真环境中实现三角形编队控制

代码实现

将乌龟节点启动自带的小龟视为领航者,设定有两个跟随者,以三角形编队运动

新建两个乌龟

代码如下(示例):
python创建龟2

#! /usr/bin/env python 


import rospy
from rospy import client
from turtlesim.srv import Spawn,SpawnRequest,SpawnResponse

if __name__ == "__main__":
    rospy.init_node("newturtle_p")
    client = rospy.ServiceProxy("/spawn",Spawn)
    request = SpawnRequest()
    request.x = 4.5
    request.y = 2.0
    request.theta = 0
    request.name = "turtle2"

    client.wait_for_service()
    try:
        response = client.call(request)
        rospy.loginfo("生成成功")
    except Exception as e:
        rospy.loginfo("wrong")

C++创建龟3

#include "ros/ros.h"
#include "turtlesim/Spawn.h"

int main(int argc, char *argv[])
{   
    setlocale(LC_ALL,"");
    ros::init(argc,argv,"my_turtle");
    ros::NodeHandle nh;
    ros::ServiceClient client = nh.serviceClient<turtlesim::Spawn>("/spawn");
    turtlesim::Spawn spawn;
    spawn.request.x = 1.0;
    spawn.request.y = 1.0;
    spawn.request.theta = 0.0;
    spawn.request.name = "turtle3";

    client.waitForExistence();
    bool flag = client.call(spawn);
    if (flag)
    {
        ROS_INFO("乌龟成功,新乌龟叫%s",spawn.response.name.c_str());
    }
    else
    {
        ROS_INFO("失败!");
    }
    
    return 0;
}

配置Cmakelist

add_executable(test_01_newturtle src/test_01_newturtle.cpp)
add_dependencies(test_01_newturtle ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
target_link_libraries(test_01_newturtle
  ${catkin_LIBRARIES}
)
catkin_install_python(PROGRAMS
  scripts/test01_newtutle_p.py
  DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

由控制律计算小龟2、3速度信息并发布

只显示控制龟2,龟3同理:

#! /usr/bin/env python

import rospy
import math
from turtlesim.msg import Pose
from geometry_msgs.msg import Twist

def turtle1callback(pose):
    ideal_pose.x = pose.x
    ideal_pose.y = pose.y
    ideal_pose.theta = pose.theta
    ideal_pose.linear_velocity = pose.linear_velocity
    ideal_pose.angular_velocity = pose.angular_velocity
   
def turtle2callback(pose):
    pub = rospy.Publisher("/turtle2/cmd_vel",Twist,queue_size=1)
    error_pose.x = (ideal_pose.x-pose.x)*math.cos(pose.theta) + (ideal_pose.y-pose.y)*math.sin(pose.theta) - 1
    error_pose.y = (ideal_pose.y-pose.y)*math.cos(pose.theta) - (ideal_pose.x-pose.x)*math.sin(pose.theta) - 1
    error_pose.theta = math.degrees(ideal_pose.theta) - math.degrees(pose.theta)
    error_pose.theta = math.radians(error_pose.theta)
    error_pose.linear_velocity = ideal_pose.linear_velocity
    error_pose.angular_velocity = ideal_pose.angular_velocity    error_pose.linear_velocity*math.cos(error_pose.theta)+1*error_pose.x
    twist.linear.x = 2*math.cos(error_pose.theta)+ 4 * error_pose.x
    twist.angular.z = 1 * ideal_pose.linear_velocity * error_pose.y + 1* error_pose.linear_velocity * math.sin(error_pose.theta)

    if(abs(twist.linear.x)>4):
       twist.linear.x = 4
    pub.publish(twist)

if __name__ == "__main__":
    rospy.init_node("ss")
    ideal_pose = Pose()
    error_pose = Pose()
    sub1 = rospy.Subscriber("/turtle1/pose",Pose,turtle1callback,queue_size=10)
    sub2 = rospy.Subscriber("/turtle2/pose",Pose,turtle2callback,queue_size=10)
    rospy.spin()

代码编译通过后,启动小乌龟节点以及以上节点,再给领航龟发布速度信息或使用键盘控制节点。

结果展示

ROS小龟编队控制


总结

迈出了第一步,本文主要特点在于系统是闭环。
在小乌龟界面实现后,会在gazebo环境下的小车仿真实现。
一起进步吧

  • 19
    点赞
  • 111
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值