This is a cute simulation.

>From the code you provided, I take it that you are using an older version of 
>Chrono. I just tried your code with the latest Chrono from the main git 
>branch, and I cannot reproduce the issue.

Regarding your question about ChBodyEasMesh, note that this creates under the 
hood a ChBodyAuxRef (and not a ChBody).  In that case, you probably want to 
control the pose of the reference frame with respect to the global frame. 
However, SetPos and SetRot actually affect the pose of the centroidal frame 
(relative to the global frame).
I know that this is *very* confusing and it’s something I intend to change 
throughout Chrono whenever I will find the time.

In the meantime, I suggest you

  *   Use the latest code in the Chrono main branch
  *   Switch to using Chrono::VSG for run-time visualization (better than 
Irrlicht)

I attached a modification of your code where I

  *   Changed the way the initial body poses are set
  *   Used Chrono::VSG for run-time visualization
  *   Flipped one of the spinning tops
  *   Increased the initial angular velocities to 50 rad/s

Let me know what you get.

Radu

From: [email protected] <[email protected]> On Behalf 
Of kuwt
Sent: Friday, January 9, 2026 2:43 PM
To: ProjectChrono <[email protected]>
Subject: [chrono] Re: Simulation of spinning top collision

Interestingly if I change the object from mesh to simple ChBodyEasyBox(as shown 
below). The weird attraction disappears(video a.mp4). I am not sure if I 
misunderstand
anything for ChBodyEasyMesh. Forgot to mention that i'm using version release 
9.0.

// auto falling = 
chrono_types::make_shared<ChBodyEasyMesh>("../resource/spinningTop1.obj",7000,true,true,true,contact_mat,0.005);
    auto falling = 
chrono_types::make_shared<ChBodyEasyBox>(2,2,2,7000,true,true,contact_mat);
    falling->SetRot(QuatFromAngleY(180 * CH_DEG_TO_RAD));
    falling->SetPos(ChVector3d(3, 0, 0));
    falling->SetAngVelLocal(ChVector3d(0,0, 5));
    sys.Add(falling);

   // auto falling2 = chrono_types::make_shared<ChBodyEasyMesh>( 
"../resource/spinningTop2.obj",7000,true,true,true,contact_mat,0.005);
    auto falling2 = 
chrono_types::make_shared<ChBodyEasyBox>(2,2,2,7000,true,true,contact_mat);
    falling2->SetRot(QuatFromAngleY(180 * CH_DEG_TO_RAD));
    falling2->SetPos(ChVector3d(-3, 0, 0));
    falling2->SetAngVelLocal(ChVector3d(0,0, 5));
    sys.Add(falling2);





On Thursday, 8 January 2026 at 15:05:36 UTC+1 kuwt wrote:
Hello project chrono community,

I want to simulate the collision of two spinning top using project chrono. 
However, I encounter a weird problem that the two spinning top goes towards 
each other. v0.mp4 is a video showing how they go towards each other.. v1.mp4 
is a video showing another viewing angle. I release the two spinning top mid 
air with some angular velocity and let them drop to the floor. I expect they 
will go towards each other after they hit the floor but not during initially 
mid air. I inserted the object as shown in the following code script(whole 
minimal script attached as spinningtop2.cpp. The resources are attached too. I 
made the floor myself. The spinning tops are from github as mentioned in the 
code.):

    auto falling = chrono_types::make_shared<ChBodyEasyMesh>(
        "../resource/spinningTop1.obj",7000,true,true,true,contact_mat,0.005);
    falling->SetRot(QuatFromAngleY(180 * CH_DEG_TO_RAD));
    falling->SetPos(ChVector3d(3, 0, 0));
    falling->SetAngVelLocal(ChVector3d(0,0, 5));
    sys.Add(falling);

    auto falling2 = chrono_types::make_shared<ChBodyEasyMesh>(
        "../resource/spinningTop2.obj",7000,true,true,true,contact_mat,0.005);
    falling2->SetRot(QuatFromAngleY(180 * CH_DEG_TO_RAD));
    falling2->SetPos(ChVector3d(-3, 0, 0));
    falling2->SetAngVelLocal(ChVector3d(0,0, 5));
    sys.Add(falling2);

    auto floor = chrono_types::make_shared<ChBodyEasyMesh>(
        "../resource/floor.obj",7000,true,true,true,contact_mat,0.005);
    floor->SetPos(ChVector3d(0, 0, -3));
    floor->SetFixed(true);
    sys.Add(floor);

Does anybody know what I have misunderstood? Thank you.

--
You received this message because you are subscribed to the Google Groups 
"ProjectChrono" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to 
[email protected]<mailto:[email protected]>.
To view this discussion visit 
https://groups.google.com/d/msgid/projectchrono/c35f6ec9-0d9f-4311-8b8c-f09a3afdbb94n%40googlegroups.com<https://urldefense.com/v3/__https:/groups.google.com/d/msgid/projectchrono/c35f6ec9-0d9f-4311-8b8c-f09a3afdbb94n*40googlegroups.com?utm_medium=email&utm_source=footer__;JQ!!Mak6IKo!IURuo14tx79V4w0442j6WmjWXUdDLjbMh3Y44YSSYSxBO1TM1X5rt1x_f8gaOknaMcEc26tdMrCBs9k$>.

-- 
You received this message because you are subscribed to the Google Groups 
"ProjectChrono" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/projectchrono/CH3PPF46CDC2185AA87D54BB886C5604F41A782A%40CH3PPF46CDC2185.namprd06.prod.outlook.com.
#include "chrono/physics/ChSystemNSC.h"
#include "chrono/physics/ChBodyEasy.h"
#include "chrono/physics/ChMassProperties.h"
#include "chrono/assets/ChTexture.h"
#include "chrono/assets/ChVisualShapeTriangleMesh.h"
#include "chrono/geometry/ChTriangleMeshConnected.h"
#include "chrono/core/ChRandom.h"
#include "chrono/core/ChRealtimeStep.h"

#include "chrono_vsg/ChVisualSystemVSG.h"

// Use the namespaces of Chrono
using namespace chrono;
using namespace chrono::vsg3d;

// adapted from src/demos/mbs/demo_MBS_collision_trimesh.cpp
// texture from https://github.com/tizian/Spinning-Top-Simulation/

// -----------------------------------------------------------------------------
ChCollisionSystem::Type coll_sys_type = ChCollisionSystem::Type::BULLET;
// -----------------------------------------------------------------------------

int main(int argc, char* argv[]) {
    ChRandom::SetSeed(0);

    ChSystemNSC sys;
    sys.SetGravitationalAcceleration(ChVector3d(0, 0, -9.8));
    std::cout << "gravity is " << sys.GetGravitationalAcceleration() << "\n";
    ChCollisionModel::SetDefaultSuggestedEnvelope(0.0025);
    ChCollisionModel::SetDefaultSuggestedMargin(0.0025);
    sys.SetCollisionSystemType(coll_sys_type);

    auto contact_mat = chrono_types::make_shared<ChContactMaterialNSC>();
    contact_mat->SetRestitution(0.4f);
    contact_mat->SetStaticFriction(0.0f);

    double omg1 = 50;
    double omg2 = 50;

    auto falling1 = 
chrono_types::make_shared<ChBodyEasyMesh>("../resource/spinningTop1.obj", 7000, 
true, true, true,
                                                              contact_mat, 
0.005);
    ////falling1->SetFixed(true);
    falling1->SetFrameRefToAbs(ChFramed(ChVector3d(3, 0, 0), 
QuatFromAngleX(CH_PI_2)));
    falling1->SetAngVelLocal(ChVector3d(0, 0, omg1));
    sys.Add(falling1);

    auto falling2 = 
chrono_types::make_shared<ChBodyEasyMesh>("../resource/spinningTop2.obj", 7000, 
true, true, true,
                                                              contact_mat, 
0.005);
    ////falling2->SetFixed(true);
    falling2->SetFrameRefToAbs(ChFramed(ChVector3d(-3, 0, 0), 
QuatFromAngleX(CH_PI_2)));
    falling2->SetAngVelLocal(ChVector3d(0, 0, omg2));
    sys.Add(falling2);

    auto floor =
        chrono_types::make_shared<ChBodyEasyMesh>("../resource/floor.obj", 
7000, true, true, true, contact_mat, 0.005);
    floor->SetPos(ChVector3d(0, 0, -3));
    floor->SetFixed(true);
    sys.Add(floor);

    auto vis = chrono_types::make_shared<ChVisualSystemVSG>();
    vis->AttachSystem(&sys);
    vis->SetWindowTitle("Collision");
    vis->SetCameraVertical(CameraVerticalDir::Y);
    vis->AddCamera(ChVector3d(0, -15, 1), ChVector3d(0, 0, 0));
    vis->SetWindowSize(1280, 800);
    vis->SetWindowPosition(100, 100);
    vis->SetCameraAngleDeg(40.0);
    vis->SetLightIntensity(1.0f);
    vis->SetLightDirection(1.5 * CH_PI_2, CH_PI_4);
    vis->EnableShadows();
    vis->Initialize();

    vis->ToggleRefFrameVisibility();
    vis->SetRefFrameScale(2.0);
    vis->SetContactNormalsVisibility(true);

    ChRealtimeStepTimer realtime_timer;

    double timestep = 5e-4;
    int frame = 0;
    double next_save_time = 0;
    double save_interval = 0.01;

    while (vis->Run()) {
        vis->BeginScene();
        vis->Render();
        vis->EndScene();

        sys.DoStepDynamics(timestep);
        realtime_timer.Spin(timestep);

        ////double cur_time = vis->GetSimulationTime();
        ////char time_text[50];
        ////std::cout << "\rSimulation Time:" << vis->GetSimulationTime() << 
std::flush;
        ////if (cur_time >= next_save_time) {
        ////    char filename[100];
        ////    sprintf(filename, "frames/frame_%04d.png", frame++);
        ////    vis->WriteImageToFile(filename);
        ////    std::cout << "Saving at t = " << cur_time << std::endl;
        ////    next_save_time += save_interval;
        ////}
    }

    return 0;
}

Reply via email to