当前位置: 首页 > news >正文

机器人制作开源方案 | 森林管理员

​作者:李佳骏、常睿康、张智斌、李世斌、高华耸

单位:山西能源学院

指导老师:赵浩成、郜敏

1. 研究背景

      森林作为地球上可再生自然资源及陆地生态的主体,在人类生存和发展的历史中起着不可代替的作用,它不仅能提供国家建设和人民生活所需的木材及林副产品,而且还肩负着释放氧气调节气候环境,涵养水源、保持水土、防风固沙、美化环境、净化空气、减少噪音及旅游保健等多种使命,同时森林还是农牧业稳产高产的重要条件。然而,森林火灾是森林最危险的敌人,也是林业最可怕的灾害,也会给森林带来最有害、具有毁灭性的后果。森林火灾不只是烧毀片片森林,伤害林内动物,而旦还降低森林的更新能力,引起土壤的贫瘠和破坏森林涵养水源的作用,甚至号致生态环境失去平衡。2019年3月30日,四川省凉山州木里县就曾经发生过一次非常严重的森林火灾。2019年3月30日是一个雨天,木里县喇嘛寺沟附近下午5点左右出现了雷雨天气,虽然只是一次持续了30秒左右的阵雨,但是隆隆雷声却一直回荡在天空,不绝于耳。下午6点时一场森林火灾在山上悄然而至,起火点位于海拔3800余米的山上,山中地形复杂,遍布沟壑,无论是交通还是通讯情况都非常不好,消防官兵难以迅速赶往现场进行救援。经过相关部门得知消息后初步判断本次火灾的原因,可能是由于之前降兩时的雷击导致,多个起火点都位于山崖上,火场平均海拔高达4千米。31日下午,689位救火人员带着各种设备登山,前往海拔4000余米的原始森林开展救火工作,由于当日风向不定,风力风向突变导致山火爆燃形成一个巨大的火球。救火人员兵分两路进行避险,其中一路安全撤离,另一路的27位森林消防指战员和三名地方救火人员就此和其他人失去了联系。4月2日早晨六点30分,田火山山上的明火终于被扑灭。而制作山林隔离带是有效制止森林大火蔓延的的有效方式,且该方面大多是通过人工下地来完成的,所以我们设计了一款可通过远程遥控来实现砍伐、运输一体化的全地形机器人,减少人工的需求量和危险性。同时,目前生活中的伐木大多由人工实地操作,我们的作品也可以代替其完成系统化的作业。

2. 主要功能

      本小组作品的主要功能有在大火发生时,及时进入火场中,对还未涉及到的地域进行砍伐树木,降低火灾面积。本小车为全地形小车,可以适应森林中的各种地形,如山坡、地坑等等。小车一侧设有抓夹,在另一侧砍伐完树木后抓夹可以及时将树枝抓起放到车后部,最终由小车将其带出森林。在救援的同时小车前部设有摄像头以及湿度传感器,实时监控并记录火灾情况。本作品不仅可以用作在森林防护中制作隔离带的一体化工作,也可以用作日常生活中做伐木一体机器人使用。

3. 场景调研

      森林火灾的起因主要有两大类:人为火和自然火。人为火包括:生产性火源(农、林、牧业生产用火,林副业生产用火,工矿运输生产用火等)、非生产性火源(野外吸烟、做饭、烧纸、取暖等)、故意纵火。自然火包括:雷电火、自燃等。由于我国的森林火灾中,由吸烟、烧荒和上坟烧纸引起的火灾占了绝大多数,所以我们小组场地模拟森林火灾的起因为烧荒。在实际的地形中会存在山坡和小断层,我们小组在模拟时,模拟机器人爬小山坡和爬小台阶(断层)。同时,模拟了砍伐树木的过程,再砍伐完后,车另一侧的抓夹会将树木夹起搬运出森林。在进行就救援以及砍伐树木时,车前的摄像头可进行实时监控,可记录下在砍伐树木时周遭的实时动态,同时还有湿度传感器的实时监测。

4. 机器人本体技术路线说明

      ① 机械结构:整体车身分为两部分,前端车体运用柔性结构,并采用履带式车轮,后部采用传统轮胎,有着很好的抓地力。车体大致结合军用坦克的履带的优越性并结合实际,改装了后置轮胎,使得前后轮可以通过配合,从而顺利翻越一些工作途中所遇到的障碍。

      ② 驱动系统:该车加装了6个双直流电机共同驱动,六个电机同时驱动,为小车提供了足够的动力,减少了动力的损失,为通过障碍物提供了足够的动力条件,电锯有单舵机制作的机械臂和电机控制的电锯体实现横向自由伸展,砍伐树木。机械爪由两个舵机控制的机械臂和单舵机控制的爪体构成,可实现横向伸展并调整爪子的摆动,实现抓取。

      ③ 控制系统:主板采用了Basra主控板,通过ESP8266Wi-Fi模块与电脑连接实现远程实时无限操作,通过摄像头、温湿度传感器来实时反馈现场情况,为人们的勘测和救援提供信息帮助。

      ④ 感知系统:车体全程操作由人工在远程通过WiFi模块实时操作,在车体的前方和中段均装有摄像头,前部摄像头可帮我我们锁定目标树木的方向,也可以规避障碍物,在侧端的摄像头可对目标数目进行定位,当其进入合适位置后进行砍伐和搬运。在车的顶部同时也装配了温湿度传感器,对周围环境进行监控,并及时反馈,为人工救援行动提供保障。

5. 示例程序

#include <Servo.h>int _ABVAR_1_data = 0 ;int in1 = 5;int in2 = 6;int in3 = 9;int in4 = 10;int in5 = 12;int SERVO_SPEED=20;                                        //定义舵机转动快慢的时间int ACTION_DELAY=200;                                      //定义所有舵机每个状态时间间隔Servo myServo[4];int f = 50;                                                     //定义舵机每个状态间转动的次数,以此来确定每个舵机每次转动的角度int servo_port[4] = {3,4,7,8};                            //定义舵机引脚int servo_num = sizeof(servo_port) / sizeof(servo_port[0]);     //定义舵机数量float value_init[4] = {10, 40, 20, 40};                //定义舵机初始角度//10, 110, 20, 40chu    100, 110, 60, 30   kaishi     100, 40, 60, 30zhua     100, 40, 40, 30qi    10, 40, 60, 30weizhi   //float value_init[6] = {10, 130, 60, 30};                //定义舵机初始角度//float value_init[6] = {0, 40, 40, 40};void setup(){Serial.begin(9600);pinMode(in1, OUTPUT);pinMode(in2, OUTPUT);pinMode(in3, OUTPUT);pinMode(in4, OUTPUT);pinMode(in5, OUTPUT);for(int i=0;i<servo_num;i++){ServoGo(i,value_init[i]);}}void ServoStart(int which){if(!myServo[which].attached())myServo[which].attach(servo_port[which]);pinMode(servo_port[which], OUTPUT);}void ServoStop(int which){myServo[which].detach();digitalWrite(servo_port[which],LOW);}void ServoGo(int which , int where){if(where!=200){if(where==201) ServoStop(which);else{ServoStart(which);myServo[which].write(where);}}}void servo_move(float value0, float value1, float value2, float value3){float value_arguments[] = {value0, value1, value2, value3};float value_delta[servo_num];for(int i=0;i<servo_num;i++){value_delta[i] = (value_arguments[i] - value_init[i]) / f;}for(int i=0;i<f;i++){for(int k=0;k<servo_num;k++){value_init[k] = value_delta[k] == 0 ? value_arguments[k] : value_init[k] + value_delta[k];/**************************串口查看输出*****************************///      Serial.print(value_init[k]);//      Serial.print(" ");}//    Serial.println();/**************************串口查看输出*****************************/for(int j=0;j<servo_num;j++){ServoGo(j,value_init[j]);}delay(SERVO_SPEED);}delay(ACTION_DELAY);}void loop(){/*   servo_move(10, 40, 20, 40);delay(500);servo_move(100, 20, 20, 40);delay(500);servo_move(100, 110, 20, 40);delay(500);servo_move(100, 110, 60, 40);delay(500);   servo_move(100, 40, 60, 40);delay(500);servo_move(10, 40, 60, 40);delay(500);servo_move(10, 40, 20, 40);*/_ABVAR_1_data = Serial.read() ;if (( ( _ABVAR_1_data ) == ( 1 ) )){analogWrite(in1, 0);                         analogWrite(in2, 0);analogWrite(in3, 0);analogWrite(in4, 160);delay (10);}if (( ( _ABVAR_1_data ) == ( 2 ) )){for(int i=0;i<10;i++){analogWrite(in1, 160);analogWrite(in2, 0);analogWrite(in3, 0);analogWrite(in4, 0);delay (10);}}if (( ( _ABVAR_1_data ) == ( 12 ) )){     for(int i=0;i<10;i++){servo_move(190, 40, 20, 130);analogWrite(in1,150);analogWrite(in2,0);     analogWrite(in4,150);analogWrite(in3,0);delay (1000);}}if (( ( _ABVAR_1_data ) == ( 3 ) )){     analogWrite(in1,150);analogWrite(in2,0);     analogWrite(in4,150);analogWrite(in3,0);delay (1000);}if (( ( _ABVAR_1_data ) == ( 0 ) )){       analogWrite(in1,0);analogWrite(in2,0);     analogWrite(in4,0);analogWrite(in3,0);}if (( ( _ABVAR_1_data ) == ( 4) ))   //jixiebi1{     servo_move(10, 40, 40, 130);delay(500);delay(500);delay(500);analogWrite(in5, 250);delay(500);}if (( ( _ABVAR_1_data ) == ( 5) ))   //jixiebi1{     servo_move(10, 40, 20, 60);delay(500);analogWrite(in5, 0);}if (( ( _ABVAR_1_data ) == ( 7) ))   //10, 110, 20, 40chu    100, 110, 60, 30   kaishi     100, 40, 60, 30zhua     100, 40, 40, 30qi    10, 40, 60, 30weizhi   {     servo_move(100, 110, 60, 30);delay(500);}if (( ( _ABVAR_1_data ) == ( 8) ))   //qi{     servo_move(100, 40, 60, 30);delay(500);}if (( ( _ABVAR_1_data ) == ( 9) ))   //fan{     servo_move( 100, 40, 40, 30);delay(1000);  }if (( ( _ABVAR_1_data ) == ( 10) ))   //fan{     servo_move( 10, 40, 60, 30);delay(1000);  }if (( ( _ABVAR_1_data ) == ( 11) ))   //fan{   servo_move(10, 40, 20, 40);delay(500);servo_move(100, 20, 20, 40);delay(500);servo_move(100, 130, 20, 40);delay(500);servo_move(100, 130, 50, 40);delay(500);   servo_move(100, 40, 50, 40);delay(500);servo_move(10, 40, 50, 40);delay(500);servo_move(10, 40, 20, 40);}}

6. 创新点

      小车行进结构利用“太极”式刚柔结合进行翻越障碍。当小车遇到有一定角度的倾斜坡的时候,此时小车的刚性材料组成的车轮即可派上用场,通过调整履带的旋转自由度,使得小车在上坡的过程中不会发射管前倾和后倾。在小车遇到有断崖(台阶)的地面环境时,其柔性材料做成的车轮,经过调整前轮的自由度和前轮和后轮之间的距离,可以做出俯仰抬头的动作,从而轻松爬上断崖(台阶}。与此同时,俩种不同材料组成的车轮,也解决了在移动过程中出现的打滑问题,使小车的稳定性更高。其次,小车的机械臂可以180°进行旋转,不仅使小车在工作时候可接触的范围更广,还减小了车的体积,从而加快了小车的速度,车身在此期间也可以保持到最佳的位置。在此期间,同时可以利用小车体积小的优势,可以顺利通过小的隧道进行工作。最后,我们设计的小车使其重心集中在了整个小车的最中心,减少了了在通过障碍工作途中造成小车前倾或者后倾,从而翻车的情况,加强了小车的稳定性。

7. 作品难点

      ① 本作品在左右两侧分别装有不同的机械结构,应对其进行有效合理的位置和结构设计,保证其相对应与其他传感器的配合。

      ② 小车在运行过程中需通过不同的障碍结构,而由于车身较小,故掌握小车在登台阶和上坡时的平衡很是关键,防止侧翻。故我们在进行上(下)坡(台阶)会将左右机械臂摆至前(后)进行平衡。

      ③ 在小车砍到设计的隔离带树木后,放在车后方拉出时,怎么样去寻找最合适的路线去拉走树木,从而防止其他树木在路途中阻挡砍到的树木撤离火源。

更多详情请见 :【S043】森林管理员

相关文章:

机器人制作开源方案 | 森林管理员

​作者&#xff1a;李佳骏、常睿康、张智斌、李世斌、高华耸 单位&#xff1a;山西能源学院 指导老师&#xff1a;赵浩成、郜敏 1. 研究背景 森林作为地球上可再生自然资源及陆地生态的主体&#xff0c;在人类生存和发展的历史中起着不可代替的作用&#xff0c;它不仅能提供…...

Laravel框架使用phpstudy本地安装的composer用Laravel 安装器进行安装搭建

一、首先需要安装Laravel 安装器 composer global require laravel/installer 二、安装器安装好后&#xff0c;可以使用如下命令创建项目 laravel new sys 三、本地运行 php artisan serve 四、 使用Composer快速安装Laravel5.8框架 安装指定版本的最新版本&#xff08;推荐&a…...

炫酷登录注册界面【超级简单 jQuery+JS+HTML+CSS实现】

一&#xff1a;源码获取 这两天根据需求写了一个比较好看的有动态效果的登录注册切换页面&#xff0c;这里我将源码资源分享给大家&#xff0c;大家可以直接免费下载使用哦&#xff0c;没有 vip 的小伙伴找我私聊发送"登录注册"即可我给你发文件&#xff0c;此登录注…...

2023年国赛高教杯数学建模E题黄河水沙监测数据分析解题全过程文档及程序

2023年国赛高教杯数学建模 E题 黄河水沙监测数据分析 原题再现 黄河是中华民族的母亲河。研究黄河水沙通量的变化规律对沿黄流域的环境治理、气候变化和人民生活的影响&#xff0c;以及对优化黄河流域水资源分配、协调人地关系、调水调沙、防洪减灾等方面都具有重要的理论指导…...

跨国企业传输大文件注意事项和解决方案

随着全球化的推进&#xff0c;越来越多的企业需要在跨国业务合作、项目交付、数据分析等方面展开合作&#xff0c;这就带来了大量大文件的传输需求。大文件传输是指文件大小超过1GB的传输&#xff0c;通常涉及视频、音频、图片、文档、压缩包等多种格式。跨国传输大文件不仅需要…...

【Redis】Redis 的数据类型

有五种常用数据类型&#xff1a;String、Hash、Set、List、SortedSet。以及三种特殊的数据类型&#xff1a;Bitmap、HyperLogLog、Geospatial &#xff0c;其中HyperLogLog、Bitmap的底层都是 String 数据类型&#xff0c;Geospatial 的底层是 Sorted Set 数据类型。 五种常用…...

QT小技巧 - 使用QMovie进行gif切帧

简介 使用QMovie 将 gif 进行切帧&#xff0c; magick 进行合并代码 QString gifPath "E:\\workspace\\qt\\gif2imgs\\203526qre64haq3ccoobqi.gif"; // 你的图片QMovie movie(gifPath); movie.setCacheMode(QMovie::CacheNone);qDebug() << movie.frameCou…...

ES-搜索

聚合分析 聚合分析&#xff0c;英文为Aggregation&#xff0c;是es 除搜索功能外提供的针对es 数据做统计分析的功能 - 功能丰富&#xff0c;提供Bucket、Metric、Pipeline等多种分析方式&#xff0c;可以满足大部分的分析需求 实时性高&#xff0c;所有的计算结果都是即时返回…...

微信小程序面试题

微信小程序面试题 请解释微信小程序的生命周期及其对应的钩子函数。 微信小程序的生命周期包括 onLaunch、onShow、onHide、onError、onPageNotFound 等阶段。对应的钩子函数分别是&#xff1a; onLaunch&#xff1a;小程序初始化时触发。onShow&#xff1a;小程序启动或从后台…...

OpenCV之图像匹配与定位

利用图像特征的keypoints和descriptor来实现图像的匹配与定位。图像匹配算法主要有暴力匹配和FLANN匹配&#xff0c;而图像定位是通过图像匹配结果来反向查询它们在目标图片中的具体坐标位置。 以QQ登录界面为例&#xff0c;将整个QQ登录界面保存为QQ.png文件&#xff0c;QQ登…...

掌握JWT:解密身份验证和授权的关键技术

JSON Web Token 1、什么是JWT2、JWT解决了什么问题3、早期的SSO认证4、JWT认证5、JWT优势6、JWT结构Header 标头Payload 负载 Signature 签名 7、代码实现添加依赖生成Token认证token 8、工具类9、JWT整合Web10、拦截器校验11、网关路由校验12、解决多用户登录的问题13、客户端…...

git命令和docker命令

1、git git是分布式的版本控制工具 git可以通过本地仓库管理文件的历史版本记录 # 本地仓库操作的命令 # 初始化本地库 git init # 添加文件到暂存区 git add . git checkout 暂存区要撤销的文件名称 # 提交暂存区文件 git commit -m 注释# 版本穿梭 # 查看提交记录 git log…...

【K8S in Action】服务:让客户端发现pod 并与之通信(2)

一 通过Ingress暴露服务 Ingress (名词&#xff09; 一一进入或进入的行为&#xff1b;进入的权利&#xff1b;进入的手段或地点&#xff1b;入口。一个重要的原因是每个 LoadBalancer 服务都需要自己的负载均衡器&#xff0c; 以及 独有的公有 IP 地址&#xff0c; 而 Ingres…...

Spring Boot 中实现跨域的几种方式

前言 在现代Web应用中&#xff0c;由于安全性和隐私的考虑&#xff0c;浏览器限制了从一个域向另一个域发起的跨域HTTP请求。解决这个问题的一种常见方式是实现跨域资源共享&#xff08;CORS&#xff09;。Spring Boot提供了多种方式来处理跨域请求&#xff0c;本文将介绍其中的…...

WT2605C音频蓝牙语音芯片:单芯片实现蓝牙+MP3+BLE+电话本多功能应用

在当今的电子产品领域&#xff0c;多功能、高集成度成为了一种趋势。各种产品都需要具备多种功能&#xff0c;以满足用户多样化的需求。针对这一市场趋势&#xff0c;唯创知音推出了一款集成了蓝牙、MP3播放、BLE和电话本功能的音频蓝牙语音芯片——WT2605C&#xff0c;实现了单…...

计算机毕业设计 基于SpringBoot的高校宣讲会管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…...

Android 使用Serialiable接口和Parcelable接口进行数据传送

一、前言 这篇文章主要针对Serialiable和Parcelable接口来传递对象。呈现的功能是跳转到另一个界面&#xff0c;然后通过toast展现我收到的数据。 二、使用Serialiable接口传递数据 1.创建需要传递的对象 //必须实现Serializable接口&#xff0c;此对象才有传递的资格 publ…...

【数据结构入门精讲 | 第十七篇】一文讲清图及各类图算法

在上一篇中我们进行了的并查集相关练习&#xff0c;在这一篇中我们将学习图的知识点。 目录 概念深度优先DFS伪代码 广度优先BFS伪代码 最短路径算法&#xff08;Dijkstra&#xff09;伪代码 Floyd算法拓扑排序逆拓扑排序 概念 下面介绍几种在对图操作时常用的算法。 深度优先D…...

Python 直方图的绘制-`hist()`方法(Matplotlib篇-第7讲)

Python 直方图的绘制-hist()方法(Matplotlib篇-第7讲)         🍹博主 侯小啾 感谢您的支持与信赖。☀️ 🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹…...

Quartz持久化(springboot整合mybatis版本实现调度任务持久化)--提供源码下载

1、Quartz持久化功能概述 1、实现使用quartz提供的默认11张持久化表存储quartz相关信息。 2、实现定时任务的编辑、启动、关闭、删除。 3、实现自定义持久化表存储quartz定时任务信息。 4、本案例使用springboot整合mybatis框架和MySQL数据库实现持久化 5、提供源码下载 …...

后进先出(LIFO)详解

LIFO 是 Last In, First Out 的缩写&#xff0c;中文译为后进先出。这是一种数据结构的工作原则&#xff0c;类似于一摞盘子或一叠书本&#xff1a; 最后放进去的元素最先出来 -想象往筒状容器里放盘子&#xff1a; &#xff08;1&#xff09;你放进的最后一个盘子&#xff08…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​&#xff0c;覆盖应用全生命周期测试需求&#xff0c;主要提供五大核心能力&#xff1a; ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…...

如何在网页里填写 PDF 表格?

有时候&#xff0c;你可能希望用户能在你的网站上填写 PDF 表单。然而&#xff0c;这件事并不简单&#xff0c;因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件&#xff0c;但原生并不支持编辑或填写它们。更糟的是&#xff0c;如果你想收集表单数据&#xff…...

基于Springboot+Vue的办公管理系统

角色&#xff1a; 管理员、员工 技术&#xff1a; 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能&#xff1a; 该办公管理系统是一个综合性的企业内部管理平台&#xff0c;旨在提升企业运营效率和员工管理水…...

uni-app学习笔记三十五--扩展组件的安装和使用

由于内置组件不能满足日常开发需要&#xff0c;uniapp官方也提供了众多的扩展组件供我们使用。由于不是内置组件&#xff0c;需要安装才能使用。 一、安装扩展插件 安装方法&#xff1a; 1.访问uniapp官方文档组件部分&#xff1a;组件使用的入门教程 | uni-app官网 点击左侧…...

__VUE_PROD_HYDRATION_MISMATCH_DETAILS__ is not explicitly defined.

这个警告表明您在使用Vue的esm-bundler构建版本时&#xff0c;未明确定义编译时特性标志。以下是详细解释和解决方案&#xff1a; ‌问题原因‌&#xff1a; 该标志是Vue 3.4引入的编译时特性标志&#xff0c;用于控制生产环境下SSR水合不匹配错误的详细报告1使用esm-bundler…...

基于 HTTP 的单向流式通信协议SSE详解

SSE&#xff08;Server-Sent Events&#xff09;详解 &#x1f9e0; 什么是 SSE&#xff1f; SSE&#xff08;Server-Sent Events&#xff09; 是 HTML5 标准中定义的一种通信机制&#xff0c;它允许服务器主动将事件推送给客户端&#xff08;浏览器&#xff09;。与传统的 H…...

C#中用于控制自定义特性(Attribute)

我们来详细解释一下 [AttributeUsage(AttributeTargets.Class, AllowMultiple false, Inherited false)] 这个 C# 属性。 在 C# 中&#xff0c;Attribute&#xff08;特性&#xff09;是一种用于向程序元素&#xff08;如类、方法、属性等&#xff09;添加元数据的机制。Attr…...

篇章一 论坛系统——前置知识

目录 1.软件开发 1.1 软件的生命周期 1.2 面向对象 1.3 CS、BS架构 1.CS架构​编辑 2.BS架构 1.4 软件需求 1.需求分类 2.需求获取 1.5 需求分析 1. 工作内容 1.6 面向对象分析 1.OOA的任务 2.统一建模语言UML 3. 用例模型 3.1 用例图的元素 3.2 建立用例模型 …...

数据可视化交互

目录 【实验目的】 【实验原理】 【实验环境】 【实验步骤】 一、安装 pyecharts 二、下载数据 三、实验任务 实验 1&#xff1a;AQI 横向对比条形图 代码说明&#xff1a; 运行结果&#xff1a; 实验 2&#xff1a;AQI 等级分布饼图 实验 3&#xff1a;多城市 AQI…...