2017-04-13 605 views
2

我有飛行數據包含時間函數的位置(緯度,經度,高度)和方向(俯仰,滾轉,航向)。CESIUM:如何從俯仰,滾轉,朝向製作飛機動畫?

我想代表飛機在CesiumJS。

我試圖從航班數據中創建CZML文件。一切工作正常的位置。但CZML格式僅支持基於地球固定軸參考中的四元數的方向。 這意味着我將不得不爲每個位置,音高,滾動,標題預處理這個四元數以編寫CZML。

你認爲我應該實現這個四元數計算(不是直截了當的)嗎?

或者我應該使用另一種解決方案來使用銫功能,它允許我直接使用俯仰,滾動,標題值?在這種情況下,我想知道我可以使用哪種格式將我的飛行數據傳輸給Cesium。

謝謝您的建議

+0

銫包括幾個功能,用於將歐拉角來四元數以及從地方上轉換爲地球固定。也許你可以寫一個NodeJS腳本來使用這些函數進行批量轉換? – emackey

+0

thx @emackey所以,你的意思是我可以寫一個NodeJS腳本來使用Cesium函數將節距標題滾動+位置轉換爲四元數? –

+0

我認爲這應該是可能的,是的。我沒有嘗試過自己做。位置保持獨立於航向/俯仰/滾轉。 – emackey

回答

0

我還沒有嘗試過這個自己,但它應該是可以轉換的飛機航向/俯仰/卷(已知的飛機位置的局部軸)到地球固定四元,只使用Cesium附帶的數學函數。

這裏需要兩個轉換,一個是標題 - 俯仰 - 滾動到四元數,另一個是局部軸到地球固定。

  1. 將簡單的標題 - 間距卷轉換爲四元數,這是用Quaternion.fromHeadingPitchRoll完成的。這是很容易的部分,它完成了。稍後保存此結果。

現在我們需要本地固定。

  1. 使用Transforms.eastNorthUpToFixedFrame。這考慮到了位置,但是以Matrix4的形式爲您提供超過您的需求。

  2. 使用Matrix4.getRotation獲取Matrix4的輪換。這剝離了變換偏移(地對飛機)併產生僅包含旋轉偏移的Matrix3。使用Quaternion.fromRotationMatrix將您的Matrix3轉換爲四元數。

現在你有2四元數,一個來自步驟1和另一從步驟4

  • 乘法的兩個四元一起使用Quaternion.multiply。這裏的結果應該是你需要的答案。
  • 我希望我的數學是正確的。祝你好運!

    +0

    謝謝你的回答。我會嘗試用cesium代替czml來設置我的方向。但是,我不明白如何在銫中正確設置方向。對於職位來說,我很容易使用Cesium.SampledPositionProperty(),並給出了時間函數的位置。我怎樣才能按照時間來定位?在下面的例子中,我如何用時間函數中的自己的方向值替換函數new Cesium.VelocityOrientationProperty(position)? https://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=Interpolation.html&label=Showcases –

    0

    我發現如何根據時間的函數基於俯仰,滾轉,航向值來定位模型。遺憾的是,官方網站上沒有與Cesium.Quaternion一起使用的SampledProperty文檔。 sandCastle也沒有例子。

    我修改了幾行代碼示例來說明銫中的方向可能性(在Cesium sandCastle中複製/粘貼HTML和JAVASCRIPT選項卡中的代碼,只有標題在本例中使用不同的值,但您可以使用pitch和滾太

    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'); 
    
    相關問題