当前位置: 首页 > 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、提供源码下载 …...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

【Go】3、Go语言进阶与依赖管理

前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课&#xff0c;做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程&#xff0c;它的核心机制是 Goroutine 协程、Channel 通道&#xff0c;并基于CSP&#xff08;Communicating Sequential Processes&#xff0…...

如何为服务器生成TLS证书

TLS&#xff08;Transport Layer Security&#xff09;证书是确保网络通信安全的重要手段&#xff0c;它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书&#xff0c;可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障

关键领域软件测试的"安全密码"&#xff1a;Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力&#xff0c;从金融交易到交通管控&#xff0c;这些关乎国计民生的关键领域…...

Linux部署私有文件管理系统MinIO

最近需要用到一个文件管理服务&#xff0c;但是又不想花钱&#xff0c;所以就想着自己搭建一个&#xff0c;刚好我们用的一个开源框架已经集成了MinIO&#xff0c;所以就选了这个 我这边对文件服务性能要求不是太高&#xff0c;单机版就可以 安装非常简单&#xff0c;几个命令就…...

《Docker》架构

文章目录 架构模式单机架构应用数据分离架构应用服务器集群架构读写分离/主从分离架构冷热分离架构垂直分库架构微服务架构容器编排架构什么是容器&#xff0c;docker&#xff0c;镜像&#xff0c;k8s 架构模式 单机架构 单机架构其实就是应用服务器和单机服务器都部署在同一…...

【Kafka】Kafka从入门到实战:构建高吞吐量分布式消息系统

Kafka从入门到实战:构建高吞吐量分布式消息系统 一、Kafka概述 Apache Kafka是一个分布式流处理平台,最初由LinkedIn开发,后成为Apache顶级项目。它被设计用于高吞吐量、低延迟的消息处理,能够处理来自多个生产者的海量数据,并将这些数据实时传递给消费者。 Kafka核心特…...

高防服务器价格高原因分析

高防服务器的价格较高&#xff0c;主要是由于其特殊的防御机制、硬件配置、运营维护等多方面的综合成本。以下从技术、资源和服务三个维度详细解析高防服务器昂贵的原因&#xff1a; 一、硬件与技术投入 大带宽需求 DDoS攻击通过占用大量带宽资源瘫痪目标服务器&#xff0c;因此…...

前端开发者常用网站

Can I use网站&#xff1a;一个查询网页技术兼容性的网站 一个查询网页技术兼容性的网站Can I use&#xff1a;Can I use... Support tables for HTML5, CSS3, etc (查询浏览器对HTML5的支持情况) 权威网站&#xff1a;MDN JavaScript权威网站&#xff1a;JavaScript | MDN...