liyihongcug 发表于 2020-4-2 20:15:33

向量夹角计算问题

本帖最后由 liyihongcug 于 2020-4-3 10:30 编辑

无论是BS还是CS ,向量之间的方位角计算 俯仰角计算肯定是必须,特别在地球球面上。另外在动画场景下是要的。
向量之间的方位角,可以转化在ENU坐标系下的向量在XOY投影分量与当地的Y轴向量之间的夹角。其他类推。

最简单的例子先入门
两个向量的夹角计算公式:θ=acos(v1⋅v2/||v1||||v2||)acos(弧度)就可以得到了
需要注意的θ的范围再0~pi之间,怎么解决0~2pi的问题呢?
这里就需要用到向量的叉乘,根据叉乘后的向量与屏幕方向来确定角度是否超过180°。
代码如下:
float Angle(osg::Vec3f line1, osg::Vec3f line2, osg::Vec3f direction)
{
        line1.normalize();
        line2.normalize();
        float temp = (line1 * line2);
        // 1和-1时为0和180°
        if (fabs(fabs(temp) - 1) < EPSILON)
        {
                return temp > 0 ? 0 : osg::PI;
        }
        float angle = (float)acos(temp);

        // 两个向量的叉乘结果与屏幕方向是否一致来判断角度是否超过180°
        osg::Vec3f axis = line1 ^ line2;
        return axis * direction > 0 ? angle : 2 * osg::PI - angle;
}每个变换矩阵matrix都可以分解为三个矩阵的乘积:其旋转矩阵rotateMatrix,放缩矩阵,和平移矩阵
matrix = rotateMatrix* osg::Matrix::scale(matrix.getScale())*osg::Matrix::translate(matrix.getTrans());
由此rotateMatrix = mateix*osg::Matrix::inverse(osg::Matrix::translate(matrix.getTrans()))*osg::Matrix::inverse( osg::Matrix::scale(matrix.getScale()))

liyihongcug 发表于 2020-4-3 09:09:46

本帖最后由 liyihongcug 于 2020-4-3 10:41 编辑

数学问题与GIs之间的问题。最经典的计算都发现一个大bug, 可见都是在无意识复制其他人的东西,已经更改验证成功。数学强但不见得gis能融合,实际上osg与webgl坐标轴是一致的,应该代码可以迁移.
确认一点:经典数学 两个向量点乘夹角0度=<角度<=180度.C++ Math.h的acos完美解决这个问题,提醒是参数是弧度。(方法见一楼略加处理就可以)
而实际上在地理上不完全是数学, 正北的顺时针方向表明必须是0《 角度《360.所以必须在2个向量上进行改造
首先判断投影分量跟x轴的夹角是否大于90,如果是表明角度在180360之间;
如果《90,表明角度正常在0 180之间。 这样才能完全解决ENU下的问题。

liyihongcug 发表于 2020-4-3 10:50:18

本帖最后由 liyihongcug 于 2020-4-8 10:06 编辑

根据物体的起始位置(经度、纬度、高度)和目的位置获取物体的旋转 quat
当前的计算测试在osg和webgl多端测试验证结果

问题集中在这里:
有个osg问题四元数欧拉角转换问题讨论 死活总有一个负数符号与实际背离

{x: -0.0528416077945538, y: -0.3545720185955853, z: -0.34854906127364393, w: 0.8660254037844387}
osg::Vec3 QuaternionToVector3(osg::Quat _q)
{
        osg::Vec3 v(
                atan((2*(_q.w()*_q.x() + _q.y()*_q.z()))      /      (1-2*( pow(_q.x(),2) + pow(_q.y(),2) )) ),
                asin(2*(_q.w()*_q.y()-_q.z()*_q.x())),
                atan((2*(_q.w()*_q.z() + _q.x()*_q.y()))      /      (1-2*( pow(_q.y(),2) + pow(_q.z(),2) )) )
                );
        return v;
}
实际heading: 0.8419220914223688, pitch: 0.7088649026650486, roll: 0.20650593768060643}

结果有错VM2946:4 heading=-0.8419220914223688 pitch=-0.7088649026650486 roll=0.20650593768060643
为何出现heading pitch符号与WEBGL的符号不同的情况

原因在于
Heading就是yaw,即偏航的意思。则相机的Heading/pitch/roll与飞机类似:

Heading=yaw,表示相机绕Up轴旋转,Up轴为+Z轴,且定义绕-Z轴旋转为正。
Pitch,表示相机绕Right轴旋转,Right轴为-Y轴,且定义绕-Y轴旋转为正。
Roll,表示相机绕Direction轴(视线方向)旋转,Direction轴为+X轴,且绕+X轴旋转为正。

权威:原文
*
   * Computes a rotation from the given heading, pitch and roll angles. Heading is the rotation about the
   * negative z axis. Pitch is the rotation about the negative y axis. Roll is the rotation about
   * the positive x axis.
   *
result.heading = -Math.atan2(numeratorHeading, denominatorHeading);
      result.roll = Math.atan2(numeratorRoll, denominatorRoll);
      result.pitch = -Math.asin(test);


确认一点
广义欧拉角=卡尔丹角
欧拉角:章动角θ、旋进角(即进动角)ψ和自转角j
卡尔丹角:俯仰角、偏航角、滚转角=楼主所说的姿态角================准确的说还不是欧拉角 是姿态角
欧拉角是用来唯一地确定定点转动刚体位置的三个一组独立角参量,由章动角θ、进动角ψ和自转角φ组成,为L.欧拉首先提出,故得名。它们有多种取法,下面是常见的一种。

如图所示,由定点O作出固定坐标系Oxyz以及固连于刚体的坐标系Ox'y'z'。以轴Oz和Oz'为基本轴,其垂直面Oxy和Ox'y'为基本平面.由轴Oz量到Oz'的角度θ称为章动角。平面zOz'的垂线ON称为节线,它又是基本平面Ox'y'和Oxy的交线。在右手坐标系中,由ON的正端看,角θ应按逆时针方向计量。由固定轴Ox量到节线ON的角度ψ称为进动角,由节线ON量到动轴Ox'的角度φ称为自转角。由轴Oz和Oz'正端看,角ψ和φ也都按逆时针方向计量。欧拉角(ψ,θ,φ)的名称来源于天文学。
从左右手坐标系和作用对像出发就可以捋清该如何推导和使用这些矩阵了。对右手系而言,定义的正向转动为绕旋转轴的逆时针方向,所以当作用对像(或叫旋转对象)
由固定轴Ox量到节线ON的角度ψ称为进动角,由节线ON量到动轴Ox'的角度φ称为自转角ψ)


理论上都应是让各轴的正向(X轴向右、Y轴向下、Z轴面向自己)指向自己,顺时针(正角度值)/逆时针(负角度值)转

liyihongcug 发表于 2020-4-8 09:34:26

本帖最后由 liyihongcug 于 2020-4-14 10:17 编辑

早上验证。三维里面的headingpitch roll 与地理信息系统有不同的含义,上面的帖子较多不严密的地方。
三维里面的heading代码验证是x轴正向的夹角。
地理的方位角度是与正北方向的角度(0-360),这属于不同领域的。三维是纯粹的数学计算,地理是加了业务规则的业务数学计算(特定含义)。
三维的的姿态有确定的含义,BS里确认。

无论Bs CS
GeoTransform
GeoTransform->setMatrix(osg::Matrix::rotate(osg::DegreesToRadians(headingAngle), 0, 0, 1));//Z
GeoTransform>setMatrix(osg::Matrix::rotate(osg::DegreesToRadians(pitchAngle), 0, 1, 0) * GeoTransform->getMatrix());//Y
GeoTransform>setMatrix(osg::Matrix::rotate(osg::DegreesToRadians(rollAngle), 1, 0, 0) * GeoTransform->getMatrix());//X

BS 和CS模型同样的数据方位不一致。
页: [1]
查看完整版本: 向量夹角计算问题