【rotors】多旋翼无人机仿真(四)——参数补偿和PID控制

2023-05-16

【rotors】多旋翼无人机仿真(一)——搭建rotors仿真环境
【rotors】多旋翼无人机仿真(二)——设置飞行轨迹
【rotors】多旋翼无人机仿真(三)——SE3控制
【rotors】多旋翼无人机仿真(四)——参数补偿和PID控制
【rotors】多旋翼无人机仿真(五)——多无人机仿真

本贴内容参考两位博主的内容:
月照银海似蛟
Reed Liao

1、前言

在上一节中,我们讲解了SE3算法和rotor的算法实现,本节中我们讲一讲rotor的参数补偿 和pid控制

2、绘制算法的收敛过程

通过se3控制,当我们指定目标点(x y z yaw)后无人机就会收敛至设定目标点,但是我们还关心收敛速度,这是评价一个控制算法的重要指标,为了直观算法的收敛过程,我们用python的matplotlib库绘制算法的收敛过程曲线

(1)设置目标点

修改hovering_example节点程序,将目标点设置为(1 1 1 0),当然不修改也行,但修改了可以更直观对比xyz的收敛速度

// hovering_example.cpp
// 期望位置和偏航角
Eigen::Vector3d desired_position(1.0, 1.0, 1.0);
double desired_yaw = 0.0;

(2)编写绘制曲线程序

首先说一下绘制曲线的一个编程思路,当我们运行rotor时仿真时(如运行mav_hovering_example.launch),会有XXX/command/trajectoryXXX/odometry_sensor1/odometry的ros话题发布无人机的目标点和当前无人机位姿信息,那么我们只需要用python的rospy订阅这两个话题,保存一段时间的话题信息,最后用matplotlib库绘制相应曲线即可。
~/UAV_rotors/src/rotors_simulator/rotors_gazebo/scripts文件夹下创建draw_curve.py,其内容为:

#! /home/用户名/anaconda3/envs/虚拟环境名字/bin/python
"""
绘制无人机的曲线误差
"""

import rospy
import time
import numpy as np
import matplotlib.pyplot as plt
from trajectory_msgs.msg import MultiDOFJointTrajectory
from nav_msgs.msg import Odometry

plt.rcParams['font.sans-serif'] = ['SimHei']    #指定字体为SimHei
plt.rcParams['axes.unicode_minus'] = False      #让-号显示正常

def trajectory_callback(msg):
    # trajectory回调函数
    global begin_time,desire_x,desire_y,desire_z
    if not begin_time:
        begin_time = msg.header.stamp.to_sec()
    desire_x = msg.points[0].transforms[0].translation.x
    desire_y = msg.points[0].transforms[0].translation.y
    desire_z = msg.points[0].transforms[0].translation.z

def odometry_callback(msg):
    # odometry回调函数
    global begin_time,time_list,x,y,z,desire_x,desire_y,desire_z
    if  begin_time:
        time_list.append(msg.header.stamp.to_sec() - begin_time)
        x['actual'].append(msg.pose.pose.position.x)
        y['actual'].append(msg.pose.pose.position.y)
        z['actual'].append(msg.pose.pose.position.z)
        x['desire'].append(desire_x)
        y['desire'].append(desire_y)
        z['desire'].append(desire_z)

def draw_curve():
    # 绘制曲线
    global time_list,x,y,z,trajectory_sub,odometry_sub,fig, axes
    print('draw curve...')
    # 取消订阅话题
    trajectory_sub.unregister()
    odometry_sub.unregister()
    # 绘制曲线
    fig, axes = plt.subplots(3, 1, figsize=(10, 15))
    axes[0].plot(time_list,x['desire'],'r',time_list,x['actual'],'b')
    axes[0].grid(True)
    axes[0].legend(['期望曲线','实际曲线'])
    axes[0].set_title('X')

    axes[1].plot(time_list, y['desire'], 'r', time_list, y['actual'], 'b')
    axes[1].grid(True)
    axes[1].legend(['期望曲线', '实际曲线'])
    axes[1].set_title('Y')

    axes[2].plot(time_list, z['desire'], 'r', time_list, z['actual'], 'b')
    axes[2].grid(True)
    axes[2].legend(['期望曲线', '实际曲线'])
    axes[2].set_title('Z')

    plt.show()



begin_time = None
time_list = []
draw_duration = 10 # 绘制时长,单位s
desire_x = 0
desire_y = 0
desire_z = 0
x = {'desire':[],'actual':[]}
y = {'desire':[],'actual':[]}
z = {'desire':[],'actual':[]}
trajectory_topic = "/firefly/command/trajectory"    # 轨迹topic名称
odometry_topic = "/firefly/odometry_sensor1/odometry"   # odometry topic 名称
rospy.init_node("draw_curve_node")
trajectory_sub = rospy.Subscriber(trajectory_topic,
                                  MultiDOFJointTrajectory,
                                  trajectory_callback,queue_size=10)
odometry_sub = rospy.Subscriber(odometry_topic,
                                  Odometry,
                                  odometry_callback, queue_size=10)
print('等待服务端发送轨迹指令...')
while(not begin_time):  # 等待接受到数据
    pass
print('正在接受数据...')
time.sleep(draw_duration)
draw_curve()

说明一下,第一行指定了要用的python解释器,由于ROS melodic的python是2.7版本的,许多库不能正常运行,因此这里我使用conda创建的python3.7环境的解释器运行该py文件,这里就修改为自己的python解释器位置即可;其次我绘制曲线时有中文,但是Ubuntu默认没有该字体,需要自己下载安装,安装方法见这里;最后,程序需要自己修改trajectory_topic和odometry_topic,我运行的无人机型号是firefly,如果是其他型号就自行修改topic name

(3)运行程序 绘制曲线

# 终端1
roscore
# 终端2
cd ~/UAV_rotors/src/rotors_simulator/rotors_gazebo/scripts
chmod 777 draw_curve.py
./draw_curve.py
# 终端3
roslaunch rotors_gazebo mav_hovering_example.launch

无人机起飞后,程序会记录10s的数据并绘制为曲线:

image-20230126175744266

3、参数补偿

如果你运行mav_hovering_example_with_vi_sensor.launch或者修改无人机型号为其他型号时,重新绘制收敛曲线,你大概会发现结果存在着较大的静差,就像下面这样:

image-20230126180056157

原因在于无人机的控制节点lee_position_controller_node并没有根据无人机型号的不同而自适应修改无人机的参数如质量,lee_position_controller_node里面的无人机参数是无深度摄像头的firefly型号飞机参数,当你无人机上加载深度摄像头或者其他型号无人机时,无人机的质量等参数就改变了,自然控制就不对了,存在着静差。当然想消除静差你可以修改无人机参数,但这样比较麻烦,得自己去看无人机建模文件,下面讲一种简单有效的参数补偿方法:

(1)打印无人机当前的期望加速度和角加速度

修改~/UAV_rotors/src/rotors_simulator/rotors_control/src/library/lee_position_controller.cpp,打印无人机当前的期望加速度和角加速度:

Eigen::Vector3d angular_acceleration;
ComputeDesiredAngularAcc(acceleration, &angular_acceleration);
std::cout << "angular_acceleration = "<<angular_acceleration.transpose() << std::endl;

double thrust = -vehicle_parameters_.mass_ * acceleration.dot(odometry_.orientation.toRotationMatrix().col(2));
std::cout << "thrust = "<<thrust << std::endl;

期望加速度和角加速度是控制的关键,我们只要补偿使这两个变量正确即可

(2)运行程序,查看无人机悬停时的angular_acceleration和thrust

roslaunch rotors_gazebo mav_hovering_example_with_vi_sensor.launch

当无人机稳定悬停时,查看终端打印结果

image-20230126181049383

可以看到稳定悬停时的升力thrust =16.5626,而角加速度angular_acceleration[1] = -3.14854

分析一下,正常情况下,无人机处于悬停时,升力应该是等于重力的,角加速度应该是全0向量,而这里升力并不等于重力, 角加速度有一项不为0,我们只需对这两部分补偿即可

(3)补偿参数

修改~/UAV_rotors/src/rotors_simulator/rotors_control/src/library/lee_position_controller.cpp,补偿参数:

Eigen::Vector3d angular_acceleration;
ComputeDesiredAngularAcc(acceleration, &angular_acceleration);
angular_acceleration[1] -= 3.14854; //angular_acceleration补偿

double thrust = -vehicle_parameters_.mass_ * acceleration.dot(odometry_.orientation.toRotationMatrix().col(2));
double k = 16.5626 / (vehicle_parameters_.mass_ * vehicle_parameters_.gravity_);
thrust = k * thrust; //thrust补偿

(4)重新编译

cd ~/UAV_rotors
catkin build

(5)重新运行绘制曲线

# 终端1
roscore
# 终端2
cd ~/UAV_rotors/src/rotors_simulator/rotors_gazebo/scripts
chmod 777 draw_curve.py
./draw_curve.py
# 终端3
roslaunch rotors_gazebo mav_hovering_example_with_vi_sensor.launch

从结果来看,静差被成功补偿掉了

image-20230126181842336

4、PID控制

补偿掉静差后,我们观察一下收敛速度,从(0 0 0)到(1 1 1)需要5s的时间,感觉还是太久了,我们加入PID加快收敛速度:

(1)修改程序

修改~/UAV_rotors/src/rotors_simulator/rotors_control/include/rotors_control/lee_position_controller.h,加入PID控制函数声明:

class LeePositionController {
 public:
  LeePositionController();
  ~LeePositionController();
  void InitializeParameters();
  void CalculateRotorVelocities(Eigen::VectorXd* rotor_velocities) const;

  void SetOdometry(const EigenOdometry& odometry);
  void SetTrajectoryPoint(
    const mav_msgs::EigenTrajectoryPoint& command_trajectory);

  LeePositionControllerParameters controller_parameters_;
  VehicleParameters vehicle_parameters_;

  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
 private:
  bool initialized_params_;
  bool controller_active_;

  Eigen::Vector3d normalized_attitude_gain_;
  Eigen::Vector3d normalized_angular_rate_gain_;
  Eigen::MatrixX4d angular_acc_to_rotor_velocities_;

  mav_msgs::EigenTrajectoryPoint command_trajectory_;
  EigenOdometry odometry_;

  void ComputeDesiredAngularAcc(const Eigen::Vector3d& acceleration,
                                Eigen::Vector3d* angular_acceleration) const;
  void ComputeDesiredAcceleration(Eigen::Vector3d* acceleration) const;
  Eigen::Vector3d position_error_pid(Eigen::Vector3d position_error) const; // 函数声明
};

修改~/UAV_rotors/src/rotors_simulator/rotors_control/src/library/lee_position_controller.cpp,定义pid函数:

Eigen::Vector3d LeePositionController::position_error_pid(Eigen::Vector3d position_error) const
{
  // position_error的PID控制
  Eigen::Vector3d Kp(7, 7, 7) , Ki(0, 0, 0),Kd(2.5,2.5,2.5); 
  Eigen::Vector3d max_output_pid(10,10,10) , min_output_pid(-10,-10,-10);
  Eigen::Vector3d max_output_i(5,5,5),min_output_i(-5,-5,-5);
  static Eigen::Vector3d error(0,0,0),error_last(0,0,0),error_last_last(0,0,0);
  static Eigen::Vector3d output_p(0,0,0),output_i(0,0,0),output_d(0,0,0),output_pid(0,0,0); 

  // 偏差计算
  error = position_error ;
  output_p +=  Kp.cwiseProduct(error - error_last) ;
  output_i +=  Ki.cwiseProduct(error) ;
  output_d +=  Kd.cwiseProduct(error - 2*error_last + error_last_last) ;
  // 更新偏差量
  error_last_last = error_last ;
  error_last = error ;

  output_i.cwiseMin(max_output_i);
  output_i.cwiseMax(min_output_i);
  

  // 汇总输出
  output_pid = output_p + output_i + output_d;

  output_pid.cwiseMin(max_output_pid);
  output_pid.cwiseMax(min_output_pid);
  // 控制器最终输出
  return output_pid; 
}

有许多地方可以加入PID,这里我们将位置误差的比例控制改为PID控制:

image-20230126182537603

 *acceleration = (position_error_pid(position_error)   // PID控制
      + velocity_error.cwiseProduct(controller_parameters_.velocity_gain_)) / vehicle_parameters_.mass_
      - vehicle_parameters_.gravity_ * e_3 - command_trajectory_.acceleration_W;

(2)重新编译

cd ~/UAV_rotors
catkin build

(3)重新运行绘制曲线

# 终端1
roscore
# 终端2
cd ~/UAV_rotors/src/rotors_simulator/rotors_gazebo/scripts
chmod 777 draw_curve.py
./draw_curve.py
# 终端3
roslaunch rotors_gazebo mav_hovering_example_with_vi_sensor.launch

image-20230126182807691

加入PID后收敛速度大概3s,继续调整pid参数或者在其他地方加入pid可以进一步提高收敛速度,说一下我pid调参方法,因为仿真中还不存在干扰,因此曲线不存在静差,因而不需要积分部分,先调整比例到曲线有超调,然后适当加入微分将超调减小。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【rotors】多旋翼无人机仿真(四)——参数补偿和PID控制 的相关文章

  • 配置虚拟机

    方式一 xff1a 用AS自带的虚拟机 此时把system images放在sdk目录内 但是注意 xff0c amd平台不支持intel虚拟化 xff0c 所以不能用 方式二 xff1a 使用genymotion插件 任何平台都推荐使用G
  • Genymotion虚拟软件的配置

    一 genymotion软件本身 xff08 1 xff09 点击安装 xff08 2 xff09 登录账户 xff08 3 xff09 设置关联virtualbox的安装路径 xff08 4 xff09 在ADB下选择使用genymoti
  • Vim编辑器配置

    推荐使用space Vim GitHub xff1a https github com SpaceVim SpaceVim 官网 xff1a https spacevim org cn 安装教程 xff1a https github com
  • 修改win10 cmd和shell的编码方式

    936对应GBK 65001对应utf 8 power shell 可以用Powershell的配置文件 xff08 PROFILE xff09 来实现 PROFILE默认文件不存在 xff0c 需要创建 New Item PROFILE
  • wsl2的hyper-v的开启与关闭

    大家都知道 xff0c win10在开启自家虚拟机的时候 xff0c VM和virtualbox就用不了了 xff01 开启hyper v xff1a xff08 1 xff09 打开控制面板 xff08 2 xff09 选择程序 xff0
  • virtualbox和vmware最新版已经支持win10的hyper了

    vmware支持hyper的版本 xff1a https blogs vmware com workstation 2020 01 vmware workstation tech preview 20h1 html virtualbox支持
  • Java读取已打包好的Jar包中的文件

    一般我们是通过下面这种代码获取文件在项目中的的绝对路径 Xxx class getResource 34 META INF xxx yaml 34 但是当模块打包成jar后 xff0c 我们获取到的路径可能会是下面这种 xff0c 这种并不
  • linux更换镜像的一般步骤

    xff08 1 xff09 根据使用的操作系统 xff0c 到清华镜像站上找到该系统的镜像源的连接 xff08 2 xff09 操作步骤 对系统给的镜像源进行备份 xff0c 以防出问题 sudo cp etc apt sources li
  • UEFI模式下Win10和Ubuntu18.04双系统安装总结

    现在都2020年了 市面上根本就买不到传统模式开机的笔记本了 所以我以我的经验总结一下uefi主板如何安装win10和Ubuntu操作系统 其他Linux也是同理 这篇教程是在安装了win10的基础上再安装的Linux 若不符合你的情况 请
  • gun-grub引导选择页面的美化

    不出意外地 xff0c 安装好Ubuntu和Windows的双系统后应该是由Ubuntu的grub引导启动的 也就是那个及其丑陋的页面 逃 优化设置 grub引导的设置文件是 etc default grub xff0c 对其进行修改可以得
  • 双系统完整卸载Ubuntu+Windows磁盘分区安全删除Ubuntu的EFI分区和其他分区

    就参考这篇文章吧 https blog csdn net wq6ylg08 article details 103223620 大致上分为三个步骤 一 把开机引导给删除 可以使用easyUEFI或者BOOTICE 删除你准备卸载的系统的引导
  • legacy传统模式启动下的win10和Ubuntu18.04双系统安装

    前提是你的电脑支持传统模式开机 比如现在的一些笔记本已经不支持传统模式了 强行会找不到引导 和这篇文章大致相同 注意以下不同点 1 在为linux分区的时候 legacy模式下的启动引导分区需要这样设置 空闲 处 xff0c 继续点 43
  • 使用rEFInd来引导多个操作系统

    以下讲解仅适用于EFI的启动模式 且注意一定要关闭secure boot 在同一个电脑上安装了N个操作系统 在开机时 引导肯定会非常的混乱 一种方式是可以使用windows boot manager来选择要启动的操作系统 但是缺点是每次开机
  • rEFInd去掉不必要的启动项

    refind是uefi环境下使用的引导器 如果一台设备上有N个系统 xff0c 那么有必要了解一下refind如 何来引导 但因为默认的引导效果是非常杂乱的 xff0c 我们需要做一些工作 一 安装refind 参考这篇文章 https b
  • pacman的常用命令

    S 指令 安装 sudo pacman S 安装软件 sudo pacman Sy 获取最新打软件情况 xff0c 如果已经是最新了 xff0c 直接会提示已经更新到最新了 sudo pacman Syy 强行更新你的应用的软件库 xff0
  • pacman的包管理命令

    S 指令 安装 sudo pacman S 安装软件 sudo pacman Sy 获取软件源的最新情况 xff0c 如果已经是最新了 xff0c 会提示已经更新到最新了 sudo pacman Syy 重新同步应用的软件源 sudo pa
  • vscode的不同设置的区别

    转载链接 https www jb51 net article 186000 htm
  • Unable to register with master node [http://localhost:11311/]: master may not be running yet.

    树莓派和PC端都安装了ROS xff0c 然后将树莓派ROS当主机运行roscore xff0c 为了让两台机子的ROS可以通讯 xff0c 需要在PC端的 bashrc文件中配置如下环境变量 xff1a PC端 bashrc文件 expo
  • 新手安装arch安装界面wifi-menu连接不了wifi

    新手安装arch安装界面wifi menu连接不了wifi 在物理机上安装arch 但是遇到了一个很无语的地方 因为安装arch是要联网下载基础包的 所以在安装过程中要进行联网 我是连接的wifi 在安装命令行里执行 wifi menu 可
  • 安装arch的网络连接问题(新手易犯)

    估计有很多像我这样的 第一次安装arch 被网络的连接问题搞得欲仙欲死 这篇文章就总结一下我遇到的问题 只适用于wifi无线连接 有线的绕开 刚开始安装 进入到live系统 你会发现 哎 可以使用wifi menu iw 等这些命令 但是a

随机推荐

  • Arch设置开机自动连接wifi网络:

    Arch设置开机自动连接wifi网络 i3wm netctl是arch的源生项目 xff0c 集成于base包 netctl基于命令行 xff0c 你可以安装其他的图形网络管理工具 从 etc netctl examples 拷贝 wire
  • 现在最新版的vmware已经和win10hyper-v兼容

    新增功能 此 VMware Workstation Pro 发行版本是面向所有 VMware Workstation 15 Pro 用户的免费升级 其中包含以下更新 xff1a 支持 Windows 10 主机 VBS xff1a 现在 x
  • Linux下如何设置交换文件?

    一 创建指定大小的文件 我们需要用到dd命令来创建一个指定大小的空文件 xff0c 比如是1G xff0c 执行命令 dd if 61 dev zero of 61 swap bs 61 1024 count 61 1048576 上面命令
  • 虚拟机vmware安装arch在桥接模式下没有eth0网卡,只有ens33,提示no such device

    参考大牛的一篇博客 道理都是一样的 CentOS7系统安装完毕之后 xff0c 输入ifconfig命令发现没有eth0 不符合我们的习惯 而且也无法远程ssh连接 xff0c 这个问题解决起来还算简单 xff1a 一 xff0c 永久搞定
  • vim或gvim的配置(推荐)

    本文简述如何跟换gVim的字体和选择喜欢的配色方案 xff1a 1 下载配色方案 xff1a gVim官网提供了很多配色方案 xff0c 可以根据自己的需要来选择下载 xff0c 本人比较喜欢深色背景系列的 xff0c 所以以下列举一些 x
  • vim的光标设置

    光标显示选项 可以通过以下命令设置guicursor选项 xff0c 来定义图形界面下的光标显示 xff1a set guicursor 61 mode style highlight mode style highlight 其中 xff
  • 如何修改WSL的安装路径

    一 还没有安装wsl实例 自定义wsl安装位置 下载wsl的appx镜像https docs microsoft com zh cn windows wsl install manual xff0c 比如下载的Ubuntu 18 04 将下
  • WSL安装Arch

    WSL安装Archlinux子系统 再次感谢助人为乐的朋友 xff1a https github com yuk7 ArchWSL 下载releases的zip包 并解压到一个有写权限的地方 xff0c 在右键管理员权限运行Arch exe
  • 【rotors】多旋翼无人机仿真(一)——搭建rotors仿真环境

    rotors 多旋翼无人机仿真 xff08 一 xff09 搭建rotors仿真环境 rotors 多旋翼无人机仿真 xff08 二 xff09 设置飞行轨迹 rotors 多旋翼无人机仿真 xff08 三 xff09 SE3控制 roto
  • 黑苹果热补丁hotpatch来禁用笔记本独显

    写在前面 最近我根据 RehabMan 的 hotpatch 添加了一些路径做了一个屏蔽独显得 hotpatch 来屏蔽独显解决一些升级 10 13 后因为 nv disable 参数失效而卡在 Window Server Service
  • _OFF方法包含EC依赖的情况,笔记本禁用独显的方法(通过修改DSDT和SSDT)

    概述 这个教程的目的 xff0c 是向大家展示 xff0c 怎样通过修改DSDT和SSDT xff0c 来屏蔽双显卡笔记本的独立显卡 xff08 例如 xff1a Intel集成显卡 xff0b 英伟达独立显卡 Optimus技术 xff0
  • 如何通过配置文件修改powershell for .net firmwork的启动路径

    一 在用户所在的文档目录中创建一个名为 WindowsPowerShell 的目录 例如 xff1a C Users silence Documents WindowsPowerShell 二 在WindowsPowerShell的目录下创
  • vim中查看和修改文件编码格式

    vim 中查询和转换文件编码格式 set fileencoding 查看现在文本的编码 set fenc 61 编码 转换当前文本的编码为指定的编码 set enc 61 编码 以指定的编码显示文本 xff0c 但不保存到文件中 这里的 编
  • win10使用cmd合并两个文件

    先在目标目录下打开cmd 输入 copy b 文件名1 后缀1 43 文件名2 后缀2 目标文件名 目标后缀 回车完成
  • 黑苹果intel网卡驱动

    方法1 链接 https pan baidu com s 192A1NAB0mkkSA151KkxAYA 密码 d4gj 备用 xff1a https pan baidu com s 1p7LxLxwlRFhnvIjzCbx49w 提取码
  • 分享最新版的 INTELWIFI 驱动包

    转载 http bbs pcbeta com forum php mod 61 viewthread amp tid 61 1856465 amp extra 61 page 3D1 26filter 3Dtypeid 26typeid 3
  • intel网卡驱动方法1的安装说明书

    Z大github https github com zxystd itlwm 说明书 1 解压itlwm 43 客户端 将heliport 拖进应用程序 安装 2 若为clover引导 把itlwm kext拖进EFI Clever Kex
  • 绝地求生键位魔改v3.0

    因为fps类游戏的默认按键和LOL有很大差别 从舒服度和操作灵活性上说 LOL应该是更胜一筹 今天我就强行改下键位布局 当然这不是最终版 女士们和先生们欢迎讨论 绝地求生魔改键位 未提到的保持默认设置 各位同学根据需要修改 图像 显示模式
  • 绝地求生魔改键位v4.0

    绝地求生魔改键位v4 0 未提到的保持默认设置 各位同学根据需要修改 图像 显示模式 窗口化 分辨率 1920 1080 抗锯齿 超高 后期处理 超高 材质 超高 其他的都保持为 低 鲜明度 禁用 垂直同步 禁用 运动模糊 禁用 声音 音乐
  • 【rotors】多旋翼无人机仿真(四)——参数补偿和PID控制

    rotors 多旋翼无人机仿真 xff08 一 xff09 搭建rotors仿真环境 rotors 多旋翼无人机仿真 xff08 二 xff09 设置飞行轨迹 rotors 多旋翼无人机仿真 xff08 三 xff09 SE3控制 roto