Coordinate transformation (demo_CH_coords.cpp) 
  Tutorial on how to perform coordinate transformations in Chrono.
No GUI: only text output.
// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution and at
// http://projectchrono.org/license-chrono.txt.
//
// =============================================================================
// Authors: Alessandro Tasora
// =============================================================================
//
// Demo on how to use Chrono coordinate transformations
//
// =============================================================================
#include <cmath>
#include "chrono/core/ChLog.h"
#include "chrono/core/ChTransform.h"
#include "chrono/core/ChFrame.h"
#include "chrono/core/ChFrameMoving.h"
#include "chrono/core/ChTimer.h"
using namespace chrono;
int main(int argc, char* argv[]) {
    // To write something to the console, use the chrono::GetLog()
    GetLog() << "CHRONO demo about coordinate transformations: \n\n";
    //
    // Some methods to achieve coordinate transformations, and some
    // examples of how to manipulate coordinates and frames, using Chrono features.
    //
    // You can use ChTransform or ChChCoordsys<> or ChFrame functions to transform points
    // from/to local coordinates in 3D, in ascending complexity and capabilities.
    //
    ChVector<> mvect2;  // resulting (transformed) vectors will go here
    ChVector<> mvect3;
    // Define a  POINT  to be transformed, expressed in
    // local frame coordinate.
    ChVector<> mvect1(2, 3, 4);
    // Define a vector representing the TRASLATION of the frame
    // respect to absolute (world) coordinates.
    ChVector<> vtraslA(5, 6, 7);
    // Define a quaternion representing the ROTATION of the frame
    // respect to absolute (world) coordinates. Must be normalized.
    ChQuaternion<> qrotA(1, 3, 4, 5);
    qrotA.Normalize();
    // ..Also create a 3x3 rotation matrix [A] from the quaternion
    // (at any time you can use mrotA.Set_A_quaternion(qrotA) );
    ChMatrix33<> mrotA(qrotA);
    // ..Also create a ChCoordsys<>tem object, representing both
    // translation and rotation.
    ChCoordsys<> csysA(vtraslA, qrotA);
    // OK!!! Now we are ready to perform the transformation, like in
    // linear algebra formula v'=t+[A]*v, so that we will obtain
    // the coordinates of mvect1 in absolute coordinates.
    // This can be achieved in many ways. Let's see them.
    // TRASFORM USING ROTATION MATRIX AND LINEAR ALGEBRA
    //
    mvect2 = vtraslA + mrotA * mvect1;  // like:  v2 = t + [A]*v1
    GetLog() << mvect2 << " ..using linear algebra, \n";
    // TRASFORM USING QUATERNION ROTATION
    mvect2 = vtraslA + qrotA.Rotate(mvect1);
    GetLog() << mvect2 << " ..using quaternion rotation, \n";
    // TRASFORM USING THE ChTransform STATIC METHODS
    mvect2 = ChTransform<>::TransformLocalToParent(mvect1, vtraslA, mrotA);
    GetLog() << mvect2 << " ..using the ChTransform- vect and rot.matrix, \n";
    mvect2 = ChTransform<>::TransformLocalToParent(mvect1, vtraslA, qrotA);
    GetLog() << mvect2 << " ..using the ChTransform- vect and quat, \n";
    // TRASFORM USING A ChCoordys OBJECT
    mvect2 = csysA.TransformLocalToParent(mvect1);
    GetLog() << mvect2 << " ..using a ChChCoordsys<> object, \n";
    mvect2 = mvect1 >> csysA;
    GetLog() << mvect2 << " ..using a ChChCoordsys<> '>>' operator, \n";
    mvect2 = csysA * mvect1;
    GetLog() << mvect2 << " ..using a ChChCoordsys<> '*' operator, \n";
    // TRASFORM USING A ChFrame OBJECT
    ChFrame<> mframeA(vtraslA, qrotA);  // or ChFrame<> mframeA(csysA);
    mvect2 = mframeA.TransformLocalToParent(mvect1);
    GetLog() << mvect2 << " ..using a ChFrame object function, \n";
    mvect2 = mvect1 >> mframeA;
    GetLog() << mvect2 << " ..using a ChFrame '>>' operator, \n";
    mvect2 = mframeA * mvect1;
    GetLog() << mvect2 << " ..using a ChFrame '*' operator, \n";
    //
    // Now perform transformations in a chain of frames, in
    // sequence.
    //
    ChVector<> v10(5, 6, 7);
    ChQuaternion<> q10(1, 3, 4, 5);
    q10.Normalize();
    ChMatrix33<> m10(q10);
    ChVector<> v21(4, 1, 3);
    ChQuaternion<> q21(3, 2, 1, 5);
    q21.Normalize();
    ChMatrix33<> m21(q21);
    ChVector<> v32(1, 5, 1);
    ChQuaternion<> q32(4, 1, 3, 1);
    q32.Normalize();
    ChMatrix33<> m32(q32);
    // ...with linear algebra:
    mvect3 = v10 + m10 * (v21 + m21 * (v32 + m32 * mvect1));
    GetLog() << mvect3 << " ..triple trsf. using linear algebra, \n";
    // ...with ChFrame '>>' operator or "*" operator
    // is by far much simplier!
    ChFrame<> f10(v10, q10);
    ChFrame<> f21(v21, q21);
    ChFrame<> f32(v32, q32);
    mvect3 = mvect1 >> f32 >> f21 >> f10;
    GetLog() << mvect3 << " ..triple vector trsf. with ChFrame '>>' operator, \n";
    mvect3 = f10 * f21 * f32 * mvect1;
    GetLog() << mvect3 << " ..triple vector trsf. with ChFrame '*' operator, \n";
    ChFrame<> tempf(f10 * f21 * f32);
    mvect3 = tempf * mvect1;
    GetLog() << mvect3 << " ..triple vector trsf. with ChFrame '*' operator, \n";
    // Not only vectors, but also ChFrame can be transformed
    // with ">>" or "*" operators.
    ChFrame<> f_3(mvect1);
    ChFrame<> f_0;
    f_0 = f_3 >> f32 >> f21 >> f10;
    GetLog() << f_0 << " ..triple frame trsf. with ChFrame '>>' operator,  \n";
    f_0 = f10 * f21 * f32 * f_3;
    GetLog() << f_0 << " ..triple frame trsf. with ChFrame '*' operator,  \n";
    // Test the  ">>" or "*" operators also for ChCoordsys:
    ChCoordsys<> c_0;
    c_0 = f_3.GetCoord() >> f32.GetCoord() >> f21.GetCoord() >> f10.GetCoord();
    GetLog() << f_0 << " ..triple frame trsf. with ChCoordsys '>>' operator,  \n";
    c_0 = f10.GetCoord() * f21.GetCoord() * f32.GetCoord() * f_3.GetCoord();
    GetLog() << f_0 << " ..triple frame trsf. with ChCoordsys '*' operator,  \n";
    //
    // Now test inverse transformations too.
    //
    // From the low-level to the higher level methods, here are some
    // ways to accomplish this.
    //
    // TRASFORM USING ROTATION MATRIX AND LINEAR ALGEBRA
    //
    GetLog() << mvect1 << " ..mvect1 \n";
    mvect1 = mrotA.transpose() * (mvect2 - vtraslA);  // like:  v1 = [A]'*(v2-t)
    GetLog() << mvect1 << " ..inv, using linear algebra, \n";
    // TRASFORM USING QUATERNION ROTATION
    mvect1 = qrotA.RotateBack(mvect2 - vtraslA);
    GetLog() << mvect1 << " ..inv, using quaternion rotation, \n";
    // TRASFORM USING THE ChTransform STATIC METHODS
    mvect1 = ChTransform<>::TransformParentToLocal(mvect2, vtraslA, mrotA);
    GetLog() << mvect1 << " ..inv, using the ChTransform- vect and rot.matrix, \n";
    mvect1 = ChTransform<>::TransformParentToLocal(mvect2, vtraslA, qrotA);
    GetLog() << mvect1 << " ..inv, using the ChTransform- vect and quat, \n";
    // TRASFORM USING A ChCoordys OBJECT
    mvect1 = csysA.TransformParentToLocal(mvect2);
    GetLog() << mvect1 << " ..inv, using a ChChCoordsys<> object, \n";
    // TRASFORM USING A ChFrame OBJECT
    mvect1 = mframeA.TransformParentToLocal(mvect2);
    GetLog() << mvect1 << " ..inv, using a ChFrame object function, \n";
    mvect1 = mvect2 >> mframeA.GetInverse();
    GetLog() << mvect1 << " ..inv, using a ChFrame inverse and '>>' operator, \n";
    mvect1 = mframeA.GetInverse() * mvect2;
    GetLog() << mvect1 << " ..inv, using a ChFrame inverse and  '*' operator, \n";
    mvect1 = mframeA / mvect2;
    GetLog() << mvect1 << " ..inv, using a ChFrame '/' operator, \n";
    ChFrame<> mframeAinv(mframeA);
    mframeAinv.Invert();
    mvect1 = mframeAinv * mvect2;
    GetLog() << mvect1 << " ..inv, using an inverted ChFrame \n";
    // ... also for inverting chain of transformations...
    // mvect3 =  f10 * f21 * f32 * mvect1;              // direct transf..
    mvect1 = (f10 * f21 * f32).GetInverse() * mvect3;  // inverse transf.
    GetLog() << mvect1 << " ..inv three transf \n";
    mvect1 = f32.GetInverse() * f21.GetInverse() * f10.GetInverse() * mvect3;
    GetLog() << mvect1 << " ..inv three transf (another method) \n";
    mvect1 = mvect3 >> (f32 >> f21 >> f10).GetInverse();
    GetLog() << mvect1 << " ..inv three transf (another method) \n";
    mvect1 = mvect3 >> f10.GetInverse() >> f21.GetInverse() >> f32.GetInverse();
    GetLog() << mvect1 << " ..inv three transf (another method) \n";
    //
    // Now test the * and >> operators with some mixed-types operators
    //
    ChFrame<> mframeA1(vtraslA, qrotA);
    ChFrameMoving<> mframemovingB1(vtraslA, qrotA);
    ChFrame<> mresf = mframemovingB1 * mframeA1;
    ChFrameMoving<> mresg = mframeA1 * mframemovingB1;
    //
    // Test some in-place operators, even with mixed-types. Some examples.
    //
    // Transform mframeA1 by rotating & translating by another frame,
    // using the in-place >>= operator, as in  A >>= B,
    // that means:   frameA' = frameA >> frameB  = frameB * frameA
    mframeA1 >>= f10;
    // Transform mframeA1 by translating by a vector:
    mframeA1 >>= ChVector<>(1, 2, 3);
    // Transform mframeA1 by rotating it 30 degrees on axis Y, using a quaternion:
    mframeA1 >>= Q_from_AngAxis(30 * CH_C_DEG_TO_RAD, VECT_Y);
    //
    // BENCHMARK FOR EXECUTION SPEED
    //
    GetLog() << " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \n\n";
    mrotA.Set_A_quaternion(qrotA);
    ChFpMatrix34<> Fp(qrotA);
    ChFmMatrix34<> Fm(qrotA);
    ChGlMatrix34<> Gl(qrotA);
    ChGwMatrix34<> Gw(qrotA);
    ChFrameMoving<> testa(vtraslA, qrotA);
    testa.SetPos_dt(ChVector<>(0.5, 0.6, 0.7));
    testa.SetWvel_loc(ChVector<>(1.1, 2.1, 5.1));
    testa.SetPos_dtdt(ChVector<>(7, 8, 9));
    testa.SetWacc_loc(ChVector<>(4.3, 5.3, 2.3));
    GetLog() << testa << "a moving frame";
    ChVector<> locpos(0.1, 3.1, 1.1);
    ChVector<> locspeed(3.2, 9.2, 7.2);
    ChVector<> locacc(5.3, 3.3, 2.3);
    ChVector<> parentpos = locpos >> testa;
    ChFrameMoving<> testPl(locpos, QUNIT);
    testPl.SetPos_dt(locspeed);
    testPl.SetRot_dt(qrotA);
    testPl.SetWvel_loc(ChVector<>(0.4, 0.5, 0.6));
    testPl.SetPos_dtdt(locacc);
    testPl.SetWacc_loc(ChVector<>(0.43, 0.53, 0.63));
    ChFrameMoving<> testPw;
    ChFrameMoving<> testX;
    testa.TransformLocalToParent(testPl, testPw);
    ChFrameMoving<> bres = (testPl >> testa);
    GetLog() << bres << " trasf loc->abs \n";
    ChQuaternion<> pollo(3, 5, 6, 7);
    ChVector<> pallo(2, 4, 6);
    ChTimer<double> timer;
    int numcycles = 100000;
    int i;
    timer.start();
    for (i = 0; i < 1000000; i++) {
        testa.TransformLocalToParent(testPl, testPw);
    }
    timer.stop();
    // VC6   : 1.380
    // VC2003: 0.861
    // VC2005: 0.691
    // GCC   : 0.661
    timer.start();
    for (i = 0; i < 1000000; i++) {
        mvect2 = mvect1 >> mframeA;
    }
    timer.stop();
    // VC6   : 0.03
    // VC2003: 0.03
    // VC2005: 0.03
    // GCC   : 0.03
    timer.start();
    for (i = 0; i < 1000000; i++) {
        testa.PointAccelerationParentToLocal(vtraslA, vtraslA, vtraslA);
    }
    timer.stop();
    // VC6   : 0.811
    // VC2003: 0.531
    // VC2005: 0.410
    // GCC   : 0.320
    /*
       timer.start();
       for (i= 0; i<numcycles; i++)
       {
           for (int j = 0; j<100; j++)
           {
               mvect2 = mvect1 >> f32 >> f21 >> f10;
               // NOTE: thank to the fact that operators are executed from left to
               // right, the above is MUCH faster (16x) than the equivalent:
               //    mvect2 =  f10 * f21 * f32 * mvect1;
               // because the latter, if no parenthesis are used, would imply
               // three expensive frame*frame operations, and a last frame*vector.
           }
       }
       timer.stop();
       GetLog() << "Test 3 frame transf. with >> ChFrame operator: " <<  timer() << " \n";
       timer.start();
       for (i= 0; i<1000000; i++)
       {
           testa.SetCoord(vtraslA,qrotA);
       }
       timer.stop();
       GetLog() << "Test ChFrame::SetPos() " <<  timer() << " \n";
   //ChQuaternion<> mqdt(1, 2, 3, 4);
       timer.start();
       for (i= 0; i<1000000; i++)
       {
           testa.SetRot_dt(mqdt);
       }
       timer.stop();
       GetLog() << "Test ChFrame::SetRot_dt() " <<  timer() << " \n";
       timer.start();
       for (i= 0; i<1000000; i++)
       {
           testa.SetRot_dtdt(mqdt);
       }
       timer.stop()
       GetLog() << "Test ChFrame::SetRot_dtdt() " <<  timer() << " \n";
   ChVector<> mv(1, 2, 3);
       timer.start();
       for (i= 0; i<1000000; i++)
       {
           testa.SetWvel_loc(mv);
       }
       timer.stop();
       GetLog() << "Test ChFrame::SetWvel_loc() " <<  timer() << " \n";
       timer.start();
       for (i= 0; i<1000000; i++)
       {
           testa.SetWacc_loc(mv);
       }
       timer.stop();
       GetLog() << "Test ChFrame::SetWacc_loc() " <<  timer() << " \n";
       timer.start();
       for (i= 0; i<1000000; i++)
       {
           Vector p= testa.GetWvel_loc();
       }
       timer.stop();
       GetLog() << "Test ChFrame::GetWvel_loc() " <<  timer() << " \n";
       timer.start();
       for (i= 0; i<1000000; i++)
       {
           ChVector<> p= testa.GetWacc_loc();
       }
       timer.stop();
       GetLog() << "Test ChFrame::GetWacc_loc() " <<  timer() << " \n";
   */
    GetLog() << "\n  CHRONO execution terminated.";
    return 0;
}
ChLog & GetLog()
Global function to get the current ChLog object.
Definition: ChLog.cpp:39
Definition of a 3x3 fixed size matrix to represent 3D rotations and inertia tensors.
Definition: ChMatrix33.h:31
void TransformLocalToParent(const ChFrameMoving< Real > &local, ChFrameMoving< Real > &parent) const
This function transforms a frame from 'this' local coordinate system to parent frame coordinate syste...
Definition: ChFrameMoving.h:409
Special MBD 3x4 matrix [Fp(q)], as in [Fp(q)] * [Fm(q)]' = [A(q)].
Definition: ChMatrixMBD.h:48
Special MBD 3x4 matrix [Gw(q)], as in absolute angular speed conversion.
Definition: ChMatrixMBD.h:148
ChQuaternion< double > Q_from_AngAxis(double angle, const ChVector< double > &axis)
Get the quaternion from an angle of rotation and an axis, defined in abs coords.
Definition: ChQuaternion.cpp:100
const ChApi ChQuaternion< double > QUNIT
Constant unit quaternion: {1, 0, 0, 0} , corresponds to no rotation (diagonal rotation matrix)
static ChVector< Real > TransformParentToLocal(const ChVector< Real > &parent, const ChVector< Real > &origin, const ChMatrix33< Real > &alignment)
This function transforms a point from the parent coordinate system to a local coordinate system,...
Definition: ChTransform.h:55
static ChVector< Real > TransformLocalToParent(const ChVector< Real > &local, const ChVector< Real > &origin, const ChMatrix33< Real > &alignment)
This function transforms a point from the local reference frame to the parent reference frame.
Definition: ChTransform.h:79
Definition of general purpose 3d vector variables, such as points in 3D.
Definition: ChVector.h:35
Special MBD 3x4 matrix [Fm(q)], as in [Fp(q)] * [Fm(q)]' = [A(q)].
Definition: ChMatrixMBD.h:71
ChFrameMoving: a class for coordinate systems in 3D space.
Definition: ChFrameMoving.h:38
Class defining quaternion objects, that is four-dimensional numbers, also known as Euler parameters.
Definition: ChQuaternion.h:44
Special MBD 3x4 matrix [Gl(q)], as in local angular speed conversion.
Definition: ChMatrixMBD.h:95
