【Tello无人机】Tello飞行控制

server/2024/10/18 5:39:45/

【Tello无人机】Tello飞行控制

上一篇介绍了Tello无人机的仿真环境搭建,本篇将介绍tello无人机在pybullet环境中的飞行控制,实现无人机的速度控制。本环境最终要实现强化学习算法下的飞行任务,故采用通用的gym接口进行环境搭建。

Gym环境接口

OpenAI Gym 包含许多有趣的环境,从具有经典控制任务的环境到可让你训练智能体玩 Atari 游戏的环境。但本文是想自己定义一个tello无人机飞行的环境,同时为了兼容强化学习算法,采用gym接口进行封装。gym 对环境镜像了抽象,无论多复杂的环境,最终暴露出来的只有gym.Env抽象的5个方法,本文在gym-pybullet-drones代码的基础上进行修改:

BaseAviary类 

class BaseAviary(gym.Env):    """该类是gym.Env的子类,表明它是用于强化学习环境的基本结构。以下是对每个部分的功能说明:"""    def __init__(self,                 num_drones: int = 1,                 initial_xyzs=None,                 initial_rpys=None,                 pyb_freq: int = 240,                 ctrl_freq: int = 240,                 gui=False,                 obstacles=False,                 user_control_debug=False,                 output_folder='results'                 ):      """用于初始化环境的实例。接受多个参数,包括无人机数量(num_drones)、初始位置和姿态信息(initial_xyzs 和 initial_rpys)、PyBullet模拟的频率(pyb_freq)、控制频率(ctrl_freq)、是否使用GUI进行可视化(gui)、是否包含障碍物(obstacles)、是否启用用户控制调试模式(user_control_debug)以及结果输出文件夹路径(output_folder)。"""    def reset(self, seed: int = None, options: dict = None):        """用于重置环境的状态。可以传递种子值(seed)和其他配置选项(options)。"""    def step(self, action):        """实现了环境的一个时间步骤。接受动作作为输入,返回包含观察、奖励、终止标志和其他信息的元组。"""    def render(self, mode='human', close=False):        """用于将环境可视化。接受模式(mode)和关闭标志(close)等参数。"""    def close(self):        """用于关闭环境,释放资源。"""

 初始化函数,初始化模型信息,环境信息

 def __init__(self,                 num_drones: int = 1,                 initial_xyzs=None,                 initial_rpys=None,                 pyb_freq: int = 240,                 ctrl_freq: int = 60,                 gui=False,                 obstacles=False,                 user_control_debug=False,                 show_traj=False,                 output_folder='results'                 ):        #### Constants #############################################        self.aim_h = 0.60        self.G = 9.8        self.RAD2DEG = 180 / np.pi        self.DEG2RAD = np.pi / 180        self.CTRL_FREQ = ctrl_freq        self.PYB_FREQ = pyb_freq        if self.PYB_FREQ % self.CTRL_FREQ != 0:  # 控制频率与系统仿真频率            raise ValueError('[ERROR] in BaseAviary.__init__(), pyb_freq is not divisible by env_freq.')        self.PYB_STEPS_PER_CTRL = int(self.PYB_FREQ / self.CTRL_FREQ)        self.CTRL_TIMESTEP = 1. / self.CTRL_FREQ        self.PYB_TIMESTEP = 1. / self.PYB_FREQ        #### Parameters ############################################        self.NUM_DRONES = num_drones        #### Options ###############################################        self.GUI = gui        self.show_traj = show_traj        self.OBSTACLES = obstacles        self.user_control_debug = user_control_debug        self.URDF = "tello.urdf"        self.OUTPUT_FOLDER = output_folder        #### Load the drone properties from the .urdf file ######### 模型参数        self.M, \        self.L, \        self.THRUST2WEIGHT_RATIO, \        self.J, \        self.J_INV, \        self.KF, \        self.KM, \        self.COLLISION_H, \        self.COLLISION_R, \        self.COLLISION_Z_OFFSET, \        self.MAX_SPEED_KMH, \        self.GND_EFF_COEFF, \        self.PROP_RADIUS, \        self.DRAG_COEFF, \        self.DW_COEFF_1, \        self.DW_COEFF_2, \        self.DW_COEFF_3 = self._parseURDFParameters()        print(            "[INFO] BaseAviary.__init__() loaded parameters from the drone's .urdf:\n[INFO] m {:f}, L {:f},\n[INFO] ixx {:f}, iyy {:f}, izz {:f},\n[INFO] kf {:f}, km {:f},\n[INFO] t2w {:f}, max_speed_kmh {:f},\n[INFO] gnd_eff_coeff {:f}, prop_radius {:f},\n[INFO] drag_xy_coeff {:f}, drag_z_coeff {:f},\n[INFO] dw_coeff_1 {:f}, dw_coeff_2 {:f}, dw_coeff_3 {:f}".format(                self.M, self.L, self.J[0, 0], self.J[1, 1], self.J[2, 2], self.KF, self.KM, self.THRUST2WEIGHT_RATIO,                self.MAX_SPEED_KMH, self.GND_EFF_COEFF, self.PROP_RADIUS, self.DRAG_COEFF[0], self.DRAG_COEFF[2],                self.DW_COEFF_1, self.DW_COEFF_2, self.DW_COEFF_3))        #### Compute constants #####################################        self.GRAVITY = self.G * self.M  # 无人机重力        self.HOVER_RPM = np.sqrt(self.GRAVITY / (4 * self.KF))  # 计算悬停转速        self.MAX_RPM = np.sqrt((self.THRUST2WEIGHT_RATIO * self.GRAVITY) / (4 * self.KF))  # 计算最大转速        print("max_a:", self.MAX_RPM)        self.MAX_THRUST = (4 * self.KF * self.MAX_RPM ** 2)  # 计算最大推力        self.MAX_XY_TORQUE = (2 * self.L * self.KF * self.MAX_RPM ** 2) / np.sqrt(2)  # xy方向的最大推力        self.MAX_Z_TORQUE = (2 * self.KM * self.MAX_RPM ** 2)  # z方向的最大推力        self.GND_EFF_H_CLIP = 0.25 * self.PROP_RADIUS * np.sqrt(            (15 * self.MAX_RPM ** 2 * self.KF * self.GND_EFF_COEFF) / self.MAX_THRUST)  # 计算地面效益系数        if self.GUI:            #### With debug GUI ########################################            self.CLIENT = p.connect(p.GUI)  # p.connect(p.GUI, options="--opengl2")            for i in [p.COV_ENABLE_RGB_BUFFER_PREVIEW, p.COV_ENABLE_DEPTH_BUFFER_PREVIEW,                      p.COV_ENABLE_SEGMENTATION_MARK_PREVIEW, p.COV_ENABLE_GUI]:                p.configureDebugVisualizer(i, 0, physicsClientId=self.CLIENT)            # TODO 相机视角            p.resetDebugVisualizerCamera(cameraDistance=2,                                         cameraYaw=-0,                                         cameraPitch=-80,                                         cameraTargetPosition=[0, 0, 0],                                         physicsClientId=self.CLIENT                                         )            ret = p.getDebugVisualizerCamera(physicsClientId=self.CLIENT)            print("viewMatrix", ret[2])            print("projectionMatrix", ret[3])        else:            #### Without debug GUI #####################################            self.CLIENT = p.connect(p.DIRECT)        #### Set initial poses #####################################        if initial_xyzs is None:            self.INIT_XYZS = np.array([[1, -1, 0.2]])        elif np.array(initial_xyzs).shape == (self.NUM_DRONES, 3):            self.INIT_XYZS = initial_xyzs        else:            print("[ERROR] invalid initial_xyzs in BaseAviary.__init__(), try initial_xyzs.reshape(NUM_DRONES,3)")        if initial_rpys is None:            self.INIT_RPYS = np.zeros((self.NUM_DRONES, 3))        elif np.array(initial_rpys).shape == (self.NUM_DRONES, 3):            self.INIT_RPYS = initial_rpys        else:            print("[ERROR] invalid initial_rpys in BaseAviary.__init__(), try initial_rpys.reshape(NUM_DRONES,3)")        #### Create action and observation spaces ##################        self.quaternion_orient_zero = p.getQuaternionFromEuler([0, 0, 0])        # self.env_dim = 5.0  # 5*5m的仿真环境        self.random_pos = True        self.action_space = self._actionSpace()        self.observation_space = self._observationSpace()        self.init_env()        self._task_reset()  # 加载任务场景        self._updateAndStoreKinematicInformation()        self.action_list = deque(maxlen=5)

复位函数,将环境恢复到初始状态

    def reset(self, seed: int = None, options: dict = None):        # TODO : initialize random number generator with seed        p.resetSimulation(physicsClientId=self.CLIENT)        self._housekeeping()        self._updateAndStoreKinematicInformation()        self.end_point = [0, 0, 0]        initial_obs = self._computeObs()        initial_info = self._computeInfo()        return initial_obs, initial_info

step函数,与环境交互接口

点击【Tello无人机】Tello飞行控制 - 古月居可查看全文


http://www.ppmy.cn/server/47694.html

相关文章

Java:流程控制语句

文章目录 一、顺序结构二、分支结构2.1 if2.2 switch 三、循环结构3.1 for3.2 while3.3 do...while 四、流程控制4.1 break4.2 continue 五、结语 一、顺序结构 顺序结构语句是Java程序默认的执行流程,按照代码的先后顺序,从上到下依次执行。 二、分支结…

使用Rufus工具制作Ubuntu To Go——很详细

一、准备工作 准备工具: 1、下载Rufus(主角)软件 2、准备一个U盘或硬盘(小白128G足够,装Ubuntu系统) 3、下载Ubuntu系统镜像文件 1、下载软件Rufus 先来看一下官网介绍: Rufus 是一款格式化和创建 USB 启动盘的辅助工…

按最小体积和最小距离原则筛选4点结构

在4*4*4范围内取4个点有635376种可能,考虑旋转对称只有55个不同的结构, 这次按最小体积原则筛选结构,在结构相同的情况下只保留体积最小的, 共面 共面 共面 序号 构造 体积 距离 体积 距离 结构 z y x 数量 z y …

在mongodb5.0.11版本中创建用户和授权

目录 处理原因: 1、设定mongodb的环境变量 2、登录mongodb 3、使用admin库 4、创建 mongouser用户 5、更新 mongouser 可使用的库 6、创建 mongouser角色授权 7、更新root账号也可以使用 mongouser角色 8、重启服务 9、mongo命令 可能在高版本中无法使用&…

Spring Boot既打jar包又打war包如何做

你好,我是柳岸花开。 引言 在软件开发中,根据不同的部署需求,我们可能需要将应用打包成不同的格式。Spring Boot作为目前流行的Java应用开发框架,提供了一种简单的方式来打包应用。本文将介绍如何利用Maven Profiles在Spring Boot…

C语言数据结构排序、插入排序、希尔排序(多组并排、一组排完排另一组)、选择排序、堆排序、冒泡排序等的介绍

文章目录 前言打印数组函数一、插入排序二、希尔排序三、选择排序四、堆排序五、冒泡排序总结 前言 C语言数据结构排序、插入排序、希尔排序(多组并排、一组排完排另一组)、选择排序、堆排序、冒泡排序等的介绍 打印数组函数 打印数组函数定义 // 打印…

会计电子档案系统方案

会计电子档案系统方案是指建立一个以电子方式存储和管理会计档案的系统。该方案具体包括以下几个方面: 1. 系统架构设计:确定系统的组成以及各个组件之间的关联和交互方式。包括数据库设计、系统服务器和客户端的部署等。 2. 电子档案管理:建…