基本信息

项目名称:
无线网络机器人监控系统
小类:
信息技术
简介:
本设计采用ZigBee无线传感器网络和SimpliciTI网络实现计算机终端对机器人进行无线控制与定位。通过组建ZigBee无线传感器网络,将大量无线的传感器节点组网,计算机终端可与机器人之间进行无线数据传输,不仅能够对机器人工作环境进行实时数据监测,而且能够对机器人无线控制以及无线定位。 经测试:机器人在发出命令到动作时间平均响应时间为0.8s;在室内的环境下无线操控范围距离小于20m,室外空旷地小于100m;定位功能受到环境和节点位置影响较大,定位精度小于5m;视频的最大传输值平均为7Mb/s;通信误码率<1/10000;信噪比(SNR)为60dB~75dB。 无线定位机器人既可独立工作,将采集各种数据传回PC控制端;PC控制端也可对其的进行远程操纵以及精确定位、目标跟踪。利用远程监控克服了全人工智能无法应对突发情况的缺点,将人工智能和人工干预相结合,因此大大加强了系统的灵活性与复杂环境的适用性。可以普遍应用于工厂、车站物流运输,小区安防巡逻、医疗护理、高危场所等领域。
详细介绍:
无线网络机器人监控系统 1. 系统设计 1.1 系统结构及功能 1.2 方案论证与选择 1.2.1 无线通信网络的方案论证与选择 1.2.2 定位方式方案论证与选择 1.2.3 定位算法方案论证与选择 1.2.4 智能避障的设计方案论证与选择 2. 系统单元设计 2.1 移动平台设计 2.1.1 移动平台结构与性能 2.1.2 电机以及驱动电路设计 2.1.3 超声波测距仪设计 2.1.4 红外避障模块设计 2.1.5 轨迹记录仪设计 2.2 控制电路设计 2.3 视频及其传输模块设计 2.4 ZigBee无线传感器网络硬件设计 2.4.1监控终端以及监控节点硬件设计 2.4.2 无线定位节点硬件设计 2.5 SimpliciTI无线通信网络设计 2.5.1 SimpliciTI无线通信网络软件设计 2.5.3 SimpliciTI无线通信网络硬件平台设计 3. ZigBee无线传感器网络设计 3.1 开发工具IAR Embedded Workbench for MCS-51简介 3.2 建立ZigBee无线传感器网络 3.2.1启动ZigBee网络协调器 3.2.2允许设备入网 3.2.3设备入网 3.3 ZigBee无线传感器网络数据服务 3.3.1 NWK数据服务请求 3.3.2 NWK数据服务证实 4. ZigBee无线传感器网络定位系统 4.1 ZigBee无线传感器网络定位机制 4.2 ZigBee无线传感器网络定位引擎配置 4.3 ZigBee无线传感器网络定位系统节点的设置与部署 5. 程序设计 5.1 硬件设计和软件设计的关系 5.2 上位机部分程序设计 5.2.1 程序流程图 5.3 下位机部分程序设计 5.3.1 程序流程图 5.3.3 避障部分程序设计 5.3.3 测距部分程序设计 5.3.4 轨迹记录部分程序设计 5.4 无线通信部分程序设计 5.5 无线定位部分程序设计 6. 系统测试 6.1 功能测试 6.2 性能测试 7. 结论 8. 参考文献 附录1 使用说明 附录2 主要元器件清单 附录3 电路原理图 附录3.1 移动平台控制部分电路原理图 附录3.2 CC1110无线网络节点电路原理图 附录3.3 CC2430/CC2431无线网络节点电路原理图 附录4 电路印制板图 附录4.1 移动平台控制部分印制板图 附录4.2 CC1110无线网络节点印制板图(顶层) 附录4.3 CC1110无线网络节点印制板图(底层) 附录4.4 CC2430/CC2431无线网络节点印制板图(顶层) 附录4.3 CC2430/CC2431无线网络节点印制板图(底层) 附录5 程序清单 附录5.1 电机控制程序清单 附录5.2 上位机主控模块程序清单 附录5.3 下位机主控模块程序清单 附录5.4 CC2430参考节点代码 附录5.5 CC2431定位节点代码 附录5.6 ZigBee协议协调器操作代码 附录5.7 CC1110 AP节点代码 附录5.8 CC1110 ED节点代码 附录6 实物图 附录6.1 移动平台实物图 附录6.2 无线网络节点及其网关实物图 1. 系统设计 1.1 系统结构及功能 本系统可以分成机器人工作终端、无线传感器监控网络和PC监控终端,通过ZigBee和SimpliciTI无线通信网络网络将二者连接起来。机器人工作终端以移动平台为载体,搭载自动化设备和传感器,并通过无线网络将各类传感器收集获得的数据由传输至PC监控终端。同时PC监控终端也可以通过无线传感器监控网络上传的数据。这样PC监控终端既可获得各机器人工作终端的位置,亦可对机器人的工作环境和情况进行实时监视,在必要时对机器人终端通过SimpliciTI无线通信网络进行远程无线操纵。 监控终端由数据中心与电脑组成。数据中心是由无线网络的无线网关构成,在两种网络中分别由Zigbee无线网关和SimpliciTI 无线网关所担任,数据中心负责网络管理,担当网络内设备成员管理任务并为终端节点提供数据储存及转发。此外监控终端还包括一个无线视频监控器,其摄像端安置于工作终端,通过此方式加大了对工作终端监控力度。 机器人工作终端系统是由微控制器与网络节点、传感器、移动平台共同组成,在微控制器的统一调度之下,使机器人自主工作,将采集到的工作环境信息及位置信息经无线网络传回无线网关,并能接收控制信号引导机器人动作。 无线传感器监测网络是由大量的监控节点构成,监测节点携带了所需要的传感器,大量的监测节点形成的无线网络用于收集机器人发送的位置信息、环境信息,当机器人工作位置在PC监控终端“1跳”范围之外时,监测节点还可以担任数据传输中转任务。 1.2 方案的确定 1.2.1 无线通信网络方案 无线通信方式有工作频段、覆盖范围、网络容量、传输速度、安全性、功耗等性能指标。从传输速率的角度来划分可以分为两大类。一类是以无线高保真Wi-Fi和蓝牙(Bluetooth) 为代表的高速无线通信技术,一类是以Zigbee为代表的低速无线通信网络技术。从设计的需求来分析,要求通信方式必须易于组网,对通信速率要求相对较低,抗干扰以及安全性较弱,对频段没有特殊的要求。 根据对不同方案的初步分析,可以看到各种网络的性能以及应用范围。Wi-Fi技术性能优越,满足了多媒体以及Internet数据的传输要求,但是将其应用与本设计就将大大浪费资源,并且其高功耗使得系统持续工作时间很短。Bluetooth的传输速度也达到了1Mbit/s,而且安全性也相对较高,虽然设备的通用性较高,但是协议复杂、组网不够便利且覆盖范围较小。由以上分析可知Wi-Fi和Bluetooth 都是很出色的无线系统,实际上它拥有最大的无线技术容量,但是这些技术的目标并不是以监控为主要目标的无线应用。相对于简单的低功耗应用来说,两者的功能都过于强大,产生资源的浪费。因此Zigbee 为代表的低速无线通信技术应为方案的首选。从数据速率以及覆盖范围、功耗二者没有太大的区别,但是Zigbee网络支持一种定位技术,相比之下其监控功能强大很多。从Zigbee协议结构与SimpliciTI协议结构相比,SimpliciTI协议取消了物理层(PHY)和数据链路层(MAC),使协议更加简化。正是由于SimpliciTI抛弃了很多保障功能,其数据速率会更快、功耗会更低。因此将二者结合使用,发挥自身的优势。 1.2.2 定位方案 根据机器人的工作环境的不同可分为室内、室外两种情况,并且这两种情况下都有与之相适应的的定位技术。目前广泛应用于定位领域的是GPS技术,GPS几乎可以覆盖全球并且民用是免费的。相对于GPS而言在某些场合下针对局部范围内的定位方式大多都必须根据实际情况架设RF基站,在组成无线网络之后才能针对设备终端信号进行位置判断。 在机器人定位方式的选择中,GPS定位系统相对小型设备定位精度比较低,而且当移动平台在室内工作时GPS又需要对设备进行改进,此方案在应用中会遇到很多实际问题。而上述局部定位方式,在架设基站与组建局域网的过程中会遇到复杂的问题,并且在接收与处理信号方面对硬件有更高的要求,实现起来所需的算法以及数据处理非常复杂。相对而言基于CC2431无线定位引擎的定位系统的开发和使用比较简单,而且由于建立ZigBee无线传感器网络的基础上,大大节约了系统整体的软硬件开销。此外需再结合多种传感器对机器人进行辅助定位。 1.2.3 定位算法方案 在基于ZigBee协议的无线传感器网络中,其定位机制可以简述为:根据有限的位置已知的信标节点来确定网络中其他节点的位置,在无线传感器网络节点之间建立起位置关联的机制。在该网络中需要定位的节点称之为未知节点(Blind node),而已知位置并需确定该网络中未知节点位置的节点称之为参考节点(Reference node),在一个节点通信半径范围的可直接通信的节点称之为邻节点(Neighbor node)。 在基于ZigBee协议的无线传感器网络中,传感器节点的节点数目大、能量有限、可靠性差,甚至部署都有不确定性,此外节点通信能力、数据储存和处理能力有限。因此建立在ZigBee无线传感器网络上的定位技术,需要针对无线传感器网络节点数量多,网络规模大的特点,满足其低成本、低功耗、低依赖度和高适应性的要求。 在ZigBee无线传感器网络当中,由CC2431芯片组成的节点模块使用芯片已有的定位引擎精确地读出RSSI值,进一步处理和传输RSSI值,不需要增加额外硬件的。在测定节点间距离的基础上,通过参考节点计算未知节点的方法有多种,从最简单三点定位直至多点定位可以由几何关系建立方程组从而求得未知节点的位置。 在大规模的无线传感器网络中,这种简单的定位算法不可能适应,因此在此基础之上必须改进网络节点的部署和定位算法。为了约束网络的无限扩大和节点之间的复杂无序状态,按照每个未知节点和周围节点相近的位置关系自动组合,形成若干个单元,通过多个未知节点之间的距离信息将各单元相组合,形成相对的坐标系统。从其中划分出边界节点,通过对周围单元网络的约束关系,从而确定了全局坐标下各单元网络的坐标变换矩阵。进一步将网络中的节点进一步细分为:参考节点、已知节点、准已知节点、边界节点、未知节点。准已知节点是指单位网络内局部坐标系下位置已知点,而局部坐标系又可通过坐标变换矩阵同全局坐标系相转换,最终确定了每一节点的位置。 目前在各种领域内都有与其相适应的合适算法,例如DV-HOP、EUCLIDEAN、ROBUST POSITION等算法,它们都各自用来解决不同的问题支持不同的应用范围。在本设计中由于网络没有形成很大规模,因此只需要简单的算法既可。 CC2431的定位算法为基于处理RSSI方法,定位方案示意图。在此坐标系下,所以参考节点的位置信息可以简化为(x,y)的形式。当进行定位检测时未知节点(Blind node)向各参考节点(Reference node)发出请求并接收参考节点的响应信号,各参考节点向未知节点发送包含参考节点“X”和“Y”位置信息的数据包,未知节点读出接收到的RSSI数值,并送入硬件引擎。此外定位计算能够在每一个未知节点上所运行,运算被分散,只有传送计算后的位置,这样减少了在网络中传输数据的总量。因此在简易的条件下,以CC2431芯片为基础的ZigBee定位方案是最佳的选择。 1.2.4 智能避障方案 超声波传感器相比之下检测速度快、范围广,并且超声波传感器可以测量移动平台至障碍物的距离。在本设计中超声波传感器是实现测量障碍物距离最佳的选择。 2. 系统单元 无线定位机器人主要包括机器人终端、无线传感器网络节点和PC监控端。机器人终端以车体机械平台为载体,包含有控制器电路模块、电机驱动模块、视频图像模块、智能避障模块、轨迹记录仪模块、CC2431定位模块等部分。无线网络节点是由多个CC2431无线模块通过ZigBee协议组成一个无线网络,每个模块可以安装各种传感器接收所在位置的数据并将其传回无线网关,最终上传至PC控制端。同时无线网络节点也可以对机器人终端进行定位。 2.1 移动平台 移动平台的工作环境不确定,因此移动平台需要具有强劲的动力,转弯灵活爬坡能力好,于是本设计采用由步进电机驱动的两轮履带设计方案。从动链轮的芯轮轴置于可前后和上下移动的调节滑块和弹性悬架上,使前轮不仅具有转向作用又能够起到驱动作用,这样移动平台牵引力得到增强,满足在负载较大时对牵引力的需求,转向精度也大大提高并且具备了原地旋转的能力。 2.1.1 移动平台结构与性能 移动平台结构与性能如下所示: 车体外形:180mm(长)× 125.5mm(宽)× 55mm(高),底盘高 9mm ,车轮直径48mm ; 电机:额定功率下输出电流270mA; 齿轮:三级12:50; 扭矩大小: 1.2 kg•cm; 载重:7.5Kg; 速度:最大行驶速度30cm/s,通过调整PWM输出可以控制移动平台的速度; 电池:采用铅蓄电池,型号为BT- 12M HRSEALED LEAD.ACID BATTERY,重量为1.00Kg,最大充电电流为550mA,充电电压为14.5V~15.0V。 根据移动平台的载重大小和速度的快慢不同,测试结果表明最长续航时间为3小时。 2.1.2 电机以及驱动电路 电机作为移动平台移动能力核心来源,直接关系到整个移动平台的性能,因此必须选取合适的电机。本移动平台采用了260直流电机,针对市面上种类繁多的直流电机驱动器集成电路芯片,结合大量的260直流电机工作的实际数据进行分析。主要以移动平台堵转时的最大电流,正常行驶中的平均电流,爬坡时的相对电流平均值,电机的工作电压,以及要求的实时反应速度为主要指标,最终确定选择专用电机驱动集成电路芯片LM18200来驱动电机。 2.1.3 超声波测距仪 超声波测距仪的设计包括硬件设计和软件设计两个部分。将超声波传感器与舵机结合安装,舵机在微控制器的控制下可旋转180°,由舵机带动控制超声波传感器的旋转,利用一个超声波传感器检测前方180°内的障碍。相比单一的超声波传感器安装方案视野更加广阔,避障更强。这种方案不但节省了器件成本,而其节约了I/O口线的资源。使得避障模块占用CPU资源少,CPU则可以更大发挥其功能。 2.1.4 红外避障模块 采用红外传感器E18-D80NK可探测是否存在前方障碍物。加装施密特触发器及滤光后,可以精确探测前方3厘米处是否有障碍物。此外在移动平台前方,左侧和右侧各安装一只红外传感器。 2.1.5 轨迹记录仪 通过记录平台直线移动距离以及车体转向角度可以达到记录平台的行进轨迹的目的。记录直线移动距离可以通过测量车轮转动的次数与车轮周长即可,记录移动平台转动角度通过软件的方式记录前后电机行进时间和暂停时间从而间接测量移动平台的转动数据。记录直线移动距离采用霍尔集传感器。 2.2 控制电路 移动平台的控制电路以P89V51RD2为核心,外围设备包括电源电路、电机驱动电路、轨迹记录仪、红外避障,障碍物距离检测等模块,完成了P89V51RD2与各工作模块通信,并对其进行统一协调控制。 2.3 视频及其传输模块 该系统包括CCD成像系统和无线数据传输模块。CCD (Charge Coupled Device)可以将可视范围内的景物通过感光单元逐点地进行光电信号转换、存储和传输,输出为视频信号。无线视频数据传输可以实现PC监控端得到机器人周围图像,操控人员依据视频图像对机器人进行远程无线操控。 2.4 ZigBee无线传感器网络硬件 Zigbee技术是一种具有统一技术标准的短距离无线通信技术。完整的Zigbee协议栈由物理层(PHY)、介质访问控制层(MAC)、网络层、安全层和应用层组成。其物理层和介质访问控制层协议为IEEE802.15.4协议标准,网络层和安全层由Zigbee联盟制定,应用层的开发应根据用户自己的需要,进行进一步开发利用。 物理层和介质访问控制层协议为IEEE802.15.4协议标准,本设计选定工作层为2.4GHz物理层,该频段定义了16个频道。IEEE规范了物理层的传输速率和调制方式等相关内容并且为MAC和物理层保留了一个无线通道的接口。 介质访问控制层处理所有物理层无线信道的接入,包括设备间无线链路的建立、维护和断开,确定模式的帧传送与接收,信道的接入与控制。在本设计中,Zigbee网络采用星状网络,需要中心控制设备,并且与PC相通信,组成PC监控端。 ZigBee网络层的主要功能是提供一些必要的函数,确保ZIgBee的MAC层正常工作,并且为应用层提供合适的服务接口。为了向应用层提供其接口,网络层提供了两个必须的功能服务实体,它们分别为数据服务实体和管理服务实体。数据服务实体为数据提供服务,在同一个内部个域网中两个或者更多的设备之间传送数据时,将按照应用协议数据单元(APDU)的格式进行传送。网络层管理实体提供网络管理服务,具有配置一个新的设备、初始化一个网络、连接和断开网络、邻居设备发现、路由发现、接收控制等功能。 在ZigBee网络中存在三种逻辑设备类型:协调器 (Coordinator),路由器 (Router)和终端设备 (End-Device)。ZigBee网络由一个协调器以及多个路由器和多个终端设备组成 。ZigBee无线传感器终端节点都是由一个8位或16位的单片机和ZigBee射频芯片组成。Ti-Chipcon公司生产的CC2430/31是其中的比较好的选择。终端节点可分为参考节点和未知节点以及传感器监控节点。从硬件组成来说,各节点都是由CC2430/31为核心搭建的模块。唯一不同是CC2431相比CC2430增加了一个定位引擎,也正是因此,搭载了CC2431的模块可以作为未知节点,参考节点可由CC2430担任,未知节点通过对参考节点的检测即可得出自身位置,完成对机器人的定位。 2.4.1监控终端以及监控节点硬件 监控终端在网络中是作为协调器存在,监控节点是作为终端设备或者路由器存在。为了节约成本,不需要定位功能的监控终端和监控节点均可以由CC2430担任。 CC2430是一款支持ZigBee协议的低功耗的片上系统,它包括ZigBee 射频前端、内存和微控制器。 2.4.2无线定位节点硬件 无线定位节点要求芯片具有定位功能,因此无线定位节点模块必须选用带有定位引擎的CC2431芯片。定位引擎利用是一个从软件层面看来极其简单的输入输出端口,简单地可以理解为写入参数,等待计算,读出计算的位置结果。 2.5 SimpliciTI无线通信网络 2.5.1 SimpliciTI无线通信网络软件 SimpliciTI 网络协议能够简化施工,可实现MCU资源占用的最小化,从而降低了低功耗RF网络的系统成本,对Zigbee网络是一种很好的补充。SimpliciTI 网络协议支持星状网络拓扑和点对点对等网络两种基本的网络拓扑结构。星状网络拓扑包括1个数据中心和若干个终端节点。数据中心负责网络管理。为终端节点提供数据储存转发,并可以管理网络内设备成员。SimpliciTI 网络协议所支持的点对点通信,可以使数据中心(Access Point)储存并发送数据,并且通过范围拓展设备(Range Extender)来扩大网络覆盖范围以支持四次网络跳转。 SimpliciTI协议主要包括。SimpliciTI 网络协议主要包括三层:应用层(Application Layer)、网络层(Network Layer)、硬件逻辑层(Lite Hardware Abstraction Layer),硬件逻辑层包括射频层(Radio)、应用板支持程序包(Board Support Package)。SimpliciTI没有物理层(PHY)和数据链路层(MAc/LLC),数据直接从射频层接收。 本设计中将通信网络设置为星状网络。其包括1个数据中心和若干终端节点。数据中心主要负责网络管理。数据中心为终端节点ED提供存储、转发等,并管理网络设备内成员权限、连接权限以及安全等。同时支持点对点无线数据传输。即sirnpliciTI网络可以支持任意一对点对点设备之间的数据传输。以此为基础,PC监控端可以与任意的机器人之间相互通信从而达到无线操控的目的。 2.5.3 SimpliciTI无线通信网络硬件平台 SimpliciTI协议能够开盒即用(out of the box)地在CC1110上运行,因此在SimpliciTI网络中经常使用CC1110来完成组网任务。无线通信网络的节点是以CC1110为核心搭建而成。 3. ZigBee无线传感器网络设计 3.1 开发工具IAR Embedded Workbench for MCS-51 IAR Embedded Workbench for MCS-51S是由IAR Systems公司为CC2430、CC1110等芯片开发的一个集成环境。IAR Embedded Workbench具有入门容易、使用方便、代码紧凑的特点。该环境包含一个全软件的模拟程序。用户不需要任何硬件支持就可以针对各种芯片内核,外部设备以及中断进行仿真。本设计所用的是IAR Embedded Workbench 7.20。 3.2 ZigBee无线传感器网络建立 3.2.1启动ZigBee网络协调器 在对以下函数进行调用后,即可启动ZigBee网络协调器。 (1)NLME-NETWORK-FORMATION.request原语 (2)MLME-SCAN.request原语 (3)MLME-SCAN.confirm原语 (4)MLME-SET.request原语 (5)MLME-START.request原语 (6)NLME-NETWORK-FORMATION.confirm原语等 3.2.2允许设备入网 ZigBee协调器或路由器的上层产生NLME-PERMIT-JIONING.request请求原语,并将其发送到NLME,为MAC子层的允许关联标志位设置为某个数值,在此时间内ZigBee协调器或路由器允许其他设备加入到它所在的网络。 NLME-PERMIT-JOINlNG.request原语由ZigBee协调器或路由器的上层产生并发送给NLME,用以把MAC子层的允许关联标志位设置为一个固定时限,在这段时间内ZigBee协调器或路由器允许其他设备加入到它所在的网络。只有ZigBee协调器或路由器的上层能够发NLME-PERMIT-JOINlNG.request原语。如果一个ZigBee终端设备的NWK层收到该请求原语,NLME-PERMIT-JOINING.confirm证实原语将返回状态INVALID_REQUEST。当接收到NLME-PERMIT-JOINING.request原的PermitDumtion等于0x00时,NLME就向MAC子层发出MLME-SET.request原语把MACPIB属性macAssociationPermit设为FALSE。MLME在收到来自MAC层的证实原语MIME-SET.confirm后,再向上一层发送与MLME-SET.comfirm相同状态的证实原语NLME-PERMIT-JOINING.confirm。当接收到NLME-PERMIT-JOINING.request原语PermitDuration参数值等于0xFF时,NLME就向MAC子层发出MLME-SET.request原语把MAC PIB属性maeAssociationPermit设为TRUE。MLME在收到证实原语MLME-SET.confirm后,再向上一层发送相同状态的证实原语NLME-PERMIT-JOINIMG.confirm。如果接收到NLME-PERMIT-JOINING.request原语的PermitDuration参数值不等于Ox00或Oxff,NLME将采用同样的方法把MAC PIB属性maeAssociatiouPermit设为TRUE,在接收到证实原语MLME-SET.confirm后启动一个定时器,计时时长为PermitDmation秒。启动定时器后,NLME就向上层发送NLME-PERMIT-JOINING.comfirm证实原语,状态等于MAC子层返回的状态。计时期满后,NLME再次调用MLME-SET.request原语把属macAssociafionPermit设置为FALSE。 NLME-PERMIT-JOINING.comfirm证实原语是对NLME-PERMIT-JOINING.request的响应,它是由ZigBee协调器或路由器的NLME发送,告知应用层请求允许关联的请求结果。 3.2.3设备入网 设备入网,需要对以下函数进行调用。 (1)NLME-NETWORK-DISCOVERY.request原语 (2)MLME-BEACON-NOTIFY.indcation指示原语 (3)NLME-NETWORK-DISCOVERY.confirm原语 (4)NLME-JOIN.request请求原语 (5)MLME-ASSOCIATE.request原语 (6)MLME-ASSOCIATE.indication关联指示原语 (7)MLME-COMM-STATUS.indication原语 (8)NLME-JOIN.indication原语 (9)NLME-DIRECT-JOIN.request原语 (10)NLME-DIRECT-JOIN.confirm原语 (11)MLME-ORPHAN.indication原语 (12)MLME-ORPHAN.response原语 (13)NLME-START-ROUTER.request原语 (14)NLME-START-ROUTER.confirm原语 3.3 ZigBee无线传感器网络数据服务 NLDE-SAP支持在对等应用实体之间传送应用协议数据单元(APDU)。NLDE-SAP支持的原语包括NLDE-DATA请求、证实和指示原语。 3.3.1 NWK数据服务请求 NWK数据服务请求,需要对以下函数进行调用。 (1)NLDE-DATA.request原语 (2)NLDE-DATA.request原语 (3)MCPS-DATA.confirm原语 (4)MCPS-DATA.indication原语 (5)MCPS-PURGE.request原语 (6)MCPS-PURGE.confirm原语 3.3.2 NWK数据服务证实 NWK数据服务证实,需要对以下函数进行调用。 (1)NLDE-DATA.confirm原语 (2)NLDE-DATA.indication原语 4. ZigBee无线传感器网络定位系统 4.1 ZigBee无线传感器网络定位机制 在基于ZigBee协议的无线传感器网络中,其定位机制可以表述为:根据有限的位置已知的节点来确定网络中其他节点的位置,在无线传感器网络节点之间建立起位置关联的机制。在该网络中需要定位的节点称之为未知节点,而已知位置并需确定该网络中未知节点位置的节点称之为参考节点,在一个节点通信半径范围的可直接通信的节点称之为邻节点。 4.2 ZigBee无线传感器网络定位引擎配置 定位机制的实现必须依赖相应的物理硬件,即带有定位引擎的CC2431以及CC2430,以CC2431为基础的盲节点利用其定位引擎可以依据参考节点所提供的物理位置参数(参考节点X和Y值)以及RSSI值计算出盲节点的物理位置。而基于CC2431的定位机制中所使用的算法则是依赖于接收信号强度指示器(RSSI)的数值RSSI值随距离增加而减小。 参考节点需要具有静态位置,必须配置反映该节点物理位置的X和Y值。参考节点的主要任务是提供包含XY坐标的数据包传输给盲节点,也可做为锚定节点被查阅。此类节点只要能反映出RSSI值即可,因此参考节点可以使用CC2430。 盲节点需要与其周围的参考节点通信,并且需要收集每个参考节点的物理位置的X和Y值以及RSSI,然后使用硬件定位引擎计算它身的位置。然后将计算出的位置发送至无线网关。因此盲节点必须使用带有定位引擎的CC2431。 定位引擎利用是一个从软件层面看来极其简单的输入输出端口,简单地可以理解为写入参数,等待计算,读出计算的位置结果。 4.3 ZigBee无线传感器网络定位系统节点的设置与部署 一般来说参考节点的数目尽可能多的参考节点应该被使用。要得到一个比较准确的坐标至少需要4个参考节点。如果太少节点被使用,来自于每个节点的混淆会变得更高,并且错误的RSSI值能引起计算出的位置重大改变。 在实际的计算之中,最近的参考节点优选被用于计算。一般来说是具有最高RSSI值的8个参考节点,而其他的所有节点应该被忽略。如果达不到8个,那么尽可能多的节点应该被使用。 在大规模的无线传感器网络中,这种简单的定位算法不可能适应,因此在此基础之上必须改进网络节点的部署和定位算法。 为了约束网络的无限扩大和节点之间的复杂无序状态,按照每个未知节点和周围节点相近的位置关系自动组合,形成若干个单元,通过多个未知节点之间的距离信息将各单元相组合,形成相对的坐标系统。从其中划分出边界节点,通过对周围单元网络的约束关系,从而确定了全局坐标下各单元网络的坐标变换矩阵。进一步将网络中的节点进一步细分为:参考节点、已知节点、准已知节点、边界节点、未知节点。准已知节点是指单位网络内局部坐标系下位置已知点,而局部坐标系又可通过坐标变换矩阵同全局坐标系相转换,最终确定了每一节点的位置。 在ZigBee无线网络定位系统中网关是必不可少的。网关的一些典型的功能是有节点配置、检查网络状态、要求盲节点执行计算。因为所有的位置计算在盲节点中执行,网关将不执行任何位置计算。它唯一的用途就是给用户提供与网络交互的能力。有两个主要途径建立网关:(1)网关是一个被动的设备,只能被动监听网络通信(2)它也做为网络活动的一部分。被动途径主要是包探测器,网关仅捕获RF包和提供这些信息给使用者。 在定位系统中需要使用Z-Stack定位规范,该定位规范被做为了一个ZigBee规范,并且可以通过ZigBee设备对象服务从而得到各种报文。 参考节点(设备ID:0x0010)总是允许盲节点查询它的位置(X/Y坐标)。 盲节点(设备ID:0x0011)是一个可移动的节点,可以查询射频范围内的参考节点(1跳邻节点)的位置和与它们每一个的RSSI。 Location Dongle(设备ID:0x0012) 设备与PC相连接并被其应用所使用(一个调试工具以及任何通过串口或USB的应用),可以用来与盲节点和参考节点交换TOA信息。PC应用可通过请求盲节点位置来执行定位处理,或者可以被动接收盲节点和参考节点的位置报告。PC端还可以配置盲节点和参考节点。 XY-RSSI请求(簇lD:0x0011)用来触发一个XY-RSSI响应报文。在发送一系列RSSI Blast报文后该请求应被立即发送,然后取回在“l跳”射频范围内的参考节点的坐标以及它们每一个的平均RSSI值。如果该报文被发送大于“1跳”半径,那么RssI将不可用。 XY-RSSI响应(簇ID:0x00l2)作为XY-RSSI请求报文发送的响应,RSSI平均值包含了RSSI请求报文本身的RSSI,然后RSSI平均值被归零以便为另一个一系列Blast报文做准备。因此,如果Blast报文从来被发送,那么RSSI平均值就是请求报文的RSSI值。 盲节点查找请求(簇ID:0x0013)报文使一个盲节点以迫使它执行一个位置查找。当位置查找完成后,该报文的响应报文被盲节点发回。位置查找时间取决于网络的总流量。 盲节点查找响应(簇ID:0x0014)是盲节点查找请求的响应。 参考节点配置(簇ID:0x0015)发送该报文给一个参考节点来设置它的配置项目。该报文也从参考节点被发送以响应参考节点配置请求报文。 盲节点配置(簇ID:0x0016)发送该报文给一个盲节点来设置它的配置项目。该报文也从参考节点被发送以响应“盲节点配置”请求报文。 参考节点配置请求(簇ID:0x0017)配置一个参考节点。该请求报文的响应报文是“参考节点配置”报文。 盲节点配置请求(ID:0x0018)配置一个盲节点。该请求报文的响应报文是“盲节点配置”报文。 RSSI Blast(簇ID:0x0019)以“1跳”半径广播该报文,在相对短的时间多次发送来触发射频范围内的参考节点计算它们收到的Blast 广播报文的平均RSSI。 5. 程序设计 软件分为上位机程序和下位机程序两部分。软件设计的平台为Windows XP SP2,上位机程序使用Microsoft Visual C++ 6.0(SP6)开发,下位机程序使用u Vision3 V3.34(Keil Software)开发。 5.1 硬件设计和软件设计的关系 硬件设计的目标是标准化、模块化、简单化,以求达到给软件提供清晰明了、可控性强的硬件接口的目的。于是,在进行软件设计时就能集中精力去实现关键部分的算法并且设计出更加良好的软件架构,以求提高软件的稳定性、可复用性、可修改性,进而提升系统的整体性能。 5.2 上位机部分程序设计 上位机程序主要可分为舵机控制模块、电机控制模块、数据接收模块,其中舵机模块包含测距模块和图像传输模块。 5.3 下位机部分程序设计 下位机程序主要可分为定位模块、超声波测距模块、电机控制模块、温度检测模块、液晶显示模块、轨迹记录模块、智能避障模块、舵机控制模块。 5.4 无线通信部分程序设计 系统采用SimpliciTI协议下CC1110 星状网络拓扑结构进行无线通信。主要分AP(数据中心)和ED(节点)两个部分。 5.5 无线定位部分程序设计 系统采用基于Zigbee无线传感器网络定位的方式,其中CC2431无线模块具有定位引擎从而可以根据RSSI进行无线定位。其程序主要分为协调器,参考节点和未知节点程序。 6. 系统测试 本系统可以分成工作终端和监控终端。测试主要分为功能测试、性能测试以及结论分析。测试所使用的仪器设备、软件有:数字示波器、串口调试助手等。 6.1 功能测试 测试的方法步骤为:将充好电的移动平台放到室内的平地上,连接好通信芯片,打开上位机软件,接通电源,操作上位机软件的同时记录移动平台反应的时间、温度、视频数据;将电机部分拆下换成低频示波器,分别记录其不同状态下的数据。 移动平台速度与占空比曲线测试,把占空比分为20个等分点,每个点相距5个百分点,测试时,先由0%上升到100%记录相应点的速度,再从100%下降到0%记录相应点的速度,记录相应点电机的速度,计算时取两点的平均值。已知齿轮比换算可得移动速度。 6.2 性能测试 测试的主要方法:下载测试程序到控制端芯片中,通过PC机的串口调试助手,发送数据给终端控制芯片并读出返回值,通过返回值可以得出相应的数据结果,同时记录好数据 7. 结论 无线网络机器人监控系统的设计与制作,最终完成了实现计算机终端对机器人进行无线操控与定位,完成了预期的目标。经测试:移动平台的动作灵敏度在电池电压为12V室内环境,发出命令到动作时间平均响应时间为0.8s;定位精度在室内的环境与主通信节点距离小于20m,大约为4cm;在室内复杂环境,视频图像掉帧现象不明显,图像实时完整性;视频的最大传输值平均为7Mb/s;通信误码率<1/10000;RSSI的瞬时值为sum(I2+Q2);RSSI的平均值为sum(RSSI(瞬时)/8192;信噪比(SNR)为60dB~75dB。 通过组建ZigBee无线传感器网络,将大量无线的传感器节点组成无线网络,不仅能够对机器人工作环境进行实时数据监测,而且能够对机器人无线控制以及无线定位。与现有的一些机器人控制系统相比较,本设计着重从无线控制方面入手,将机器人从有线电缆相分离,使得操作人员不仅可以轻松地完成对机器人的操纵,而且利用ZigBee无线传感器网络完成了对机器人工作环境的检测。此外机器人的定位问题一直是一个相对复杂的问题,本设计放弃了传统的定位方式,从大量信号传播方向路径的计算另辟蹊径,借助大量的廉价的无线传感器网络节点,简单的RSSI信号强度的距离衰减功率完成了对机器人的无线信号定位。 在实际测试当中,Zigbee无线传感器网络在组建之后系统将稳定运行,但是由于硬件原因程序下载不成功的概率比较大,而且在进出网络的时候比较容易丢失程序。总体来看工作相对稳定。RSSI值基于稳定无线网络环境下才能够稳定和计算的精确,而实际情况下无线电干扰因素太多,读出的数据很不稳定,特别是在电磁环境复杂的室内信号会更差,所以在室内环境下,受环境影响特别的大,比如关键参数包括:RSSI(接收信号场强)、干扰、SNR(信噪比)、最强接入点、总接入点数、信道信号和数据速率等,定位精度的效果不是很理想。但是误差还在允许的范围之内。以后的工作当中需要针对无线节点的位置进行进一步的研究,得出一个比较通用的结论,使得该系统能够广泛的适用于各种场合。 8. 参考文献 [1] 倪巍,王宗欣.基于接受信号强度测量的室内定位算法[J].复旦学报(自然科学版),2004年2月第43卷第1期,P72-P76 [2] 张明华,张申生,曹健.无线局域网中基于信号强度的室内定位[J].计算机科学,2007年,Vol134 №16,P68-P71 [3] 王文峰,耿力,基于射频识别的实时定位系统技术研究[J].集成电路,2007年第7期,P21-P24 [4] 杨凤,史浩山,朱灵波,赵洪钢.一种基于测距的无线传感器网络智能定位算法[J].传感技术学报,2008年1月第21 卷 第1 期,P135-P140 [5] 石鹏,徐凤燕,王宗欣.基于传播损耗模型的最大似然估计室内定位算法[J].信号处理,2005年10月第5期,P502-P504 [6] 陈维克,李文锋,首珩,袁兵. 基于RSSI的无线传感器网络加权质心定位算法[J].武汉理工大学学报(交通科学与工程版), 2006,(02) . [7] 李泳. 基于ZigBee技术的室内定位系统设计[D]. 上海师范大学, 2008 . [8] 李本佳. 无线传感器网络中的分布式定位算法[D]. 浙江大学, 2007 . [9] 王立波,陈慈发. CC2431的室内定位系统设计[J]. 单片机与嵌入式系统应用, 2008,(09) . [10] 王福豹,史龙,任丰原. 无线传感器网络中的自身定位系统和算法[J]. 软件学报, 2005,(05) . [11] Steven W Smith.The Scientist and Engineer S Guide to Digital Signal Processing [M]. California Technical Publishing,1999 [12] Texas Instruments Incorporated.CC1110Fx/CC111Fx Low-power sub-1GHz RF System-on-Chip (SoC) with MCU[EB/OL]. [2009.6.14]. focus.ti.com.cn/cn/ [13] Texas Instruments Incorporated.SimpliciTI Specification[EB/OL]. [2009.6.14]. http://www.ti.com [14] 李文仲,段朝玉.CC1110/CC2510无线自组织网络入门与实战[M].北京航空航天大学出版社,2007 [15] 李文仲,段朝玉.Zigbee2006无线网络与无线定位实践[M].北京航空航天大学出版社,2008 [16] 李文仲,段朝玉.Zigbee无线网络技术入门与实战[M]. 北京航空航天大学出版社,2007 [17] 黄智伟.全国大学生电子设计竞赛制作实训[M].北京航空航天大学出版社,2007 [18] 黄智伟.全国大学生电子设计竞赛电路设计[M].北京航空航天大学出版社,2006 [19] 黄智伟.全国大学生电子设计竞赛系统设计[M].北京航空航天大学出版社,2006 附录1 使用说明 无线网络机器人监控系统使用可以分为两个部分,第一为部分为网络节点的部署,在布网时要考虑传感器节点的位置并且将定位节点和通信节点安装于机器人外侧,PC监控端要与无线网关相连接调试实现网络畅通。第二部分为代码下载与软件安装,将机器人运动操控代码下载入控制器,将上位机软件安装于PC监控端。调试成功之后便可运行监控程序,实现对环境与机器人的无线监控。使用时首先打开PC机,连接好通信终端,启动上位机软件;然后依次接通无线网关电源、移动平台电源,此时系统进入自检状态。当1602液晶显示自检完成后即可开始工作。 附录2 主要元器件清单(略) 附录3 电路原理图(略) 附录4 电路印制板图(略) 附录5 程序清单 附录5.1 电机控制程序清单(略) 附录5.2 上位机主控模块程序清单(略) 附录5.3 下位机主控模块程序清单(略) 附录5.4 CC2430参考节点代码 ************************************************************************ // 函数名: static void processMSGCmd(afIncomingMSGPacket_t*pkt) // 功能: 通过串ID对数据信息处理 // 输入: 接收的数据 // 输出: 无 *************************************************************************/ static void processMSGCmd(afIncomingMSGPacket_t *pkt) { switch(pkt->clusterld) { case LOCAtiON_XY_RSSI_REQUEST: //XY_RSSI请求 rssiRsp(pkt); break; case LOCATION_REFNODE_CONFIG: //参考节点配置 parseConfig(pkt->cmd.Data); break; case LOCATION_REFNODE_REQUEST_CONFIG: //参考节点请求配置 pkt->srcAddr.addrMode=afAddr16Bit; rspMsgE43 = 0x88; rspMsg[5] = 0x99; (void)AF_DataRequest(&pkt->srcAddr,(endPointDesc_t*)&epDesc, \ LOCATION_REFNODE_CONFIG,REFNODE_CONFIG_LEN,rspMsg, & transId,0,AF_DEFAULT_RADIUS); break; case LOCATION_RSSI_BLAST: //收集RSSI addBlast(pkt->srcAddr.addr.shortAddr,pkt->LinkQuality); break; default; break; } }/*********************************************************************** // 函数名:static void rssiRsp(afIncomingMSGPacket_t *pkt) // 功能:响应XY_RSSI请求,发送RSSI平均值和坐标值 // 输入:接收的数据 // 输出:无 *************************************************************************/ static void rssiRsp(afIncomingMSGPacket_t *pkt) { blastAcc_t*ptr = blastPtr; blastAcc_t*prev=NULL; byte options,radius; while(ptr) { if(ptr->addr == pkt->srcAddr.addr.shortAddr) { break; } prey = ptr; ptr.ptr->next: } if(ptr) { rspMsg[LOCATION_XY_RSSI_RSSI_IDX] = (ptr->acc+pkt->LinkQuality)/(ptr->cnt + 1): if(prey) { prey->next.ptr->next; } else { blastPtr = ptr->next; } osal_mem_free(ptr); options = AF_SKIP_ROUTING; radius = 1; } else { rspMsg[LOCATION_XY_RSSI_RSSI_IDX] = pkt->LinkQuality; // 求RSSI平均值 options = AF_TX_OPTIONS_NONE; radius = AF_DEFAULT_RADIUS; } pkt->srcAddr.addrMode = afAddr16Bit; (void)AF_DataRequest(&pkt->srcAddr,(endPointDesc_t *)&epDesc, \ LOCATION_XY_RSSI_RESPONSE, LOCATION_XY_RSSI_LEN, \ rspMsg, &transId,options, radius); /************************************************************************ // 函数名:static void parseConfig(byte *msg) // 功能:配置参考节点坐标 // 输入:接收的数据 // 输出:无 *************************************************************************/ static void parseConfig(byte *msg) { refNode_Config_t config; config.x = BUILD_UINTl6(msg[REFNODE_CONFIG_X_LO_IDX], \ // x坐标低8位 msg[REFNODE_CONFIG_X_HI_IDX3) // x坐标高8位 config.y = BUILD_UINTl6(msg[REFNODE_CONFIG_Y_LO_IDX], \ // x坐标低8位 msg[REFNODE_CONFIG_Y_HI_IDX3) // y坐标高8位 osal_nv_write(LOC_NV_REFNODE_CONFIG, 0, sizeof(refNode_Config_t), &config); // 将配置参数写入Flash rspMsg[REFNODE_CONFIG_X_LO_IDX] = msg[REFNODE_CONFIG_X_LO_IDX]; rspMsg[REFNODE_CONFIG_X_HI_IDX] = msg[REFNODE_CONFIG_X_HI_IDX]; rspMsgEREFNODE_CONFIG_Y_LO_IDX] = msg[REFNODE_CONFIG_Y_LO_IDX]; spMsg[REFNODE_CONFIG_Y_HI_IDx] = msg[REFNODE_CONFIG_Y_HI_IDX]; } /************************************************************************* //函数名:static void addBlast(uintl6 addr,byte rssi) // 功能:添加或初始化一个定位节点和自身的RSSI值 // 输入:定位节点网络地址、RSSI // 输出:无 *************************************************************************/ static void addBlast(uintl6 addr,byte rssi) { blastAcc_t *ptr = blastPtr; while(ptr) { if(ptr->addr == addr) //网络地址已经存在 { break; } Ptr = ptr->next; } if(ptr) { Ptr->aCC+ = rssi; //添加RSSI Ptr->cnt++: } else { Ptr = (blastAcc_t*)osal_mem_alloc(sizeof(blastAcc_t)); if(ptr) //网络地址不存在 { Ptr->next = blastPtr; blastPtr = ptr; ptr->addr = addr; ptr->acc = rssi; ptr->cnt = 1; } }} /************************************************************************* //函数名:static void processMSGCmd(afIncomingMSGPacket_t *pkt) // 功能:数据回收处理 // 输入:接收到的数据 // 输出:无 *************************************************************************/ static void processMSGCmd(afIncomingMSGPacket_t *pkt) { switch(pkt->clusterId) { case LOCATION_XY_RSSI_REQUEST: rssiRsp(pkt); break; case LOCATION_REFNODE_CONFIG: parseConfig(pkt->cmd.Data); break; case LOCATION_REFNODE_REQUES_CONFIG: pkt一>srcAddr.addrMode = afAddrl6Bit; (void)AF_DataRequest(&pkt->srcAddr,(endPointDesc_t*)&epDesc, LOCATION_REFNODE_CONFIG,REFNODE_CONFIG_LEN,rspMsg, &transId,0,AF_DEFAULT_RADIUS); break; case LOCATl0N_RSSI_BLAST: addBlast(pkt->srcAddr.addr.shortAddr,pkt->LinkQuality); break; default; break; } } 附录5.5 CC2431定位节点代码 /*********************************************************************** // 函数名:static void processMSGCmd(afIncomingMSGPacket_t*pkt) // 功能:接收数据处理 // 输入:接收到的数据 // 输出:无 ***********************************************************************/ static void processMSGCmd(afIncomingMSGPacket_t *pkt) { switch(pkt->clusterId) { case LOCATION_XY_RSSI_REQUEST: //0x0011RSSI数据请求 rspMsg[LOCATION_XY_RSSI_RSSI_IDx] = pkt->LinkQuality; pkt->srcAddr.addrMode = afAddr16Bit; (Void)AF_DataRequest(&pkt->srcAddr,(endPointDeC_t *)&epDesc, LOCATION_XY_RSSI_RESPONSE,LOCATION_Y_RSSI_LEN, spMsg,&transId,0,AF_DEFAULT_RADIUS); break; case LOCATION_BLINDNODE_FIND_REQUEST: //0x0013定位节点发求 if(state == eBnldle defAddr.addrMode = afAddr166Bit; defAddr•addr.shortAddr = pkt->srcAddr.addr.shortAddr; defAddr.endPoint = pkt->srcAddr.endPoint; startBlast(); } break; case LOCATION_BLINDNODE_CONFIG: //0x0016定位节点配置 if(state == eBnIdle){ parseConfig(pkt->cmd.Data);} break; case LOCATION_BLINDNODE_REQUEST_CONFIG: //0x0018定位节点请求配置 sendConfig(&(pkt->srcAddr)); break; case LOCATION_XY_RSSI_RESPONSE: //0x0012 RSSI应答 if(state == eBnBlastIn{ uint8 idx; for(idx=0;idx<BLINDNODE_MAX_REF_NODES;idx++) { if((refNodes[idx].add == INVALID_NODE_ADDR)|| (refNodes[idx].add == pkt->srcAddr.addr.shortAddr)) { refNodes[idx].addr = pkt->srcAddr.addr.shortAddr; refNodes[idx].ep = pkt->srcAddr.endPoint; refNodes[idx].x = BUILD_UINT16( pkt->cmd.Data[LOCATION_XY_RSSI_X_LO_IDX], pkt->cmd.Data[LOCATION_XY_RSSI_X_HI_IDX]); refNodes[idx].y = BUILD_UINT16( pkt->cmd.Data[LOCATION_XY_RSSI_Y_LO_IDX], pkt->cmd.Data[LOCATION_XY_RSSI_Y_HI_IDX]); refNodes[idx].rssi = pkt->cmd.Data[LOCATION_XY_RSSI_RSSI_IDX]; if(rspCnt <= idx) { rspCnt:idx+l;} break; } } }break; default: break; } } /************************************************************************** //函数名:static void parseConfig(uint8 *msg)// 功能:定位节点请求配置响应函数,发送自己的配置参 // 输入:接收到的数据 // 输出:无**************************************************************************/ static afStatus_t sendConfig(afAddrType_t *dstAddr) { uint8 msg[BLINDNODE_CONFIG_LEN]; msg[BLINDNODE_CONFIG_A_IDX] = config.10c.param_a; msg[BLINDNODE_CONFIG_N_IDX] = config.10c.param_n; msg[BLINDNODE_CONFIG_MODE_IDX] = config.mode; msg[BLINDNODE_CONFIG_COLLECT_TIME_LO_IDX] = L0_UINTl6(config.timeout/BN_TIME_INCR); msg[BLINDNODE_CONFIG_COLLECT_TIME_HI_IDX] = HI_UINTl6( config.timeout/BN_TIME_INCR); Config.dstAddr = \BUILD_UINTl6(msg[BLINDNODE_CONFIG_REPORT_SADDR_LO_IDX], msg[BLINDNODE_CONFIG_REPORT_SADDR_HI_IDX]);config.dstEp = msg[BLINDNODE_CONFIQREPORT_EP_IDX] config.minRefNodes = msq[BLINDNODE_CONFIG_MIN_REFNODES_IDX];//配置最小计算参考节点 osal_nv_write(LOC_NV_BLINDNODE_CONFIG,0,sizeof(BN_Cfg_t), &config); if(config.mode = NODE_MODE_AUTO) {osal_set_event(BlindNode_TaskID, BLINDNODE_FIND_EVT); } } /************************************************************************** //函数名:static void parseConfig(uint8 *msg)// 功能:定位节点请求配置响应函数,发送自己的配置参 // 输入:接收到的数据// 输出:无 **************************************************************************/ static afStatus_t sendConfig(afAddrType_t *dstAddr) { uint8 msg[BLINDNODE_CONFIG_LEN]; msgEBLINDNODE_CONFIG_A_IDX] = config.1oc.param_a;msgEBLINDNODE_CONFIG_N_IDX] = config.1oc.param_n; msgEBLINDNODE_CONFIG_MODE_IDX] = config.mode; msgEBLINDNODE_CONFIG_COLLCT_TIME_LO_IDX] = L0_UINTl6( config.timeout/BN_TIME_INCR); msg[BLINDNODE_CONFIG_COLLECT_TIME HI_IDX] = HI_UINTl6( config.timeout/BN_TIME_INCR); msg[BLINDNODE_CONFIG_CYCLE_LO_IDX] = LO_UINTl6(config.cycle/BN_TIME_INCR); msg[BLINDNODE_CONFIG_CYCLE_HI_IDX] =\HI_UINTl6(config.cycle/BN TIME_INCR); msg[BLINDNODE_CONFIG_REPORT_SADDR_LO_IDX] = LO_UINT16(config.dstAddr); msg[BLINDNODE CONFIG_REPORT_SADDR_HI_IDX] = HI_UINT16(config.dstAddr); msg[BLINDNODE_CONFIG_REPORT_EP_IDX] = config.dstEp; msg[BLINDNODE_CONFIG_MIN_REFNODES_IDX] = config.minRefNodes; return(AF_DataRequest(dstAddr,(endPointDesc_t*)&epDesc, \ LOCATION_BLINDNODE_CONFIG, \ BLINDNODE_CONFIG_LEN,msg, \ &transId,0,AF_DEFAULT_RADIUS)); } /************************************************************************* // 函数名:static void startBlast(void) // 功能:发送RSSI_BLAST请求 // 输人:无 // 输出:无 *************************************************************************/ static void startBlast(void) { uint8 idx; afAddrType_t dstAddr; dstAddr.addr.Mode = afAddrBroadcast; dstAddr.addr.shortAddr = NWK_BROADCAST_SHORTADDR_DEVALL; dstAddr.endPoint = LOCATION_REFNODE_ENDPOINT; if((ZDO_Config_Node_Descriptor.CapabilityFlaqs & CAPINFO_RCVR_ON_IDLE) == 0) { idx = true; ZMacSetReq(ZMacRxOnIdle, &idx); } SampleApp_S1eep(FALSE); for(idx=0; idx<BLINDNODE_MAX_REF_NODES; idx++) { refNodes[idx].addr=INVALID_NODE_ADDR; } (void)AF_DataRequest(&dstAddr, (endPointDesc_t *)&epDesc, \ LOCATION_RSSI_BLAST, 0, NULL, &transId, \ AF_SKIP_ROUTING, 1); rspCnt = 0; blastCnt = BLINDNODE_BLAST_COUNT; state = eBnBlastOut; osal_start_timerEx(BlindNodeTaskID,BLINDNODE_BLAST_EVT, \ BLINDNODE_BLAST_DELAY); } /************************************************************************* //函数名:void locationCalculatePosition(LocRefNode_t*ref,LocDevCfg_t *node) // 功能:计算设备位置 // 输入:参考节点信息 // 输出:节点位置 ***********************************************************************/ #if defined(CC2431) #include “ZComDef.h” #include“LocationEngine.h” #include“hal_mcu.h” #define XREG(addr) ((unsigned char volatile_xdata*)0)[addr] #define REFCOORD XREG(0xDF55) /* 定位引擎 */ #define MEASPARM XREG(0xDF56) /* 定位引擎 */ #define LOCENG XREG(0xDF57) /* 定位引擎 */ #define LOCX XREG(0xDF58) /* 定位引擎 */ #define LOCY XREG(0xDF59) /* 定位引擎 */ #define LOCMIN XREG(0xDF5A) /* 定位引擎 */ //定位引擎使能 #define LOC_ENABLE() do{LOCENG| = OxlO; }while(0) #define LOC DISABLE() do{LOCENG&=~OxlO; }while(0) //定位引擎读参数 #define LOC_PARAMETER_LOAD(on)\ do{ \ if(on)LOCENG| = Ox04; \ else LOCENG& = ~Ox04; \ }while(0) //定位引擎读坐标 #define LOC_REFERENCE_LOAD(on)\ do{ \ if(on)LOCENG | = 0x02; \ else I/)CENG& = ~0x02; \ }while(0)//定位引擎运行 #define LOC_RUN() do{LOENG| = 0x01;}while(0) #define LOC_DONE() (LOCENC&0x08) void locationCalculatePosition(LocRefNode_t*ref,LocDevCfg_t *node) { LocRefNode_t *pRef = ref: const byte stop = ((CHVER == 0x01)?LOC_ENGINE_NODE_CAPACITY_REVB: LOC_ENGINE_NODE_CAPACITY_REVC); byte idx; LOC_DISABLE(); //#define LOC_DISABLE()do{LOCENG& = ~Oxl0;}while(0) LOC_ENABLE(); //#define LOC_ENABLE() do{LOCENG |= 0x10;}while(0) //读参考节点坐标 LOC_REFERENCE_LOAD(TRUE); for(idx = 0;idx<stop;idx++) { NEFCOORD = pRef->x; REFCOORD = pRef->y; pRef++; } LOC_REFERENCE_LOAD(FALSE); //读标准参数 LOC_PARAMETER_LOAD(TRUE); MEASPARM = Node->param_a; MEASPARM = Node->param_n; if(CHVER! = Ox01) { MEASPARM=LOC ENGINE_X_MIN; //0 MEASPARM=LOC_ENGINE_X_MAX; //25s MEASPARM=LOC_ENGINE_Y_MIN; //0 MEASPARM=LOC_ENGINE_Y_MAX; //256 } //读RSSI值 for(idx = 0;idx<stop;idx++) { MEASPARM = ref->rssi*2; ref++; } LOC_PARAMETER_LOAD(FALSE); //关闭读标准参数 noc RUN(); //开始计算 while(!(LOCENG&0x08)); if(CHVER == 0x01) { node->x = (LOCX<<1); node->y = (noc7<(1); node->min= LOCMIN; } else { node->x = LOCX+2; node->y = LOCY node->rain= 0; } LOC_DISABLE(); //定位引擎关闭 } #endif //CC2431 /************************************************************************* // 函数名:static afStatus_t sendRsp(void) // 功能:计算设备位置 // 输入:参考节点信息// 输出:节点位置 *************************************************************************/ satic afStatus_t sendRsp(void) { uint8 msq[BLINDNODE_RESPONSE_LEN+2];intl6 temp; LocRefNode_t locNodes[BLINDNODE_MAX_REF_NODES]; uintl6 x0ff, yOff; uint8 idx, cnt = 0; temp = HalAdcRead(0x0e,Ox04); msg[13] = temp_hil3(temp); msg[14] = temp_lol3(temp); for(idx = 0;idx<rspCnt;idx++) { BLINDNODE_CONV_RSSI(refNodes[idx].rssi); if(refNodes[idx].rssi!=0) { cnt++; } } if(cnt >= config.minRefNodes) { msg[BLINDNODE_RESPONSE_STATUS_IDx] = \ BLINDNODE_RSP_STATUS_SUCCESS; rspCnt = sortNodes(refNodes); calcOffsets(refNodes,&x0ff,&y0ff); setLogicals(1ocNodes,refNodes,x0ff,y0ff); //运行定位引擎 locationCalculatePosition(1ocNodes,&(config.loc)); xOff += config.1oc.x; yoff += config.1oc.y; if(((xOff>xOld)&&((xOff - (01d)>BLINDNODE FLUSH)) || ((xOff<xOld) && ((xOld-xOff)>BLINDNODE_FLUSH)) || ((y0ff>yOld) && ((y0ff-y0ld)>BLINDNODE_FLUSH)) || ((yOff<yOld) && ((yOld-yOff)>BLINDNODE_FLUSH)))) { xOld = xoff; yOld = yoff; } else { xOld = ((xOld * (BLINDNODE_FILTER - 1)) + xOff)BLINDNODE_FILTER; yOl = ((yOld * (BLINDNODE_FILTER - 1)) + yOff)/BLINDNODE_FILTER; } xOff = (uintl6)xOld; yOff = (uintl6)yOid; } else { msg[BLINDNODE_RESPONSE_STATUS_IDX] = \ BLINDNODE_RSP_STATUS_NOT_ENOUGH_REFNODES; xOff = (uintl6)xOld; yoff = (uintl6)yOld; } rspMsg[REFNODE_CONFIG_X_LO_IDX] = \ msg[BLINDNODE_RESPONSE_X_LO_IDX] = L0_UINT16(xOff); rspMsg[REFNODE_CONFIG_X_HI_IDX] = msg[BLINDNODE_RESPONSE_X_HI_IDX] = HI_UINTl6(xOff); rspMsg[REFNODE_CONFIG_y_LO_IDX] = msg[BLINDNODE_RESPONSE_Y_LO_IDX] = L0_UINT16(yoff); rspMsg[REFNODE_CONFIG_Y_HI_IDX] = msg[BLINDNODE_RESPONSE_Y_HI_IDX] = HI_UINT16(yOff); msg[BLINDNODE_RESPONSE_NUMREFNODES_IDX] = cnt; if(rspCnt != 0) { msg[BLINDNODE_RESPONSE_REF_SHORTADDR_LO_IDX] =LO_UINT16(refNodes->addr); msg[BLINDNODE_RESPONSE_REF_SHORTADDR_HI_IDX] = \ HI_UINT16(refNodes->addr); msg[BLfNDNODE_RESPONSE_REF_X_LO_IDX] = LO_UINTl6(refNodes->x); msg[BLINDNODE_RESPONSE_REF_X_HI_IDX] = HI_UZNT16(refNodes->x) msq[BLNDNODE_RESPONSE_REF_Y_LO_IDX] =LO_UZNT16(refNodes->y); msg[BLINDNODE_RESPONSE_REF_y_HI_IDX] = HI_UINT16(refNodes->y); msg[BLINDNODE_RESPONSE_REF_RSSI] = refNodes->rssi; } else { msg[BLINDNODE_RESPONSE_REF_SHORTADDR_LO_IDX] = \ LO_UINT16(INVALID_NODE_ADDR); msg[BLINDNODE_RESPONSE_REF_SHORTADDR_HI_IDX] = \ HI_UINT16(INVALID_NODE_ADDR); msg[BLINDNODE_RESPONSE_REF_X_LO_IDX] = \ LO_UINT16(LOC_DEFAULT_X_Y); msg[BLINDNODE_RESPONSE_REF_X_HI_IDX] = \ HI_UINT16(LOC_DEFAULT_X_Y); msg[BLINDNODE_RESPONSE_REF_Y_LO_IDX] = \ LO_UINT16(LOC_DEFAULT_X_Y); msg[BLINDNODE_RESPONSE_REF_Y_HI_IDX] = \ HI_UINT16(LOC_DEFAULT_X_Y); msg[BLINDNODE_RESPONSE_REF_RSSI] = 0xFF; } #endif osal_start_timerEx(BlindNode_TaskID, BLINDNODE_WAIT_EVT, 1000); // 时间片 return(AF_DataRequest(&defAddr, (endPointDesc_t *)&epDesc, LOCATION_BLINDNODE_FIND_RESPONSE, \ BLINDNODE_RESPONSE_LEN + 2, msg, &transId, 0, AF_DEFAULT_RADIUS); } 附录5.6 ZigBee协议协调器操作代码 /*************************************************************************// 函数名:static void LocDongle_ProcessMSGCmd(afIncomingMSGPacket_t *plt) // 功能:处理各个节点的数据 // 输入:各个节点的数据 // 输出:给PC机输入数据 *************************************************************************/ static void LocDongle_ProcessMSGCmd(afIncomingMSGPacket_t *plt) { #if defined(ZBIT) switch(pkt->clusterld) { case LOCATION BLINDNODE_RESPONSE: //定位节点回答 case LOCATION_BLINDNODE_CONFIG: //定位节点配置 blindNodes[0].addr = pkt->srcAddr.Addr.shortAddr; blindNodes[0].ep = pkt->srcAddr.endpoint; break; default: break; } #else #include“SPIMgr.h” //所有引入信息从串口发送 uintl6 cmd = SPI_RESPONSE_BIT|SPI_CMD_SYS APP_MSG; //DstEP + SrcAddr + SrcEP + cld + len = l+2+1+2+1 uint8 buf[SPI_0DATA_MSG_LEN+7]; uint8 *pBuf = buf; uint8 *nATA_XY; uint8 succ = FALSE; *pBuf++ = SOP_VALUE; //操作系统值0x02 *pBuf++ = (uint8)(HI_UINTl6(cmd)); //OxlO *pBuf++ = (uint8)(LO_UINTl6(cmd)); //0x18 *pBuf++ = pkt- >cmd.DataLength + 7; //数据长度 *pBuf++ = LOCATION_DONGLE_ENDPOINT; //0xCB *pBuf++ = L0_UINTl6(pkt->srcAddr.addr.shortAddr); *pBuf++ = HI_UINTl6(pkt->srcAddr.addr.shortAddr); //网络地址 *pBuf++ = pkt->srcAddr.endPoint; //终端地址 *pBuf++ = LO_UINTl6(pkt->clusterId); //串ID *pBuf++ = HI_UINTl6(pkt->clusterId); *pBuf++ = pkt->cmd_DataLength; //坐标数据长度 DATA_XY = Pkt->cmd Data; if(HalUARTWrite(SPI_MGR_DEFAULT_PORT,buf,11)) { if(RalUARTWrite(SPI_MGR_DEFAULT_PORT,pkt->cmd.Data, \ pkt->cmd.DataLength)) { Cmd = SPIMgr_CalcFCS(buf+1,10)^SPIMgr_CalcFCS(pkt->cmd.Data, \ pkd->cmd.DataLength); //去除buf第一位操作系统值,然后进行异或校验。 if(HalUARTWrite(SPI_MGR_DEFAULT_PORT,(uint8 * )(&cmd),1)) { SUCC=TRUE; //发送校验位 } } }#endif } /*************************************************************************// //函数名:byte SPIMgr_CalcFCS(uint8 *msg_ptr,uint8 len //功 能:对各位异或计算,校验计算 // 输入:节点各位的数据 // 输出:校验值 ************************************************************************/ byte SPIMgr_CalcFCS(uint8 *msg_ptr,uint8 len) { byte x; byte xorResult; xorResult = 0; for(x = 0;x<len; x++,msg_ptr++) xorResult = xorResult^ *msg_ptr; //异或计算 return (xorResult); //返回校验值 } /************************************************************************* //函数名:byte SPIMgr_CalcFCS(uint8 *msg_ptr,uint8 len) // 功能:接收处理串口数据 // 输人:节点各位的数据 // 输出:无 *************************************************************************/ void SPIMgr_ProcessZToolData(uint8 port,uint8 event) { uint8 ch; /*校验时间*/ if(event == HAL_UART_TX_FULL) { return; } if(event&(HAL_UART_RX_FULL | \ HAL_UART_Rx_AB0uT_FuLL | \ HAL_UART_RX_TIMEOUT)) { while(HAL_UART_RxBufLen(SPI_MGR_DEFAULT_PORT)) { HalUARTRead(SPI_MGR_DEFAULT_PORT,&ch,1); switch(state) { case SOP_STATE: if(ch == SOP_VALUE) //比较第一位是否为操作系统值 state = CMD_STATEl; break; case CMD_STATEl: CMD_Token[0] = ch; state = CMD_STATE2; break; case CMD_STATE2: CMD_Token[1] = ch; state = LEN_STATE; break; case LEN_STATE: LEN_Token = ch; // 有效数据长度 if(ch == O) state = FCS_STATE; else state = DATA_STATE; // 数据开始 tempDataLen = 0; /* 分配闪存 */ SPI_Msg = (mtOSALSerialData_t *)osal_msg_allocate( \ sizeof(mt0SALSerialData_t) + 2 + 1 + LEN_Token); if(SPI_Msg) { SPI_Msg->hdr.event = CMD_SERIAL_MSG; SPI_Msg->msg = (uint8 *)(SPI_Msg + 1); SPI_Msg->msg[0] = CMD_Token[0]; SPI_Msg->msg[1] = CMD_Token[1]; SPI_Msg->msg[2] = LEN_Token; } else { state = SOP_STATE; return; } break; case DATA_STATE: SPI_Msg->msg[3 + tempDataLen++] = ch; // 放置串口有效数据 if(tempDataLen == LEN_Token) state = FCS_STATE; break; case FCS_STATE: FSC_Token = ch; /* 确定它是正确的 */ if((SPIMgr_CalcFCS((uint8 *)&SPI_Msg->msg[0], \ 2 + 1 + LEN_Token) == FSC_Token)) { osal_msg_send(MT_TaskID, (byte *)SPI_Msg); } else { /* 分派信息 */ osal_msg_deallocate((uint8 *)SPI_Msg); } /* 复位状态,发送或丢弃buffer里面的数据 */ state = SOP_STATE; break; default: break; } } } } #endif // ZTOOL /************************************************************************* // 函数名:static void LocDongle_MTMsg(uint8 len,uint8”“。g) // 功能:根据命令发送PC机数据包括,RSSI请求、参考节点配置、定位节点配置 // 输入:Pc信息。 0 - 目的地址低位 1 - 目的地址高位 2 - endpoint 3 - 串ID低位 4 - 串ID高位 5 - 数据长度 6 - 数据第一位 // 输出:无 *************************************************************************/ static void LocDongle_MTMsg(uint8 len, uint8 * msg) { afAddrType_t dstAddr; cId_t clusterID; uint8 dataLen; dstAddr.addr.Mode = afAddrl6Bit; // 短地址发送 dstAddr.addr.shortAddr = BUILD_UINTl6(msg[O], msg[1]); // 短地址 msg += 2; dstAddr.endPoint = *msg++; clusterID = BUILD_UINTl6(msg[O], msg[1]); msg += 2; dataLen = *msg++; if((clusterID == LOCATION_XY_RSSI_REQUEST) || (clusterID == LOCATION_REFNODE_CONFIG) || (clusterID == LOCATION_REFNODE_REQUEST_CONFIG)) { dstAddr.endPoint = LOCATION_REFNODE_ENDPOINT; } else { dstAddr.endPoint = LOCATION_BLINDNODE_ENDPOINT; }/* 发送数据 */ (void)AF_DataRequest(&dstAddr, (endPointDesc_t *)&epDesc, clusterlD, dataLen, msg, &LocDongle_TransID, 0, AF_DEFAULT_RADIUS); 附录5.7 CC1110 AP节点代码(略) 附录5.8 CC1110 ED节点代码(略) 附录6 实物图(略)

作品图片

  • 无线网络机器人监控系统
  • 无线网络机器人监控系统
  • 无线网络机器人监控系统
  • 无线网络机器人监控系统
  • 无线网络机器人监控系统

作品专业信息

设计、发明的目的和基本思路、创新点、技术关键和主要技术指标

为解决机器人有线监控网络布线繁琐,维护困难,监控范围受到限制等不足,本作品借助ZigBee无线网络将机器人群进行组网,并以SimpliciTI网络作为补充,实现PC端与无线机器人网络无线链接,达到系统同步运行、多机协同作业。每个机器人可以搭载多种传感器与控制设备,既可独立完成各项功能,也可将采集各种数据传回PC机控制端。PC机可以实现对任意机器人精确定位、目标跟踪、实时监控操纵等功能。 本作品的技术关键,一是要将大量的传感器模块组成无线网络,并通过PC机控制端进行控制和数据传输;二是要将在监控范围内工作的机器人整合入网,实现无线定位并对其进行远程无线监视和操纵。 经测试:在电池电压为12V,室内环境,被控小车的前后左右等动作灵敏度发出命令到动作时间平均为0.8S;定位精度在室内的环境与主通信节点距离小于20米,大约为4cm;在室内复杂环境,视频图像掉帧现象不明显,图像实时完整性;视频的最大传输值平均为7Mb/s;通信误码率<1/10000;RSSI的瞬时值为sum(I2+Q2);RSSI的平均值为sum(RSSI(瞬时))/8192;信噪比(SNR)为60dB-75dB。 本系统可以既是一个自主的人工智能系统,也是一个可远程无线人工操纵系统,利用远程监控克服了全人工智能无法应对突发情况的缺点,将人工智能和人工干预相结合,大大加强了系统的灵活性与复杂环境的适用性。可以普遍应用于工厂、车站物流运输,小区安防巡逻、医疗护理、高危场所作业等领域。

科学性、先进性

本作品的先进性体现在:利用无线传感器网络通信及其定位技术,完成区域环境远程无线监控,并在此基础上建立对在其范围内工作的多个机器人组网,以期可以达到对各机器人无线定位,远程无线监视操纵目标,协助操控人员方便快捷地对机器人群进行监视和操纵,从而完成各项任务。 本作品的科学性体现在:基于Zigbee无线传感器网络及其定位技术和SimpliciTI通信网络可以将传统的机器人组网并与控制人员远程干预有效地无线结合,相对以往GPS、LPS定位方式和有线通信相比,不仅设备价格低,环境架设容易,网络适应性强,操控灵活实用性强的特点。 Zigbee无线传感器网络工作在ISM频段,2.4GHz频段数据传输速率为250Kb/s,并且具有长距离、低功耗,其发射输出功率为0~3.6dBm,通信距离为30~70m,节点长地址码为64bit,有着在极大的网络容量。SimpliciTI小型通信网络作为其的补充,具有与其相类似的特征。

获奖情况及鉴定结果

1、本作品在2008年取得第一批湖南省大学生研究学习和创新性实验计划项目(一万元经费支持)。 2、作品正在科技厅等相关部门进行技术成果鉴定。

作品所处阶段

实验室阶段。 实物作品已经完成,进行调试修改。

技术转让方式

正在和相关厂家联系技术转让。

作品可展示的形式

实物、产品;模型;图纸;磁盘;现场演示;图片;录像;样品。

使用说明,技术特点和优势,适应范围,推广前景的技术性说明,市场分析,经济效益预测

作品“无线网络机器人监控系统”使用操作可以分为两个部分,第一部分为网络节点部署,在布网时要考虑传感器节点的位置并且将定位节点和通信节点安装于机器人外侧,PC监控端要与无线网关相连接调试实现网络畅通。第二部分为代码下载与软件安装,将机器人运动操控代码下载入控制器,将上位机软件安装于PC监控端。调试成功之后便可运行监控程序,实现对环境与机器人的无线监控。 本作品将目前热门的无线网络传感器技术和无线信号定位技术与机器人技术相结合,不仅实现了多个机器人同步协调工作,并且利用无线传感器网络实现对各机器人的定位,以及实现远程无线监控与操纵。可以实现多个机器人实时有效监控,使得用于车站、机场行李安放托运,工厂原料、成品调运装配,货场物流,以及安防巡逻领域的机器人可以同步。不仅可以替代原有工作人员节省了人力资源,使得操控人员既可从实时监控中解脱亦可及时处理对机器人进行远程控制,有极好的应用前景。

同类课题研究水平概述

在科技飞速发展的今天,机器人技术取得了长足的进步。通过多种传感器信息的综合,配合高速的微控制器使得机器人智能化、独立化。随着对机器人应用的广泛,针对机器人的监控与定位要求也逐渐提高。 目前针对机器人的监控大体可以分为两类,一类是远程有线监控,一类是近距离的无线视频监视。这两类监控技术均有自身的优势但也有不足。总体上来说目前的监控技术或是没有摆脱电缆的束缚,或是只能依靠短距离的无线视频来达到监视的目的,并未真正做到无线网络的构建完成无线操纵与定位的目标。正是基于以上考虑,将无线传感器网络技术与机器人技术相结合,充分利用了无线传感器网络数据传输与定位技术,将机器人整合入网,并且可以对多个机器人进行监控。国外研究无线传感器监控网络与定位技术较国内发展要早,国内的研究大都处于起步阶段,针对机器人的应用研究也在起步阶段。 目前的机器人的位置测定方面大都依赖于LPS等定位方式。利用Zigbee无线传感器网络组成的定位系统就体现出明显的技术优势和价格优势。和传统的定位方式相比,该方案不仅所使用的设备价格低,通信定位范围大,而且免去了繁琐的布线工作,使得定位系统架设快捷便利,维护简单。此外,Zigbee无线传感器网络通过组网完成无线数据传输功能可以进一步加强对机器人的控制,甚至可以同时与多个机器人进行数据交互,实现对机器人群远程无线操纵。使得操控人员方便快捷地对机器人群进行监视和操纵,从而完成各项任务。 本系统可以分成机器人工作终端、无线传感器监测网络和PC监控终端,通过ZigBee无线通信网络和将三者连接起来,将机器人工作终端和PC监控终端都纳为无线通信网络中的一部分。机器人工作终端以可移动平台为载体,搭载多种传感器和自动化设备,实现对数据的采集以及动作的完成;PC监控终端由一个无线网关和计算机组成,负责启动建立一个新的网络以及维护现有的网络,从而保证数据可以在三者之间顺利传输,完成计算机对整个网络的数据采集与指令广播;传感器监控网络是由大量的监测节点构成,监测节点携带了所需要的传感器,用于收集机器人发送的位置信息、机器人工作环境信息等。 本设计将大量的传感器模块组成无线网络,并在PC机控制端得到其广播的数据,可以将在监控范围内工作的机器人整合入网,实现无线定位并对其进行远程无线监视和操纵。 本作品具有国内先进水平。
建议反馈 返回顶部
点击关闭 点击关闭