torque-free motion not giving correct output

Simbody is useful for internal coordinate and coarse grained molecule modeling, large scale mechanical models like skeletons, and anything else that can be modeled as bodies interconnected by joints, acted upon by forces, and restricted by constraints.
POST REPLY
User avatar
Naushad Khan
Posts: 4
Joined: Sun Sep 19, 2021 3:23 am

torque-free motion not giving correct output

Post by Naushad Khan » Wed Nov 17, 2021 2:46 am

Hi,

I want to simulate the torque-free motion of the axis-symmetric(Ix=Iy) body.
Analytical solution of angular velocity
Wx(t) = Wx(0) Cos(lt) - Wy(0)Sin(lt)
Wy(t) = Wx(0) Sin(lt) + Wy(0)Sin(lt)
Wz(t) = Wz(0)
Let's consider Ix = Iy =0.33 and Iz = 0.34 and rest is zero .
Wx(0) = 50 deg/sec
Wy(0) = 50 deg/sec
Wz(0) = 1
Output angular velocity in x and y should be sinusoidal with variation from 70.71 deg to -70.71 deg.



Please find the code to simulate the above.
But I cannot see the system is behaving. All three axis is constant, and there is a slight variation but not with 70.71 deg to -70.71 deg. Would you please help me to find out where I am doing wrong?
Let me know if you need any more information on it.

Code: Select all

int main() {
    try { // Create the system.

        std::ofstream MyFile("Torque_Free_motion.txt");
        MyFile << "time,ang_x,ang_y,ang_z" << "\n";
        MultibodySystem system;
        SimbodyMatterSubsystem matter(system);
        GeneralForceSubsystem forces(system);
        Force::UniformGravity gravity(forces, matter, Vec3(0, 0, 0));
        Force::DiscreteForces discreteForces(forces, matter);

        Body::Rigid pendulumBody(MassProperties(2.0, Vec3(0.0), Inertia(0.33,0.33,0.34)));


        pendulumBody.addDecoration(Transform(), DecorativeBrick(Vec3(0.1)));

        MobilizedBody masterMobod = matter.Ground();

        MobilizedBody::Free pendulum(masterMobod, Transform(Vec3(0, 0, 0)),
                                     pendulumBody, Transform(Vec3(0, 0, 0)));


        // Set up visualization.
        Visualizer viz(system);
        viz.setGroundHeight(0);
        viz.setShowShadows(true);
        viz.setBackgroundType(Visualizer::SolidColor); // default is white
        system.addEventReporter(new Visualizer::Reporter(viz, 1));



        // Initialize the system and state.
        State state =  system.realizeTopology();


        // Simulate it.
        VerletIntegrator integ(system);
        integ.setAccuracy(1e-6); // ask for *lots* of accuracy here (default is 1e-3)

        TimeStepper ts(system, integ);
        ts.initialize(state);

        // Adding initial angular velocity
        double ang_x = 50 * Pi / 180;
        double ang_y = 50 * Pi / 180;
        double ang_z = 1 * Pi / 180;
        pendulum.setUToFitAngularVelocity(integ.updAdvancedState(), Vec3(ang_x, ang_y, ang_z));
        system.realize(integ.getAdvancedState(), Stage::Acceleration);


        for (int i = 0; i < 1000; ++i) {

            auto angular_velocity = pendulum.getBodyAngularVelocity(integ.getAdvancedState());
            auto simTime = integ.getTime();

            MyFile<<simTime<<','<<180/Pi *angular_velocity[0] <<','<<180/Pi *angular_velocity[1]<<','<<180/Pi *angular_velocity[2]<<"\n";
            std::cout << "angular_velocity\t" << simTime << ',' << 180 / Pi * angular_velocity[0] << ','
                      << 180 / Pi * angular_velocity[1] << ',' << 180 / Pi * angular_velocity[2] << "\n";
            ts.stepTo(i);

        }
        MyFile.close();


    } catch (const std::exception &e) {
        std::printf("EXCEPTION THROWN: %s\n", e.what());
        exit(1);

    } catch (...) {
        std::printf("UNKNOWN EXCEPTION THROWN\n");
        exit(1);
    }

    return 0;
}

User avatar
Michael Sherman
Posts: 807
Joined: Fri Apr 01, 2005 6:05 pm

Re: torque-free motion not giving correct output

Post by Michael Sherman » Wed Nov 17, 2021 12:02 pm

Hi, Naushad.

Please take a look at the DzhanibekovEffect example, which I think is similar to what you are trying to do. I suggest you run that one to see what it does. They you might want to modify that code to your specific case.

Regards,
Sherm

User avatar
Naushad Khan
Posts: 4
Joined: Sun Sep 19, 2021 3:23 am

Re: torque-free motion not giving correct output

Post by Naushad Khan » Thu Nov 18, 2021 9:14 am

Dear Michael,

Thank you for the reply. Yes, the DzhanibekovEffect example and my "Torque free motion of an axisymmetric" is a similar condition.

I have copied the "DzhanibekovEffect example" and removed the "barBody" and just kept the shaftBody and its mass properties is
{ mass=1
com=~[0,0,0]
Uxx,yy,zz=~[0.0002,0.000933333,0.000933333]
Uxy,xz,yz=~[0,0,0]
}

So here Iyy = Izz ,

if we set the initial angular velocity as (0.1, 10 , 10 ) deg/sec then

Wx = 0.1 should stay constant where as
Wy and Wy should vary with +14.14 to -14.14 sinusoidal.
But I Cannot see this variation.
Question
1. Is this way is correct way to get angular velocity

Code: Select all

shaft.getBodyAngularVelocity(integ.getState())
2. I have even changed the accuracy setting to 1e-8?

Looking forward to your reply .

I am attaching code here

Code: Select all

#include "Simbody.h"
#include <iostream>

using namespace SimTK;

//==============================================================================
//                              SHOW ENERGY
//==============================================================================
// Generate text in the scene that displays the total energy, which should be
// conserved to roughly the number of decimal places corresponding to the
// accuracy setting (i.e., acc=1e-5 -> 5 digits).
class ShowEnergy : public DecorationGenerator {
public:
    explicit ShowEnergy(const MultibodySystem& mbs) : m_mbs(mbs) {}
    void generateDecorations(const State&                state,
                             Array_<DecorativeGeometry>& geometry) override;
private:
    const MultibodySystem& m_mbs;
};


//==============================================================================
//                                  MAIN
//==============================================================================
int main() {
    try {
        // Create the system.
        MultibodySystem system; system.setUpDirection(ZAxis);
        SimbodyMatterSubsystem matter(system);
        // No gravity or other forces

        matter.setShowDefaultGeometry(true); // turn off frames and other junk

        Rotation YtoX(-Pi/2, ZAxis);
        Body::Rigid shaftBody(MassProperties(1, Vec3(0),
                                             UnitInertia::cylinderAlongX(.02, .05)));
        shaftBody.addDecoration(YtoX,
                                DecorativeCylinder(.02, .05).setColor(Red));


        MobilizedBody::Free shaft(matter.Ground(), Transform(),
                                  shaftBody, Transform());


        // Visualize a frame every 1/60 s, and include the energy.
        Visualizer viz(system); viz.setDesiredFrameRate(60);
        viz.addDecorationGenerator(new ShowEnergy(system));
        system.addEventReporter(new Visualizer::Reporter(viz, 1./60));

        // Initialize the system and state.
        State state = system.realizeTopology();

        // Set initial conditions. Need a slight perturbation of angular velocity
        // to trigger the instability.
        shaft.setQToFitTranslation(state, Vec3(0,0,.5));
        shaft.setUToFitAngularVelocity(state, Vec3(0.1,10,10)); // 10 rad/s

        // Simulate it.
        RungeKuttaMersonIntegrator integ(system);
        integ.setAccuracy(1e-8);

        TimeStepper ts(system, integ);
        ts.initialize(state);
        std::cout << shaftBody.getDefaultRigidBodyMassProperties() << '\n';
        for (int i = 1; i < 1000; i = i +1) {

            const auto& angular_velocity = shaft.getBodyAngularVelocity(integ.getState());
            std::cout<<ts.getTime()<<'\t'<<angular_velocity<<'\n';
            ts.stepTo(float(i));

        }


    } catch(const std::exception& e) {
        std::cout << "EXCEPTION: " << e.what() << std::endl;
        return 1;
    }
    return 0;
}


void ShowEnergy::generateDecorations(const State&                state,
                                     Array_<DecorativeGeometry>& geometry)
{
    m_mbs.realize(state, Stage::Dynamics);
    const Real E=m_mbs.calcEnergy(state);
    DecorativeText energy;
    energy.setTransform(Vec3(-.2,0,.5))
            .setText("Energy: " + String(E, "%.6f"))
            .setScale(.09)
            .setColor(Black);
    geometry.push_back(energy);
}


User avatar
Michael Sherman
Posts: 807
Joined: Fri Apr 01, 2005 6:05 pm

Re: torque-free motion not giving correct output

Post by Michael Sherman » Tue Nov 23, 2021 2:57 pm

Hi, Naushad.

I found a few minor problems with your implementation:
- angular velocity in Simbody is given in radians/sec, not degrees/sec
- angular velocity for a body B is given and reported as w_GB_G, that is, the angular velocity of body B in Ground, expressed in Ground; what you are interested in is w_GB_B, that is, the angular velocity of body B in Ground, expressed in body B! The angular velocity about the long axis (x) is constant in the body frame, but not in Ground since the body is rotating wrt Ground.
- at a small angular velocity like 10 deg/s it takes a very long time for the +/- 14 deg/s cycle to occur.

I'll post some code and results shortly.

Sherm

User avatar
Michael Sherman
Posts: 807
Joined: Fri Apr 01, 2005 6:05 pm

Re: torque-free motion not giving correct output

Post by Michael Sherman » Tue Nov 23, 2021 3:46 pm

Here is a plot of the three components of the angular velocity of the shaft, expressed in the shaft frame. I set the initial conditions to (10, 1000, 1000) degrees/s. The y & z velocities vary between +/- 1414.21 degrees/s.
plot.png
plot.png (72.58 KiB) Viewed 2515 times
The modified code I used is here:

Code: Select all

#include "Simbody.h"
#include <iostream>

using namespace SimTK;

//==============================================================================
//                              SHOW ENERGY
//==============================================================================
// Generate text in the scene that displays the total energy, which should be 
// conserved to roughly the number of decimal places corresponding to the 
// accuracy setting (i.e., acc=1e-5 -> 5 digits).
// Also write to cout the angular velocity w_GS_S for the shaft S.
class ShowEnergy : public DecorationGenerator {
public:
    explicit ShowEnergy(const MultibodySystem& mbs, 
                        const MobilizedBody::Free& shaft)
        : m_mbs(mbs), m_shaft(shaft) {}
    void generateDecorations(const State&                state, 
                             Array_<DecorativeGeometry>& geometry) override;
private:
    const MultibodySystem& m_mbs;
    const MobilizedBody::Free& m_shaft;
};


//==============================================================================
//                                  MAIN
//==============================================================================
int main() {
  try {    
    // Create the system.   
    MultibodySystem system; system.setUpDirection(ZAxis);
    SimbodyMatterSubsystem matter(system);
    // No gravity or other forces

    matter.setShowDefaultGeometry(false); // turn off frames and other junk

    // Construct a single rigid body, a cylindrical shaft.
    Rotation YtoX(-Pi/2, ZAxis);
    Body::Rigid shaftBody(MassProperties(1, Vec3(0),
                            UnitInertia::cylinderAlongX(.02, .05)));
    shaftBody.addDecoration(YtoX,
                            DecorativeCylinder(.02, .05).setColor(Red));

    MobilizedBody::Free shaft(matter.Ground(), Transform(),
                              shaftBody, Transform());

    // Visualize a frame every 1/30 s, and include the energy.
    Visualizer viz(system); viz.setDesiredFrameRate(30);
    viz.addDecorationGenerator(new ShowEnergy(system, shaft));
    system.addEventReporter(new Visualizer::Reporter(viz, 1./30));
    
    // Initialize the system and state. 
    State state = system.realizeTopology();

    // Set initial conditions.
    shaft.setQToFitTranslation(state, Vec3(0,0,.5));
    shaft.setUToFitAngularVelocity(state, Pi/180 * Vec3(10, 1000, 1000)); // 1000 deg/s

    // Simulate it.
    RungeKuttaMersonIntegrator integ(system);
    integ.setAccuracy(1e-7);
    TimeStepper ts(system, integ);
    ts.initialize(state);
    ts.stepTo(100.0);

  } catch(const std::exception& e) {
    std::cout << "EXCEPTION: " << e.what() << std::endl;
    return 1;
  }
    return 0;
}


void ShowEnergy::generateDecorations(const State&                state, 
                                     Array_<DecorativeGeometry>& geometry)
{
    m_mbs.realize(state, Stage::Dynamics);
    const Real E=m_mbs.calcEnergy(state);
    DecorativeText energy;
    energy.setTransform(Vec3(-.2,0,.5))
            .setText("Energy: " + String(E, "%.6f"))
            .setScale(.09)
            .setColor(Black);
    geometry.push_back(energy);

    // Shaft S angular velocity w_GS comes back expressed in G; we want to see it in S.
    const Rotation& R_GS = m_shaft.getBodyRotation(state);
    const auto& R_SG = ~R_GS; // Transpose is inverse.
    const auto w_GS_G = 180/Pi * m_shaft.getBodyAngularVelocity(state);
    const auto w_GS_S = R_SG * w_GS_G;
    // Print this out in an Octave or Matlab-friendly format for plotting.
    std::cout << state.getTime() << '\t' << w_GS_S[0] << ' ' << w_GS_S[1] << ' ' << w_GS_S[2] << '\n';
}

User avatar
Naushad Khan
Posts: 4
Joined: Sun Sep 19, 2021 3:23 am

Re: torque-free motion not giving correct output

Post by Naushad Khan » Wed Nov 24, 2021 7:58 pm

Thank you for the solution :D

User avatar
Michael Sherman
Posts: 807
Joined: Fri Apr 01, 2005 6:05 pm

Re: torque-free motion not giving correct output

Post by Michael Sherman » Thu Nov 25, 2021 11:42 am

You're welcome!

POST REPLY