CESIUM:如何从俯仰,滚转,航向中为飞机制作动画?

时间:2017-04-13 09:55:52

标签: quaternions cesium euler-angles czml

我的飞行数据包含位置(纬度,经度,高度)和方向(俯仰,滚转,航向)随时间的变化。

我想代表CesiumJS的飞机。

我尝试根据航班数据创建CZML文件。一切都运作良好的位置。但是CZML格式仅支持基于地球固定轴参考中的四元数的方向。 这意味着我必须为每个位置,俯仰,滚动,航向预处理这个四元数,以便编写CZML。

你认为我应该实现这个四元数计算(不是直接的)吗?

或者我应该使用另一种解决方案来使用铯功能,让我直接使用俯仰,滚动,航向值?在这种情况下,我想知道我可以使用哪种格式将我的航班数据传输到Cesium。

感谢您的建议

4 个答案:

答案 0 :(得分:1)

我自己没有试过这个,但应该可以将飞机航向/俯仰/滚转(在已知飞机位置的局部轴上)转换为地球固定的四元数,仅使用附带的数学函数铯。

这里需要两个转换,一个是四元数的标题 - 俯仰 - 滚动,另一个是地球固定的局部轴。

  1. 将简单的heading-pitch-roll转换为Quaternion,用Quaternion.fromHeadingPitchRoll完成。这是一件容易的事,已经完成了。保存此结果以供日后使用。
  2. 现在我们需要本地修复地球。

    1. 使用Transforms.eastNorthUpToFixedFrame。这会考虑到位置,但会以Matrix4的形式为您提供超出您需要的位置。

    2. 使用Matrix4.getRotation从Matrix4获取旋转。这剥离了变换偏移(地对空)并产生仅包含旋转偏移的Matrix3。

    3. 使用Quaternion.fromRotationMatrix将Matrix3转换为四元数。

    4. 现在您有2个四元数,一个来自第1步,另一个来自第4步。

      1. 使用Quaternion.multiply将两个四元数相乘。这里的结果应该是您需要的答案。
      2. 我希望我的数学是正确的。祝你好运!

答案 1 :(得分:0)

解决方案似乎是使用带有四元数的sampledProperty。 这里有解释:https://groups.google.com/forum/#!topic/cesium-dev/gb4HdaTTgXE

我还没试过,但是当我成功的时候,我会发布解决方案。

答案 2 :(得分:0)

我找到了如何根据时间函数定位基于俯仰,滚转,航向值的模型。遗憾的是官方网站上没有与Cesium.Quaternion一起使用的SampledProperty的文档。在sandCastle中也没有示例。

我修改了几行代码示例以说明铯中的方向可能性(在Cesium sandCastle中复制/粘贴HTML和JAVASCRIPT选项卡中的代码。在此示例中,只有标题采用不同的值,但您可以使用俯仰和滚动太

HTML CODE:

<style> 
    @import url(../templates/bucket.css); 
</style> 
<div id="cesiumContainer" class="fullSize"></div> 
<div id="loadingOverlay"><h1>Loading...</h1></div> 
<div id="toolbar"> 
    <div id="interpolationMenu"></div> 
</div> 

JAVASCRIPT CODE:

var viewer = new Cesium.Viewer('cesiumContainer', { 
    terrainProviderViewModels : [], //Disable terrain changing 
    infoBox : false, //Disable InfoBox widget 
    selectionIndicator : false //Disable selection indicator 
}); 

//Enable lighting based on sun/moon positions 
viewer.scene.globe.enableLighting = true; 

//Use STK World Terrain 
viewer.terrainProvider = new Cesium.CesiumTerrainProvider({ 
    url : 'https://assets.agi.com/stk-terrain/world', 
    requestWaterMask : true, 
    requestVertexNormals : true 
}); 

//Enable depth testing so things behind the terrain disappear. 
viewer.scene.globe.depthTestAgainstTerrain = true; 

//Set the random number seed for consistent results. 
Cesium.Math.setRandomNumberSeed(3); 

//Set bounds of our simulation time 
var start = Cesium.JulianDate.fromDate(new Date(2015, 2, 25, 16)); 
var stop = Cesium.JulianDate.addSeconds(start, 360, new Cesium.JulianDate()); 

//Make sure viewer is at the desired time. 
viewer.clock.startTime = start.clone(); 
viewer.clock.stopTime = stop.clone(); 
viewer.clock.currentTime = start.clone(); 
viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP; //Loop at the end 
viewer.clock.multiplier = 10; 

//Set timeline to simulation bounds 
viewer.timeline.zoomTo(start, stop); 




var lon = 0; 
var lat = 45; 
var radius = 0.03; 

//Generate a random circular pattern with varying heights. 

    var positionProperty = new Cesium.SampledPositionProperty(); 
    var orientationProperty = new Cesium.SampledProperty(Cesium.Quaternion); 

    for (var i = 0; i <= 360; i += 45) { 
        var radians = Cesium.Math.toRadians(i); 
        var time = Cesium.JulianDate.addSeconds(start, i, new Cesium.JulianDate()); 

        // compute positions 
        var position = Cesium.Cartesian3.fromDegrees(lon + (radius * 1.5 * Math.cos(radians)), lat + (radius * Math.sin(radians)), Cesium.Math.nextRandomNumber() * 500 + 1750); 
        positionProperty.addSample(time, position); 

        // compute orientations 
        var heading = Cesium.Math.toRadians(90+i); 
        var pitch = Cesium.Math.toRadians(20); 
        var roll = Cesium.Math.toRadians(0);       
        var hpRoll = new Cesium.HeadingPitchRoll(heading,pitch,roll);   
        var orientation = Cesium.Transforms.headingPitchRollQuaternion(position,hpRoll); 
        orientationProperty.addSample(time, orientation); 

        //Also create a point for each sample we generate. 
        viewer.entities.add({ 
            position : position, 
            point : { 
                pixelSize : 8, 
                color : Cesium.Color.TRANSPARENT, 
                outlineColor : Cesium.Color.YELLOW, 
                outlineWidth : 3 
            } 
        }); 
    } 


//Actually create the entity 
var entity = viewer.entities.add({ 

    //Set the entity availability to the same interval as the simulation time. 
    availability : new Cesium.TimeIntervalCollection([new Cesium.TimeInterval({ 
        start : start, 
        stop : stop 
    })]), 

    //Use our computed positions 
    position : positionProperty, 

    //Automatically compute orientation based on position movement. 
    orientation : orientationProperty, 

    //Load the Cesium plane model to represent the entity 
    model : { 
        uri : '../../SampleData/models/CesiumAir/Cesium_Air.gltf', 
        minimumPixelSize : 64 
    }, 

    //Show the path as a pink line sampled in 1 second increments. 
    path : { 
        resolution : 1, 
        material : new Cesium.PolylineGlowMaterialProperty({ 
            glowPower : 0.1, 
            color : Cesium.Color.YELLOW 
        }), 
        width : 10 
    } 
}); 

//Add button to view the path from the top down 
Sandcastle.addDefaultToolbarButton('View Top Down', function() { 
    viewer.trackedEntity = undefined; 
    viewer.zoomTo(viewer.entities, new Cesium.HeadingPitchRange(0, Cesium.Math.toRadians(-90))); 
}); 

//Add button to view the path from the side 
Sandcastle.addToolbarButton('View Side', function() { 
    viewer.trackedEntity = undefined; 
    viewer.zoomTo(viewer.entities, new Cesium.HeadingPitchRange(Cesium.Math.toRadians(-90), Cesium.Math.toRadians(-15), 7500)); 
}); 

//Add button to track the entity as it moves 
Sandcastle.addToolbarButton('View Aircraft', function() { 
    viewer.trackedEntity = entity; 
}); 

//Add a combo box for selecting each interpolation mode. 
Sandcastle.addToolbarMenu([{ 
    text : 'Interpolation: Linear Approximation', 
    onselect : function() { 
        entity.position.setInterpolationOptions({ 
            interpolationDegree : 1, 
            interpolationAlgorithm : Cesium.LinearApproximation 
        }); 
    } 
}, { 
    text : 'Interpolation: Lagrange Polynomial Approximation', 
    onselect : function() { 
        entity.position.setInterpolationOptions({ 
            interpolationDegree : 5, 
            interpolationAlgorithm : Cesium.LagrangePolynomialApproximation 
        }); 
    } 
}, { 
    text : 'Interpolation: Hermite Polynomial Approximation', 
    onselect : function() { 
        entity.position.setInterpolationOptions({ 
            interpolationDegree : 2, 
            interpolationAlgorithm : Cesium.HermitePolynomialApproximation 
        }); 
    } 
}], 'interpolationMenu'); 

答案 3 :(得分:0)

我建议使用此功能Cesium.Transforms.headingPitchRollQuaternion()。参数是关于本地hpr的,而不是地球固定轴参考中的四元数。然后,您无需进行更改。

我猜您使用的是Cesium.Quaternion.fromHeadingPitchRoll。 希望这会有所帮助。