Cesium中飞行器姿态控制

问题提出

最近研究开源虚拟地球Cesium,遇到一个问题:在获取飞行器经度纬度高度偏航俯仰滚转六个参数的前提下,如何在Cesium中用CZML文件表示,从而完美实现飞行器姿态轨迹的复现。在CZML的position属性中使用cartographicDegrees表示飞行器的经度纬度高度,可以很好复现飞行器的轨迹。然而在CZML的orientation属性中使用unitQuaternion表示飞机自身姿态时,飞机姿态总是不对。

问题分析

基本知识

在Cesium中存在两种常用坐标系:

  1. 世界坐标系
    世界坐标系统是以椭球中心为原点的笛卡尔空间直角坐标系。
  2. 地理坐标系
    地理坐标系即人们常用的使用经度、纬度、高度表示位置的坐标系。
  3. 站心坐标系
    又称为Earth-fixed coordinate system(站点坐标系、东-北-天坐标系ENU)。可分为站心直角坐标系和站心极坐标系。
    常用的站心直角坐标系定义为:以站心(如GPS接收天线中心)为坐标系原点O,Z轴与椭球法线重合,向上为正(天向),y与椭球短半轴重合(北向),x轴与地球椭球的长半轴重合(东向)所构成的直角坐标系,称为当地东北天坐标系(ENU)。
    飞行器的偏航、俯仰、滚转即是以站心直角坐标系为参考。
  4. 模型坐标系
    模型坐标系以物体的中心为坐标原点,物体旋转、平移等操作都是围绕局部坐标系进行的。这时当物体模型进行旋转、平移等操作时,局部坐标系也执行相应的旋转、平移等操作。
    局部坐标系是一个假想的坐标系,该坐标系与物体的相对位置至始至终是不变的,假想出这个坐标系的目的主要是为了正向理解对三维场景中物体执行的平移和旋转操作。使用局部坐标系理解模型变换时,所有的变换操作直接作用与局部坐标系,由于局部坐标系与物体的相对位置不变,因此对局部坐标系进行平移、旋转和缩放时,物体在场景中位置和形状也会发生相应的变化。

在Cesium中存在两种世界坐标系和地理坐标系之间坐标转换的方法:

1
2
3
4
5
6
7
8
9
# 经纬度转换为世界坐标
Cesium.Cartesian3.fromDegrees(longitude, latitude, height, ellipsoid, result)
# 世界坐标转换为经纬度
var ellipsoid=viewer.scene.globe.ellipsoid;
var cartesian3=new Cesium.cartesian3(x,y,z);
var cartographic=ellipsoid.cartesianToCartographic(cartesian3);
var lat=Cesium.Math.toDegrees(cartograhphic.latitude);
var lng=Cesium.Math.toDegrees(cartograhpinc.longitude);
var alt=cartographic.height;

CZML分析

CZML是一种用来描述动态场景的JSON架构的语言,主要用于Cesium在浏览器中的展示。它可以用来描述点、线、布告板、模型以及其他的图元,同时定义他们是怎样随时间变化的[3]

CZML可使用model属性直接加载3D模型,由position属性决定模型在世界坐标系内的位置,由orientation决定模型在世界坐标系内的姿态,并最终由orientation的unitQuaternion表示。

unitQuaternion即单位四元数,可与偏航俯仰滚转相互转换,并避免偏航俯仰滚转的万向节锁定问题,但其本质上都是一个旋转矩阵,可决定模型在世界坐标系内的姿态。

获取正确的飞行器姿态

首先计算飞行器模型坐标系对站点直角坐标系的旋转矩阵(在制作飞行器3D模型时,应使其中心在本地坐标系原点,机头机翼与轴平行,方便计算在站点直角坐标系内的旋转角度),再乘以由飞行器偏航俯仰滚转得到的旋转矩阵,再乘以站点直角坐标系对世界坐标系的旋转矩阵。将最终得到旋转矩阵转换为单位四元数,即得到正确的飞行器姿态。

小技巧:飞机3D模型的中心设置在本地坐标系原点,机头机翼与轴平行后,可能在Cesium中渲染时姿态还是不对。原因是绕Z轴旋转的角度还是不对。可以在HeadingPitchRoll示例中使用自己的飞机3D模型,参照Cesium给的运输机模型,比较它们之间绕Z轴旋转的差异,然后调整飞机3D模型绕Z轴旋转的角度。

解决方法

参考代码如下:

1
2
3
4
5
6
var lon=113,lat=34;//模型的站心经纬度
var h1=0,p1=0,r1=0;//模型坐标系对站点坐标系的旋转角度
var h2=0,p2=0,r2=0;//模型在站点坐标系的姿态
var center = Cesium.Cartesian3.fromDegrees(lon, lat)
var hpr = new Cesium.HeadingPitchRoll(h1+h2, p1+p2, r1+r2)
var q1 = Cesium.Transforms.headingPitchRollQuaternion(center, hpr)

参考链接

  1. CESIUM : How to animate an aircraft from pitch, roll, heading?, by stackoverflow.
  2. Cesium中的几种坐标和相互转换, by finalLi.
  3. Cesium Language (CZML) 入门1 — CZML Structure(CZML的结构), by laixiangran.
  4. CZML Structure, by AnalyticalGraphicsInc.
  5. 3D坐标系, by S_H_C.
  6. 3D空间的坐标系, by trojanpizza.
  7. cesium获取某个位置垂直于当前地表的垂直坐标系,by 暮志未晚Webgl.
  8. Cesium控制模型旋转2019-11-15,by _____xyz.