欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

铯教程 7 - 轨迹模拟(无人机轨迹模拟飞行)

最编程 2024-04-15 17:50:46
...

先看效果

在这里插入图片描述在这里插入图片描述

航迹模拟-----模拟真实无人机飞行的轨迹和云台的拍摄方向,到达指定的拍摄点返回拍摄点的ID,用于显示对应拍摄点的照片或者视频

实现过程

创建一条轨迹和拍摄点

   /**
     * @param {*} Lines 无人机坐标点和云台的角度的坐标数组
     * @memberof TrackPath
     */
TrackPath(Lines) {
        var lins = [];
        this.dataSource = new Cesium.CustomDataSource('TrackPath');
        for (let i = 0; i < Lines.length; i++) {
            let LinesIndex = new Cesium.Cartesian3.fromDegrees(Lines[i].aircraftLongitude, Lines[i].aircraftLatitude, Lines[i].aircraftAltitude);
            this.dataSource.entities.add({ // 绘制拍摄点位置实体小球
                position: LinesIndex,
                point: {
                    pixelSize: 8,
                    color: Cesium.Color.RED
                },
            });
            lins.push(Lines[i].aircraftLongitude);
            lins.push(Lines[i].aircraftLatitude);
            lins.push(Lines[i].aircraftAltitude);

        }
        this.dataSource.entities.add({ // 绘制线段
            polyline: {
                positions: new Cesium.Cartesian3.fromDegreesArrayHeights(lins),
                width: 2,
                material: Cesium.Color.YELLOW
            }
        })

        this.viewer.dataSources.add(this.dataSource);
        this.ChangePerspective('ViewSide');
    }

设置观看角度,并定位相关位置

    /**
     * 改变观看角度
     * @param {*} name string 
     * ViewTopDown:顶视图
     * ViewSide :正视图
     * trackedEntity:跟随模型
     * @memberof Track
     */
    ChangePerspective(name) {
        if (name === "ViewTopDown") {
            this.viewer.trackedEntity = undefined;
            this.viewer.flyTo( 
                this.dataSource, {
                offset: {
                    heading: 0,
                    pitch: Cesium.Math.toRadians(-90),
                    range: 35
                }
            }
            );
        } else if (name === "ViewSide") {
            this.viewer.trackedEntity = undefined;
            this.viewer.flyTo(
                this.dataSource, {
                offset: {
                    heading: Cesium.Math.toRadians(-90),
                    pitch: Cesium.Math.toRadians(-15),
                    range: 50
                }
            }
            );
        } else if (name === "trackedEntity") {
            this.viewer.trackedEntity = this.entity;
        }

    }

调用new Track().StartFlying() 开始模拟飞行

 StartFlying() {
        this.property = this.ComputeRoamingLineProperty(this.Lines); // 返回每个点的时钟
        this.InitRoaming(this.property.property, this.property.startTime,this.property.stopTime); // 添加无人机模型
    }
 /**
     * @param {*} Lines 点集合
     * @returns 
     * @memberof ComputeRoamingLineProperty
     */
    ComputeRoamingLineProperty(Lines) {
        this.onTickstate = true;
        let startTime = Cesium.JulianDate.fromDate(new Date()); // 创建开始时间
        let stopTime;
        let property = new Cesium.SampledPositionProperty(); // 利用Cesium的 SampledPositionProperty来动态控制模型的位置,达到模型沿轨迹平滑移动的目的
        let startWaiting, endWaiting;
        let Waiting = [];
        for (let i = 0, t = 0; i < Lines.length; i++) { //通过计算出每个拍摄点的时间及停留时间
            if (i == 0) {
                t = 0;
            } else {
                let p1 = new Cesium.Cartesian3.fromDegrees(Lines[i - 1].aircraftLongitude, Lines[i - 1].aircraftLatitude, Lines[i - 1].aircraftAltitude);
                let p2 = new Cesium.Cartesian3.fromDegrees(Lines[i].aircraftLongitude, Lines[i].aircraftLatitude, Lines[i].aircraftAltitude);
                let d = Cesium.Cartesian3.distance(p1, p2);
                t += d / this.speed;
            }
            let LinesIndex = new Cesium.Cartesian3.fromDegrees(Lines[i].aircraftLongitude, Lines[i].aircraftLatitude, Lines[i].aircraftAltitude);
            property.addSample(Cesium.JulianDate.addSeconds(startTime, t, new Cesium.JulianDate()), LinesIndex);

            if (Lines[i].isShoot == true) {
                startWaiting = Cesium.JulianDate.addSeconds(startTime, t, new Cesium.JulianDate())
                t += this.stayTime || 1;
                property.addSample(Cesium.JulianDate.addSeconds(startTime, t, new Cesium.JulianDate()), LinesIndex);
                endWaiting = Cesium.JulianDate.addSeconds(startTime, t, new Cesium.JulianDate())
                Waiting.push({
                    startWaiting,
                    endWaiting,
                    shootId: Lines[i].shootId
                })
            }

            if (i == Lines.length - 1) {
                stopTime = Cesium.JulianDate.addSeconds(startTime, t, new Cesium.JulianDate())
            }

        }

        let k = true
        this.viewer.clock.onTick.addEventListener((e) => { //监听时钟检测是否到达拍摄点位
            if (this.onTickstate) {
                let finds = false
                for (let i = 0; i < Waiting.length; i++) {
                    if (Waiting[i].startWaiting.secondsOfDay < e.currentTime.secondsOfDay && Waiting[i].endWaiting.secondsOfDay > e.currentTime.secondsOfDay) { 
                        if (k) {// 开关变量 避免频繁执行
                            this.shootCallback(Waiting[i].shootId) // 执行拍摄点回调函数
                            this.SetLookCone(Waiting[i].shootId) // 绘制视椎体
                        }
                        finds = true
                        break;
                    }
                }
                if (finds) {
                    k = false
                } else {
                    k = true
                }
            }

        })


        this.viewer.clock.startTime = startTime.clone();
        this.viewer.clock.stopTime = stopTime.clone();
        this.viewer.clock.currentTime = startTime.clone();
        this.viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP;
        this.viewer.clock.multiplier = 1;
        this.viewer.clock.shouldAnimate = true;

        return {
            property,
            startTime,
            stopTime
        }
    }

添加模型

    InitRoaming(position, start, stop) {
        this.entity = this.viewer.entities.add({
            availability: new Cesium.TimeIntervalCollection([new Cesium.TimeInterval({
                start: start,
                stop: stop
            })]),
            // 位置
            position: position,
            // 计算朝向
            // orientation: new Cesium.VelocityOrientationProperty(position),
            // 加载模型
            model: {
                // 模型路径
                uri: "./air.glb",
                // 模型最小刻度
                minimumPixelSize: 64,
                maximumSize: 128,
                // 设置模型最大放大大小
                maximumScale: 200,
                // 模型是否可见
                show: true,
                // 模型轮廓颜色
                silhouetteColor: Cesium.Color.WHITE,
                // 模型颜色  ,这里可以设置颜色的变化
                // color: color,
                // 仅用于调试,显示魔仙绘制时的线框
                debugWireframe: false,
                // 仅用于调试。显示模型绘制时的边界球。
                debugShowBoundingVolume: false,

                scale: 0.02,
                runAnimations: false // 是否运行模型中的动画效果(由于我的模型是不会动所以就很呆哈哈哈)
            },
            path: {
                resolution: 1,
                material: new Cesium.PolylineGlowMaterialProperty({
                    glowPower: 0.1,
                    color: Cesium.Color.RED
                }),
                width: 10,
                show: false
            }
        })
        // 
        // this.viewer.trackedEntity = this.entity

    }

绘制视椎体

SetLookCone(value) {
        // this.RemovePrimitives()
        setTimeout(() => {
            this.RemovePrimitives() //离开拍摄点 删除视椎体
        }, this.stayTime * 1000)

        value = this.Lines.filter(function (item) {// 过滤出是拍摄点的位置
            return item.shootId == value;
        });

        value = value[0]
        let positions = new Cesium.Cartesian3.fromDegrees(value.aircraftLongitude, value.aircraftLatitude, value.aircraftAltitude)
        this.spotLightCamera = new Cesium.Camera(this.viewer.scene);
        let spotLightCamera = this.spotLightCamera

        spotLightCamera.setView({ // 设置视椎体的俯仰角度
            destination: positions,
            orientation: {
                heading: Cesium.Math.toRadians(value.gimbalYawValue),
                pitch: Cesium.Math.toRadians(value.gimbalPitchValue),
                roll: Cesium.Math.toRadians(0.0)
            }
        });



        let scratchRight = new Cesium.Cartesian3();
        let scratchRotation = new Cesium.Matrix3();
        var scratchOrientation = new Cesium.Quaternion();

        let position = spotLightCamera.positionWC;
        let directions = spotLightCamera.directionWC;
        let up = spotLightCamera.upWC;
        let right = spotLightCamera.rightWC;
        right = Cesium.Cartesian3.negate(right, scratchRight);

        let rotation = scratchRotation;
        Cesium.Matrix3.setColumn(rotation, 0, right, rotation);
        Cesium.Matrix3.setColumn(rotation, 1, up, rotation);
        Cesium.Matrix3.setColumn(rotation, 2, directions, rotation);
        //计算视锥姿态
        let orientation = Cesium.Quaternion.fromRotationMatrix(rotation, scratchOrientation);
        spotLightCamera.frustum.near = 0.1;
        spotLightCamera.frustum.far = this.frustumFar;
        // 视锥轮廓线图形
        let instanceOutline = new Cesium.GeometryInstance({
            geometry: new Cesium.FrustumGeometry({
                frustum: spotLightCamera.frustum,
                origin: position,
                orientation: orientation
            }),
            material: Cesium.Color.RED.withAlpha(1),
            id: "pri" + this.viewer.scene.primitives.length + 1,
            attributes: {
                color: Cesium.ColorGeometryInstanceAttribute.fromColor(new Cesium.Color(1.0, 1.0, 0.0, 0.5)),
                show: new Cesium.ShowGeometryInstanceAttribute(true)
            }
        });

        let instance = new Cesium.GeometryInstance({
            geometry: new Cesium.FrustumOutlineGeometry({
                frustum: spotLightCamera.frustum,
                origin: position,
                orientation: orientation
            }),
            material: Cesium.Color.RED.withAlpha(0.1),
            id: "pri0" + this.viewer.scene.primitives.length + 1,
            attributes: {
                color: Cesium.ColorGeometryInstanceAttribute.fromColor(new Cesium.Color(1.0, 0.0, 0.0, 1)),
                show: new Cesium.ShowGeometryInstanceAttribute(true)
            }
        });

        this.primitivesone = this.viewer.scene.primitives.add(new Cesium.Primitive({// 视椎体
            geometryInstances: instance,
            appearance: new Cesium.PerInstanceColorAppearance({
                translucent: true,
                flat: true
            }),
            asynchronous: false
        }));

        this.primitivestwo = this.viewer.scene.primitives.add(new Cesium.Primitive({// 轮廓
            geometryInstances: instanceOutline,
            appearance: new Cesium.PerInstanceColorAppearance({
                translucent: true,
                flat: true
            }),
            asynchronous: false
        }));

    }

以上就是实现航迹模拟的大致过程,详细代码下面,记得点星星不要白嫖哟

代码下载地址: github.com/weshmily/ce…

记得点星星哈

作者: weshmily前端

官网: 百度搜索(weshmily前端)

****博客:blog.****.net/qq_27118895

GitHub: github.com/weshmily

公众号:搜索"weshmilyqd"