关于求解euler角的问题

各位前辈好,我想请教一下,如何输出 euler 角的问题。我在做动网格计算后,输出有 6-DOF 的信息:

6-DoF rigid body motion
    Centre of rotation: (5 0.45 0.9)
    Centre of mass: (5 0.45 0.9)
    Orientation: (0.995589999257 0 -0.09381126467 0 1 0 0.09381126467 0 0.995589999257)
    Linear velocity: (0 0 0)
    Angular velocity: (0 -0.21652336234 -0)

其中有orientation矩阵,但是我不知道该怎么将这个矩阵转化为euler角。我在网上看到有在sixDoFRigidBodyMotion.C 中加入代码,直接转换为euler角,代码为:

      quaternion b = quaternion(orientation());
      vector ang = b.eulerAngles(b);
  Info<< " Euler angles: " << 180/3.14159265359*ang << endl; //- Print the angle vector

加入之后,输出就变为这样

6-DoF rigid body motion
  Centre of rotation: (-0.5 0.449998563721 0.1)
  Centre of mass: (-0.500001532453 0.449998563721 0.349999999995)
  Orientation: (0.999999999981 0 -6.1298114399e-06 0 1 0 6.1298114399e-06 0 0.999999999981)
  Linear velocity: (0 -5.227784072e-05 0)
  Angular velocity: (0 -0.000462275194671 0)
  Euler angles: (0 -0.000351212324719 0)

但这个代码是of2.4.x版本的,我现在用的是of1912,代码不兼容,我加入这个代码就编译出错。
sixDoFRigidBodyMotion/sixDoFRigidBodyMotionAngle.C:333:33: error: no matching function for call to ‘Foam::quaternion::eulerAngles(Foam::quaternion&)’
vector ang = b.eulerAngles(b);//add
我不知道改怎么修改这个代码,希望有前辈能帮忙指点一下,谢谢各位

实际上,前半部分还是对的。

    quaternion b = quaternion(orientation());
    enum eulerOrder A;
    A = ZXY;
    vector ang = b.eulerAngles(A);
    Info<< " Euler angles: " << 180/3.14159265359*ang << endl; //- Print the angle vector

ZXY 是欧拉角的坐标旋转顺序,按你的情况修改。

手上暂时没有 v1912 做调试,你可以先试一下,看看情况如何?

实际上,错误输出的后面应该有提示 eulerAngles 的函数应该怎么用,可以贴出来。

非常感谢前辈老师的恢复,老师您好,这是我之前用代码编译出的错误内容:

sixDoFRigidBodyMotion/sixDoFRigidBodyMotionAngle.C: In member function ‘void Foam::sixDoFRigidBodyMotion::status() const’: sixDoFRigidBodyMotion/sixDoFRigidBodyMotionAngle.C:340:35: error: no matching function for call to ‘Foam::quaternion::eulerAngles(Foam::quaternion&)’
       vector ang = b.eulerAngles(b);
                                   ^
In file included from /root/OpenFOAM/OpenFOAM-v1912/src/OpenFOAM/lnInclude/quaternion.H:317:0,
                 from /root/OpenFOAM/OpenFOAM-v1912/src/OpenFOAM/lnInclude/septernion.H:48,
                 from sixDoFRigidBodyMotion/sixDoFRigidBodyMotionAngle.C:31:
/root/OpenFOAM/OpenFOAM-v1912/src/OpenFOAM/lnInclude/quaternionI.H:407:21: note: candidate: Foam::vector Foam::quaternion::eulerAngles(Foam::quaternion::eulerOrder) const
 inline Foam::vector Foam::quaternion::eulerAngles
                     ^~~~
/root/OpenFOAM/OpenFOAM-v1912/src/OpenFOAM/lnInclude/quaternionI.H:407:21: note:   no known conversion for argument 1 from ‘Foam::quaternion’ to ‘Foam::quaternion::eulerOrder’
/root/OpenFOAM/OpenFOAM-v1912/wmake/rules/General/transform:34: recipe for target 'Make/linux64GccDPInt32Opt/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionAngle.o' failed
make: *** [Make/linux64GccDPInt32Opt/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionAngle.o] Error 1

下面则是我使用老师您给的代码,编译后出现的错误

sixDoFRigidBodyMotion/sixDoFRigidBodyMotionAngle.C: In member function ‘void Foam::sixDoFRigidBodyMotion::status() const’:
sixDoFRigidBodyMotion/sixDoFRigidBodyMotionAngle.C:340:12: error: use of enum ‘eulerOrder’ without previous declaration
       enum eulerOrder A;
            ^~~~~~~~~~
sixDoFRigidBodyMotion/sixDoFRigidBodyMotionAngle.C:341:11: error: ‘ZXY’ was not declared in this scope
       A = ZXY;
           ^~~
sixDoFRigidBodyMotion/sixDoFRigidBodyMotionAngle.C:342:35: error: invalid conversion from ‘int’ to ‘Foam::quaternion::eulerOrder’ [-fpermissive]
       vector ang = b.eulerAngles(A);
                                   ^
In file included from /root/OpenFOAM/OpenFOAM-v1912/src/OpenFOAM/lnInclude/quaternion.H:317:0,
                 from /root/OpenFOAM/OpenFOAM-v1912/src/OpenFOAM/lnInclude/septernion.H:48,
                 from sixDoFRigidBodyMotion/sixDoFRigidBodyMotionAngle.C:31:
/root/OpenFOAM/OpenFOAM-v1912/src/OpenFOAM/lnInclude/quaternionI.H:407:21: note:   initializing argument 1 of ‘Foam::vector Foam::quaternion::eulerAngles(Foam::quaternion::eulerOrder) const’
 inline Foam::vector Foam::quaternion::eulerAngles
                     ^~~~
/root/OpenFOAM/OpenFOAM-v1912/wmake/rules/General/transform:34: recipe for target 'Make/linux64GccDPInt32Opt/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionAngle.o' failed
make: *** [Make/linux64GccDPInt32Opt/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionAngle.o] Error 1

然后我查看了一下0f1912的quaternion的代码,quaternion.C:

        //- Euler-angle rotation order
        enum eulerOrder : unsigned char
        {
            // Proper Euler angles
            XZX, XYX, YXY, YZY, ZYZ, ZXZ,

            // Tait-Bryan angles
            XZY, XYZ, YXZ, YZX, ZYX, ZXY
        };

        //- The names for Euler-angle rotation order
        static const Enum<eulerOrder> eulerOrderNames;
·
·
·
        //- Construct from three Euler rotation angles
        inline quaternion(const eulerOrder order, const vector& angles);
·
·
·

       //- Return the Euler rotation angles corresponding to the
       //- specified rotation order
       inline vector eulerAngles(const eulerOrder order) const;

对比了一下of2.4.0的quaternion.C

        //- Construct a quaternion given the three Euler angles
        inline quaternion
        (
            const scalar angleX,
            const scalar angleY,
            const scalar angleZ
        );
·
·
·
               //- Return a vector of euler angles (rotations in radians about
               //  the x, y and z axes.
               inline vector eulerAngles(const quaternion& q) const;

但是对比了两个版本的代码,我又不知道咋个修改。最后非常感谢老师的回复,谢谢老师!

两个版本差异比较大。使用的参数不一样。

你试下呢?

    quaternion b = quaternion(orientation());
    eulerOrder A;
    A = ZXY;
    vector ang = b.eulerAngles(A);
    Info<< " Euler angles: " << 180/3.14159265359*ang << endl; //- Print the angle vector

老师您好,出现了这个错误

sixDoFRigidBodyMotion/sixDoFRigidBodyMotionAngle.C: In member function ‘void Foam::sixDoFRigidBodyMotion::status() const’:
sixDoFRigidBodyMotion/sixDoFRigidBodyMotionAngle.C:333:5: error: ‘eulerOrder’ was not declared in this scope
     eulerOrder A;
     ^~~~~~~~~~
sixDoFRigidBodyMotion/sixDoFRigidBodyMotionAngle.C:334:5: error: ‘A’ was not declared in this scope
     A = ZXY;
     ^
sixDoFRigidBodyMotion/sixDoFRigidBodyMotionAngle.C:334:9: error: ‘ZXY’ was not declared in this scope
     A = ZXY;
         ^~~
/root/OpenFOAM/OpenFOAM-v1812/wmake/rules/General/transform:34: recipe for target 'Make/linux64GccDPInt32Opt/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionAngle.o' failed
make: *** [Make/linux64GccDPInt32Opt/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionAngle.o] Error 1

谢谢老师的耐心回复。

我手上的 v1812 不一样,但是方法相同,编译是通过的。

v1912 上的定义不一样,提示跟变量定义范围有关。

老师,您好,我手上也有of1812版本,我按照您的代码编译了一下,出现了以下错误,和of1912出现的错误是一样的。

sixDoFRigidBodyMotion/sixDoFRigidBodyMotionAngle.C: In member function ‘void Foam::sixDoFRigidBodyMotion::status() const’:
sixDoFRigidBodyMotion/sixDoFRigidBodyMotionAngle.C:333:2: error: ‘eulerOrder’ was not declared in this scope
  eulerOrder A;//add
  ^~~~~~~~~~
sixDoFRigidBodyMotion/sixDoFRigidBodyMotionAngle.C:334:2: error: ‘A’ was not declared in this scope
  A = ZXY;//add
  ^
sixDoFRigidBodyMotion/sixDoFRigidBodyMotionAngle.C:334:6: error: ‘ZXY’ was not declared in this scope
  A = ZXY;//add
      ^~~
/root/OpenFOAM/OpenFOAM-v1812/wmake/rules/General/transform:34: recipe for target 'Make/linux64GccDPInt32Opt/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionAngle.o' failed
make: *** [Make/linux64GccDPInt32Opt/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionAngle.o] Error 1

看这个错误提示,我想我是不是代码加错地方了呀,我加在sixDoFRigidBodyMotion.C下的这个地方

void Foam::sixDoFRigidBodyMotion::status() const
{
    Info<< "6-DoF rigid body motion" << nl
        << "    Centre of rotation: " << centreOfRotation() << nl
        << "    Centre of mass: " << centreOfMass() << nl
        << "    Orientation: " << orientation() << nl
        << "    Linear velocity: " << v() << nl
        << "    Angular velocity: " << omega()
        << endl;
      quaternion b = quaternion(orientation());//add
      eulerOrder A;//add
      A = XZY;//add
      vector ang = b.eulerAngles(A);//add
    Info<< " Euler angles: " << 180/3.14159265359*ang << endl; //- Print the angle vector
}

感谢老师抽出时间为我解惑,谢谢老师!

如果你用 1812 的话,那个 eulerOrder 不一样,是使用的 rotationSequence

void Foam::sixDoFRigidBodyMotion::status() const
{   
    rotationSequence A(ZXY);
    Info<< "6-DoF rigid body motion" << nl
        << "    Centre of rotation: " << centreOfRotation() << nl
        << "    Centre of mass: " << centreOfMass() << nl
        << "    Orientation: " << orientation() << nl
        << "    Linear velocity: " << v() << nl
        << "    Angular velocity: " << omega() << nl
        << "    Euler Angles: " << quaternion(orientation()).eulerAngles(A)
        << endl;
} 

注意 ZXY 要按你自己的要求或习惯来设置,有可能是

    //- Euler-angle rotation sequence
    enum rotationSequence
    {
        ZYX, ZYZ, ZXY, ZXZ, YXZ, YXY, YZX, YZY, XYZ, XYX, XZY, XZX
    }

老师,您好,我按照您的代码改了还是出错 :sob:

sixDoFRigidBodyMotion/sixDoFRigidBodyMotionAngle.C: In member function ‘void Foam::sixDoFRigidBodyMotion::status() const’:
sixDoFRigidBodyMotion/sixDoFRigidBodyMotionAngle.C:325:5: error: ‘rotationSequence’ was not declared in this scope
     rotationSequence A(ZXY);
     ^~~~~~~~~~~~~~~~
sixDoFRigidBodyMotion/sixDoFRigidBodyMotionAngle.C:325:5: note: suggested alternative: ‘rotationTensorX’
     rotationSequence A(ZXY);
     ^~~~~~~~~~~~~~~~
     rotationTensorX
sixDoFRigidBodyMotion/sixDoFRigidBodyMotionAngle.C:332:64: error: ‘A’ was not declared in this scope
  << " Euler angles: " << quaternion(orientation()).eulerAngles(A)
                                                                ^
/root/OpenFOAM/OpenFOAM-v1812/wmake/rules/General/transform:34: recipe for target 'Make/linux64GccDPInt32Opt/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionAngle.o' failed
make: *** [Make/linux64GccDPInt32Opt/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionAngle.o] Error 1

我试了 v1912,这样就可以了

void Foam::sixDoFRigidBodyMotion::status() const
{
    Info<< "6-DoF rigid body motion" << nl
        << "    Centre of rotation: " << centreOfRotation() << nl
        << "    Centre of mass: " << centreOfMass() << nl
        << "    Orientation: " << orientation() << nl
        << "    Linear velocity: " << v() << nl
        << "    Angular velocity: " << omega() << nl
        << "    Euler angles: " << quaternion(orientation()).eulerAngles(quaternion::eulerOrder::ZXY)
        << endl;
}

前面不成功,是因为名称空间的问题,现在就可以用了。

另外,你使用 v1812 时,是否使用了 v1812 的预置环境?

1 Like

感谢老师深夜回复,我刚刚在of1912上使用老师的新代码编译成功了,谢谢老师。
之前使用of1812时,我是调用了of1812的预置环境的。我刚刚根据老师您的代码,把eulerOrder替换成rotationSequence,在of1812上编译成功了,这是of1812编译成功的代码

void Foam::sixDoFRigidBodyMotion::status() const
{
    Info<< "6-DoF rigid body motion" << nl
        << "    Centre of rotation: " << centreOfRotation() << nl
        << "    Centre of mass: " << centreOfMass() << nl
        << "    Orientation: " << orientation() << nl
        << "    Linear velocity: " << v() << nl
        << "    Angular velocity: " << omega() << nl
        << " Euler angles: " << quaternion(orientation()).eulerAngles(quaternion::rotationSequence::ZXY)
        << endl; 
}

再次感谢老师的耐心回复,谢谢老师!

1 Like