当前位置: 首页 > 知识库问答 >
问题:

使用横摇、俯仰、偏航和长度确定新的GPS位置

宋育
2023-03-14

我正在使用Reach RS设备来捕获全球定位系统位置数据以及IMU数据(滚动、俯仰和偏航);参见制造商网站上的“点收集”图像。我试图确定底部点的全球定位系统坐标(接收器固定在杆的空端)。为了能够以米为单位进行计算,我将经度(X)和纬度(Y)转换为UTM,同时保持高度(Z)不变。
当杆直立时,X和Y保持不变

Z1 = Z - ROD_LENGTH  

然而,当杆倾斜时,所有坐标都会受到影响,我需要一种方法来计算杆的末端位置
我已经根据实验观察研究了旋转矩阵、三角形方程、我自己的sin和cos公式,但我没有3D几何的背景,也不知道该走哪条路(例如,我不知道如何使用旋转矩阵中的杆长度)
基本上我需要以下公式:

X1 = X + ROD_LENGTH * func_X(roll, pitch, yaw)
Y1 = Y + ROD_LENGTH * func_Y(roll, pitch, yaw)
Z1 = Z + ROD_LENGTH * func_Z(roll, pitch, yaw)

滚动、俯仰和偏航的值在-180°和180°之间。

共有3个答案

卫君博
2023-03-14

我不认为你的问题恰好是万向节锁,因为你说当杆直立时X和Y是相同的。你确定你已经把惯性测量单元和地面平行放置了吗?我建议首先尝试测量IMU的结果,当你确定它给出准确的结果时,再用RS连接它。

如果你想测量GPS坐标和偏航俯仰滚动,那么我建议使用GPS模块和MPU-6050与Arduino mini。它足够小,可以挂任何东西,而且比非常贵的RS便宜很多。有了这样一个小工具,你会发现比使用RS有更多的支持。

谭云瀚
2023-03-14

目前,我正在测试一个基于three.js的解决方案,它的工作原理如下:

function getCorrectedPosition(x, y, z, dist, roll, pitch, yaw) {
    let matrix = new THREE.Matrix4().makeRotationFromEuler(new THREE.Euler(toRadians(pitch), toRadians(roll), toRadians(yaw)));
    let moveVector = new THREE.Vector3(0, 0, -dist);
    moveVector.applyMatrix4(matrix);
    let position = new THREE.Vector3(z, y, x).add(moveVector);
    return [position.x, position.y, position.z]
}

一旦我有了结果,我会发布带有结果的更新。

傅鸿波
2023-03-14

我必须说,这比我想象的要复杂得多。我想我已经完全明白了,但是请在评论中告诉我任何更正,我会尽力改正。

在您查看代码之前,请注意!这些假设很重要,您需要验证它们在您的情况下是否正确。有几十种(至少!)方法来定义空间中的方向和位置。您需要确保与您的设备对齐的主要假设是我们操作的空间框架。本文将让您了解为什么这如此重要!最明显的是我们如何标记轴,哪条方向是向上的(正Z,正如我在下面选择的,但是如果我们谈论潜艇,例如,我们可能会选择负Z)。

>

  • 框架假设:想象一架飞机(我知道它不是飞机,但这样解释更容易)一根长杆笔直垂下。我们将 Z 轴定义为向上(正)和向下(负)。X 轴指向前(正)和后(负)。Y 轴是围绕机翼的旋转轴,左翼为正,右翼为负 - 这是一个“右手坐标系”。因此,轴相交大致位于飞机的中间,大致是连接机翼的地方。旋转定义为绕轴逆时针旋转以获得正角度,顺时针旋转为负。所以。。。

      < li >“偏航”代表绝对航向的变化(因此,即使您俯仰和翻滚,这也是您相对于地球实际指向的方向。 < li >“俯仰”代表翅膀周围的角度-基本上是机头朝上还是朝下。 < li >“横滚”代表飞机的倾斜,即机翼轴线是平行于地面还是围绕机身倾斜。

    重要的是要把所有这些都做好,尤其是与你的角度相关的符号(/-)-试着把它倾斜和滚动大约30度,并确保结果与输出一致-否则改变角度的符号。对于偏航,你将需要改变航向以及俯仰和滚动,因为航向本身不会影响杆端的位置,如果它是直上直下的。你拥有的描述“飞机”的数据是位置(三个数字),在如上所述的相同的XYZ框架中,以及如上所述的三个角度(以度为单位,-180到180)。

      < li >该代码假定所有轴都在设备的底部相交,并且杆从该点垂直向下悬挂。例如,如果杆长2米,轴实际上在连接点上方3厘米处相交,则可以将杆长调整为2.03米。如果杆实际上连接到一个不完全在轴交叉点下的点,软件需要改变一点,以说明末端不在它的正下方。同样,从全局来看,几毫米对你来说可能无关紧要。 < li >代码假定设备声称的位置实际上是轴的交叉点。如果不是,你需要调整位置到那个点(或者改变软件以允许那样)。 < li >您需要以与设备位置相同的单位指定杆长。
      < li >这并不涉及地球曲率-除非您的竿非常长,否则这并不重要,如果您将竿笔直地举起(或几乎如此),这一点也不重要。

    代码:

    我留下了一些不必要的东西(如果你需要重组它的话,你可能需要这些东西),也没有试图让它更有效(例如不断地重新计算相同的罪和余弦),让它更清晰。我在闭包编译器中留下了键入的内容,这既是为了一点文档,也是为了以后你想缩小它rodloc是您想要的函数。。。

    function presentresult(location, length, yaw, pitch, roll) {
        console.log("Starting point");
        console.log(location);
        console.log("Rod length = " + length);
        console.log("Yaw = " + yaw + ", Pitch = " + pitch + ", Roll = " + roll);
        console.log("Result:");
        console.log(rodloc(location, length, yaw, pitch, roll));
    }
    
    presentresult([100, 100, 100], 2, 0, 0, 0); // Result:  [100, 100, 98] (3)
    presentresult([100, 100, 100], 2, 30, 0, 0); // Result:  [100, 100, 98] (3)
    presentresult([100, 100, 100], 2, -30, 0, 0); // Result:  [100, 100, 98] (3)
    presentresult([100, 100, 100], 2, 0, 30, 0); // Result:  [99, 100, 98.26794919243112] (3)
    presentresult([100, 100, 100], 2, 0, -30, 0); // Result:  [101, 100, 98.26794919243112] (3)
    presentresult([100, 100, 100], 2, 0, 0, 30); // Result:  [100, 101, 98.26794919243112] (3)
    presentresult([100, 100, 100], 2, 0, 0, -30); // Result:  [100, 99, 98.26794919243112] (3)
    presentresult([100, 100, 100], 2, 30, 30, 30); // Result:  [98.75, 100.43301270189222, 98.5] (3)
    presentresult([100, 100, 100], 2, -30, -30, -30); // Result:  [100.25, 98.70096189432334, 98.5] (3)
    presentresult([100, 100, 100], 2, -30, 30, -30); // Result:  [98.75, 99.56698729810778, 98.5] (3)
    
    /** @typedef {Array<number,number,number>} */ var Vector3D;
    /** @typedef {Array<Vector3D,vector3D,Vector3D>} */ var Matrix3D;
    
    /**
     * @param {Vector3D} location - The location (3 coordinates) of the "plane"
     * @param {number} length - The length of the rod
     * @param {number} yaw - the yaw (heading) in degrees
     * @param {number} pitch - the pitch in degrees
     * @param {number} roll - the roll in degrees
     * @returns {Vector3D} - the location of the end of the rod
     */
    function rodloc(location, length, yaw, pitch, roll) {
        let ryaw = yaw * Math.PI / 180.0;       // Convert to radians
        let rpitch = pitch * Math.PI / 180.0;
        let rroll = roll * Math.PI / 180.0;
    
        // This is where our axes start
        let x = [1, 0, 0];
        let y = [0, 1, 0];
        let z = [0, 0, 1];
    
        // NOTE:  ORDER MATTERS - your data may mean different things (see
        //        assumptions in answer!
        // Rotate axes around z by yaw
        let yprime = rotatearound([0, 1, 0], [0, 0, 1], ryaw);
        let xprime = rotatearound([1, 0, 0], [0, 0, 1], ryaw);
        let zprime = z;     // rotating around itself
    
        // Next we need to rotate for pitch (around the Y axis...)
        let x2prime = rotatearound(xprime, yprime, rpitch); 
        let y2prime = yprime; // dont need this
        let z2prime = rotatearound(zprime, yprime, rpitch);
    
        // Now we need to roll around the new x axis...
        let x3prime = x2prime   // dont need this
        let y3prime = rotatearound(y2prime, x2prime, rroll); // dont need this
        let z3prime = rotatearound(z2prime, x2prime, rroll);
    
        // now take what started out as [0, 0, 1] and place the end of the rod
        // (at what started out as [0, 0, -length])
        let rotend = [0,1,2].map(n=>-length*z3prime[n]);
    
        // now take that and add it to the original location of the plane 
        // and return it as the result
        return [0,1,2].map(n=>location[n]+rotend[n]);
    }
    
    /** Multiply a vector times a matrix
     * @param {Vector3D} offset - The vector of the offset
     * @param {Matrix3D} rotate - The rotation vector
     * @returns {Vector3D} - The new offset vector
     */
    function vmmult(offset, rotate) {
        return [0,1,2].map(x=>xmult(offset,rotate[x]));
    }
    
    /** dot product of two vectors
     * @param {Vector3D} col
     * @param {Vector3D} row
     * @returns {number}
     */
    function xmult(col, row) {
        return [0,1,2].reduce((a,c)=>a+col[c]*row[c],0);
    }
    
    /** Rotate a point around a vector projecting from the origin
     * @param {Vector3D} point - the we want to rotate
     * @param {Vector3D} vec - the vector (from origin to here) to rotate around
     * @param {number} angle - the angle (in radians) to rotate
     * @returns {Vector3D} - the new point location
     */
    function rotatearound(point, vec, angle) {
        let rotmat = setuprotationmatrix(angle, vec);
        return vmmult(point, rotmat);
    }
    
    /**
     * Adapted from C courtesy of Bibek Subedi
     * https://www.programming-techniques.com/2012/03/3d-rotation-algorithm-about-arbitrary.html
     * @param {number} angle - the angle to rotate around the vector
     * @param {Vector3D} vec - the vector around which to rotate
     * @returns {Matrix3D} - the rotation matrix
     */
    function setuprotationmatrix(angle, vec) {
        // Leaving L in for reusability, but it should always be 1 in our case
        let u = vec[0], v = vec[1], w = vec[2]; 
        let L = (u*u + v * v + w * w);
        let u2 = u * u;
        let v2 = v * v;
        let w2 = w * w; 
    
        let rotmat = [[],[],[]];
        rotmat[0][0] = (u2 + (v2 + w2) * Math.cos(angle)) / L;
        rotmat[0][1] = (u * v * (1 - Math.cos(angle)) - w * Math.sqrt(L) * Math.sin(angle)) / L;
        rotmat[0][2] = (u * w * (1 - Math.cos(angle)) + v * Math.sqrt(L) * Math.sin(angle)) / L;
    
        rotmat[1][0] = (u * v * (1 - Math.cos(angle)) + w * Math.sqrt(L) * Math.sin(angle)) / L;
        rotmat[1][1] = (v2 + (u2 + w2) * Math.cos(angle)) / L;
        rotmat[1][2] = (v * w * (1 - Math.cos(angle)) - u * Math.sqrt(L) * Math.sin(angle)) / L;
    
        rotmat[2][0] = (u * w * (1 - Math.cos(angle)) - v * Math.sqrt(L) * Math.sin(angle)) / L;
        rotmat[2][1] = (v * w * (1 - Math.cos(angle)) + u * Math.sqrt(L) * Math.sin(angle)) / L;
        rotmat[2][2] = (w2 + (u2 + v2) * Math.cos(angle)) / L;
        return rotmat;
    } 
    

  •  类似资料:
    • 如果我有一个相机的偏航、俯仰和向上向量(在我的情况下总是[0,1,0]),计算相应滚动的最佳方法是什么?

    • 我试图从我有的方向向量(从中我可以得到俯仰和偏航)和滚动来计算一个向上向量。我需要这个,这样我就可以做一个四元数。 有人知道我怎么做吗?

    • 我正在努力弄清楚如何使俯仰偏航和侧倾在它们之间独立。一旦我在z轴(俯仰)上旋转某个物体,第二次旋转(yaxis yaw)取决于第一次旋转的结果,第三次旋转(x轴,roll)取决于其他两次旋转的结果。所以,我没有独立的俯仰、偏航和横滚,而是把它们三者混合在一起,很难看。 我希望有可能将物体的角度存储在一个数组中[俯仰、偏航、滚动],然后在变换过程中对这些角度进行解码,以便偏航将物体放置在给定的位置,

    • 所以基本上在我的游戏中,我设法添加了向右移动,然后应用了相反的逻辑向左移动,但我仍然没有设法向前或向后移动。我只有一个俯仰和偏航可以使用,这意味着我没有RotationX、Y或Z。如果你能帮我计算这些,如果有必要的话也会很酷。这是我目前的代码: 我也有一个创建视图矩阵方法,称为每一帧,就像camera.update()方法一样

    • 我想做的是从我的相机中投射光线。我知道相机的x、y和z坐标,以及它的俯仰和偏航。我需要计算它的方向向量,这样我就可以把它传递给光线跟踪算法。 相机的向上向量是(0,1,0)。“音高”,从相机的角度来看,是上下看。 (我宁愿不使用矩阵,但如果有必要,我会使用)

    • 我一直在处理3D空间(X、Y、Z)中的点,希望能够计算其中两个点之间的俯仰和偏航。 我的当前代码: 其中X1、X2、Y1、Y2、Z1、Z2在运行时之前都是未知的,此时它们是从两个随机生成的点收集的。 然而,由于某种原因,我的结果大错特错,我尝试了许多不同的组合,在google上搜索了无数的东西,但什么都没有找到。 一些制约因素是: 节距只能小于或等于90,或大于或等于-90(90= 这是我第一次使

    • 我的投球和打哈欠都搞砸了。我有垫子的俯仰和偏航,但光束的俯仰和偏航都搞砸了。如何计算垫的俯仰和偏航的法向量?我在stackoverflow上尝试了一大堆数学,但到目前为止都失败了。 我接下来尝试做的是将光束的俯仰和偏航从垫子的俯仰和偏航中分离出来,并分别计算它们。这基本上有效,但偏航仍然完全混乱。 我过去是通过光束的偏航和俯仰来计算方向向量的,这是一个util minecraft用来计算暴徒的方向

    • 我在我的应用程序中使用最新的谷歌地图iOSSDK,似乎GPS位置在中国总是被1-2个街区抵消,然而,在谷歌地图官方应用程序中,位置是100%正确的。 我看到这篇文章,这似乎是原因:http://home.wangjianshuo.com/archives/20081109_all_maps_in_china_are_transformed.htm 官方应用程序似乎使用了正确转换的地图,而谷歌地图i