5

I have flight data containing position (lat,lon,height) and orientation (pitch, roll, heading) in function of time.

I would like to represent the aircraft in CesiumJS.

I tried to create CZML file from the flight data. Everything worked fine for the position. But CZML format support only orientation based on a quaternion in the reference of Earth fixed axes. That means I would have to preprocess this quaternion for each position, pitch, roll, heading in order to write the CZML.

Do you think I should implement this quaternion computation (not straight forward) ?

Or should I use another solution to use cesium functions that allow me to use directly pitch, roll, heading values ?. In this case, I wonder which format I can use to transfer my flight data to Cesium.

Thank you for your advices

4

4 回答 4

3

我发现了如何根据时间函数中的俯仰、滚动、航向值来定位模型。可惜官网没有关于SampledProperty与Cesium.Quaternion一起使用的文档。沙堡也没有例子。

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

HTML 代码:

<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代码:

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'); 
于 2017-04-27T13:15:15.793 回答
3

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

您需要在这里进行两种转换,一种是航向俯仰滚动到四元数,另一种是本地轴到地球固定。

  1. 将简单的航向俯仰滚动转换为四元数,这是通过Quaternion.fromHeadingPitchRoll完成的。这是最简单的部分,它已经完成了。保存此结果以备后用。

现在我们需要本地到地球固定。

  1. 使用Transforms.eastNorthUpToFixedFrame。这考虑了位置,但以 Matrix4 的形式为您提供了比您需要的更多。

  2. 使用Matrix4.getMatrix3从您的 Matrix4 获取旋转。这会去除变换偏移(地对飞机)并产生一个仅包含旋转偏移(和比例)的 Matrix3,但这应该只是我们在上一步中获得该矩阵的位置给出的恒等比例,所以我们可以放心地认为这仅作为旋转)。

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

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

  1. 使用Quaternion.multiply将两个四元数相乘。这里的结果应该是你需要的答案。

我希望我的数学是正确的。祝你好运!

于 2017-04-13T14:30:34.687 回答
0

我建议这个功能Cesium.Transforms.headingPitchRollQuaternion()。这些参数是关于局部 hpr 而不是地球固定轴参考中的四元数。然后你不需要做改变。

我猜你用这个:Cesium.Quaternion.fromHeadingPitchRoll. 希望这可能会有所帮助。

于 2020-03-26T15:03:19.993 回答
0

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

我还没有尝试过,但我会在成功时发布解决方案。

于 2017-04-26T17:01:34.913 回答