예제 #1
0
void create_some_falling_items(ChSystemNSC& mphysicalSystem) {
    // From now on, all created collision models will have a large outward envelope (needed
    // to allow some compliance with the plastic deformation of cohesive bounds
    ChCollisionModel::SetDefaultSuggestedEnvelope(0.3);

    for (int bi = 0; bi < 400; bi++) {
        // Create a bunch of ChronoENGINE rigid bodies which will fall..

        auto mrigidBody = std::make_shared<ChBodyEasySphere>(0.81,   // radius
                                                             1000,   // density
                                                             true,   // collide enable?
                                                             true);  // visualization?
        mrigidBody->SetPos(ChVector<>(-5 + ChRandom() * 10, 4 + bi * 0.05, -5 + ChRandom() * 10));
        mrigidBody->GetMaterialSurfaceNSC()->SetFriction(0.3f);

        mphysicalSystem.Add(mrigidBody);
    }

    // Create the five walls of the rectangular container, using
    // fixed rigid bodies of 'box' type:

    auto floorBody = std::make_shared<ChBodyEasyBox>(20, 1, 20,  // x,y,z size
                                                     1000,       // density
                                                     true,       // collide enable?
                                                     true);      // visualization?
    floorBody->SetPos(ChVector<>(0, -5, 0));
    floorBody->SetBodyFixed(true);

    mphysicalSystem.Add(floorBody);

    auto wallBody1 = std::make_shared<ChBodyEasyBox>(1, 10, 20.99,  // x,y,z size
                                                     1000,          // density
                                                     true,          // collide enable?
                                                     true);         // visualization?
    wallBody1->SetPos(ChVector<>(-10, 0, 0));
    wallBody1->SetBodyFixed(true);

    mphysicalSystem.Add(wallBody1);

    auto wallBody2 = std::make_shared<ChBodyEasyBox>(1, 10, 20.99,  // x,y,z size
                                                     1000,          // density
                                                     true,          // collide enable?
                                                     true);         // visualization?
    wallBody2->SetPos(ChVector<>(10, 0, 0));
    wallBody2->SetBodyFixed(true);

    mphysicalSystem.Add(wallBody2);

    auto wallBody3 = std::make_shared<ChBodyEasyBox>(20.99, 10, 1,  // x,y,z size
                                                     1000,          // density
                                                     true,          // collide enable?
                                                     true);         // visualization?
    wallBody3->SetPos(ChVector<>(0, 0, -10));
    wallBody3->SetBodyFixed(true);

    mphysicalSystem.Add(wallBody3);

    auto wallBody4 = std::make_shared<ChBodyEasyBox>(20.99, 10, 1,  // x,y,z size
                                                     1000,          // density
                                                     true,          // collide enable?
                                                     true);         // visualization?
    wallBody4->SetPos(ChVector<>(0, 0, 10));
    wallBody4->SetBodyFixed(true);

    mphysicalSystem.Add(wallBody4);

    // Add the rotating mixer
    auto rotatingBody = std::make_shared<ChBodyEasyBox>(10, 5, 1,  // x,y,z size
                                                        4000,      // density
                                                        true,      // collide enable?
                                                        true);     // visualization?
    rotatingBody->SetPos(ChVector<>(0, -1.6, 0));
    rotatingBody->GetMaterialSurfaceNSC()->SetFriction(0.4f);

    mphysicalSystem.Add(rotatingBody);

    // .. an engine between mixer and truss
    auto my_motor = std::make_shared<ChLinkEngine>();
    my_motor->Initialize(rotatingBody, floorBody, ChCoordsys<>(ChVector<>(0, 0, 0), Q_from_AngAxis(CH_C_PI_2, VECT_X)));
    my_motor->Set_eng_mode(ChLinkEngine::ENG_MODE_SPEED);
    if (auto mfun = std::dynamic_pointer_cast<ChFunction_Const>(my_motor->Get_spe_funct()))
        mfun->Set_yconst(CH_C_PI / 2.0);  // speed w=90�/s
    mphysicalSystem.AddLink(my_motor);
}
예제 #2
0
int main(int argc, char* argv[]) {
    GetLog() << "Copyright (c) 2017 projectchrono.org\nChrono version: " << CHRONO_VERSION << "\n\n";

    // Create a ChronoENGINE physical system
    ChSystemNSC mphysicalSystem;

    // Create the Irrlicht visualization (open the Irrlicht device,
    // bind a simple user interface, etc. etc.)
    ChIrrApp application(&mphysicalSystem, L"Gears and pulleys", core::dimension2d<u32>(800, 600), false);

    // Easy shortcuts to add camera, lights, logo and sky in Irrlicht scene:
    ChIrrWizard::add_typical_Logo(application.GetDevice());
    ChIrrWizard::add_typical_Sky(application.GetDevice());
    ChIrrWizard::add_typical_Lights(application.GetDevice());
    ChIrrWizard::add_typical_Camera(application.GetDevice(), core::vector3df(12, 15, -20));

    // Create all the rigid bodies.

    double radA = 2;
    double radB = 4;

    // ...the truss
    auto mbody_truss = std::make_shared<ChBodyEasyBox>(20, 10, 2, 1000, false, true);
    mphysicalSystem.Add(mbody_truss);
    mbody_truss->SetBodyFixed(true);
    mbody_truss->SetPos(ChVector<>(0, 0, 3));

    // ...a texture asset that will be shared among the four wheels
    auto cylinder_texture = std::make_shared<ChTexture>(GetChronoDataFile("pinkwhite.png"));

    // ...the rotating bar support for the two epicycloidal wheels
    auto mbody_train = std::make_shared<ChBodyEasyBox>(8, 1.5, 1.0, 1000, false, true);
    mphysicalSystem.Add(mbody_train);
    mbody_train->SetPos(ChVector<>(3, 0, 0));

    // ...which must rotate respect to truss along Z axis, in 0,0,0,
    auto link_revoluteTT = std::make_shared<ChLinkLockRevolute>();
    link_revoluteTT->Initialize(mbody_truss, mbody_train,
                                ChCoordsys<>(ChVector<>(0, 0, 0), QUNIT));
    mphysicalSystem.AddLink(link_revoluteTT);

    // ...the first gear
    auto mbody_gearA = std::make_shared<ChBodyEasyCylinder>(radA, 0.5, 1000, false, true);
    mphysicalSystem.Add(mbody_gearA);
    mbody_gearA->SetPos(ChVector<>(0, 0, -1));
    mbody_gearA->SetRot(Q_from_AngAxis(CH_C_PI / 2, VECT_X));
    mbody_gearA->AddAsset(cylinder_texture);
    // for aesthetic reasons, also add a thin cylinder only as a visualization:
    auto mshaft_shape = std::make_shared<ChCylinderShape>();
    mshaft_shape->GetCylinderGeometry().p1 = ChVector<>(0,-3,0);
    mshaft_shape->GetCylinderGeometry().p2 = ChVector<>(0, 10,0);
    mshaft_shape->GetCylinderGeometry().rad = radA*0.4;
    mbody_gearA->AddAsset(mshaft_shape);

    // ...impose rotation between the first gear and the fixed truss
    auto link_engine = std::make_shared<ChLinkEngine>();
    link_engine->Initialize(mbody_gearA, mbody_truss, ChCoordsys<>(ChVector<>(0, 0, 0), QUNIT));
    link_engine->Set_shaft_mode(ChLinkEngine::ENG_SHAFT_LOCK);  // also works as revolute support
    link_engine->Set_eng_mode(ChLinkEngine::ENG_MODE_SPEED);
    if (auto mfun = std::dynamic_pointer_cast<ChFunction_Const>(link_engine->Get_spe_funct()))
        mfun->Set_yconst(6);  // rad/s  angular speed
    mphysicalSystem.AddLink(link_engine);

    // ...the second gear
    double interaxis12 = radA + radB;
    auto mbody_gearB = std::make_shared<ChBodyEasyCylinder>(radB, 0.4, 1000, false, true);
    mphysicalSystem.Add(mbody_gearB);
    mbody_gearB->SetPos(ChVector<>(interaxis12, 0, -1));
    mbody_gearB->SetRot(Q_from_AngAxis(CH_C_PI / 2, VECT_X));
    mbody_gearB->AddAsset(cylinder_texture);

    // ... the second gear is fixed to the rotating bar
    auto link_revolute = std::make_shared<ChLinkLockRevolute>();
    link_revolute->Initialize(mbody_gearB, mbody_train,
                              ChCoordsys<>(ChVector<>(interaxis12, 0, 0), QUNIT));
    mphysicalSystem.AddLink(link_revolute);

    // ...the gear constraint between the two wheels A and B.
    //    As transmission ratio (=speed of wheel B / speed of wheel A) to enter in  Set_tau(), we
    //    could use whatever positive value we want: the ChLinkGear will compute the two radii of the
    //    wheels for its 'hidden' computations, given the distance between the two axes. However, since
    //    we already build two '3D cylinders' bodies -just for visualization reasons!- with radA and radB,
    //    we must enter Set_tau(radA/radB).
    //    Also, note that the initial position of the constraint has no importance (simply use CSYSNORM),
    //    but we must set where the two axes are placed in the local coordinates of the two wheels, so
    //    we use Set_local_shaft1() and pass some local ChFrame. Note that, since the Z axis of that frame
    //    will be considered the axis of the wheel, we must rotate the frame 90° with Q_from_AngAxis(), because
    //    we created the wheel with ChBodyEasyCylinder() which created a cylinder with Y as axis.
    auto link_gearAB = std::make_shared<ChLinkGear>();
    link_gearAB->Initialize(mbody_gearA, mbody_gearB, CSYSNORM);
    link_gearAB->Set_local_shaft1(ChFrame<>(VNULL, chrono::Q_from_AngAxis(-CH_C_PI / 2, VECT_X)));
    link_gearAB->Set_local_shaft2(ChFrame<>(VNULL, chrono::Q_from_AngAxis(-CH_C_PI / 2, VECT_X)));
    link_gearAB->Set_tau(radA / radB);
    link_gearAB->Set_checkphase(true);
    mphysicalSystem.AddLink(link_gearAB);

    // ...the gear constraint between the second wheel B and a large wheel C with inner teeth, that
    //    does not necessarily need to be created as a new body because it is the 'fixed' part of the
    //    epicycloidal reducer, so, as wheel C, we will simply use the ground object 'mbody_truss'.
    double radC = 2 * radB + radA;
    auto link_gearBC = std::make_shared<ChLinkGear>();
    link_gearBC->Initialize(mbody_gearB, mbody_truss, CSYSNORM);
    link_gearBC->Set_local_shaft1(ChFrame<>(VNULL, chrono::Q_from_AngAxis(-CH_C_PI / 2, VECT_X)));
    link_gearBC->Set_local_shaft2(ChFrame<>(ChVector<>(0, 0, -4), QUNIT));
    link_gearBC->Set_tau(radB / radC);
    link_gearBC->Set_epicyclic(true);  // <-- this means: use a wheel with internal teeth!
    mphysicalSystem.AddLink(link_gearBC);

    // ...the bevel gear at the side,
    double radD = 5;
    auto mbody_gearD = std::make_shared<ChBodyEasyCylinder>(radD, 0.8, 1000, false, true);
    mphysicalSystem.Add(mbody_gearD);
    mbody_gearD->SetPos(ChVector<>(-10, 0, -9));
    mbody_gearD->SetRot(Q_from_AngAxis(CH_C_PI / 2, VECT_Z));
    mbody_gearD->AddAsset(cylinder_texture);

    // ... it is fixed to the truss using a revolute joint with horizontal axis (must rotate
    //     default ChLink creation coordys 90° on the Y vertical, since the revolute axis is the Z axis).
    auto link_revoluteD = std::make_shared<ChLinkLockRevolute>();
    link_revoluteD->Initialize(mbody_gearD, mbody_truss,
                               ChCoordsys<>(ChVector<>(-10, 0, -9), Q_from_AngAxis(CH_C_PI / 2, VECT_Y)));
    mphysicalSystem.AddLink(link_revoluteD);

    // ... Let's make a 1:1 gear between wheel A and wheel D as a bevel gear: chrono::engine does not require
    //     special info for this case -the position of the two shafts and the transmission ratio are enough-
    auto link_gearAD = std::make_shared<ChLinkGear>();
    link_gearAD->Initialize(mbody_gearA, mbody_gearD, CSYSNORM);
    link_gearAD->Set_local_shaft1(ChFrame<>(ChVector<>(0, -7, 0), chrono::Q_from_AngAxis(-CH_C_PI / 2, VECT_X)));
    link_gearAD->Set_local_shaft2(ChFrame<>(ChVector<>(0, -7, 0), chrono::Q_from_AngAxis(-CH_C_PI / 2, VECT_X)));
    link_gearAD->Set_tau(1);
    mphysicalSystem.AddLink(link_gearAD);

    // ...the pulley at the side,
    double radE = 2;
    auto mbody_pulleyE = std::make_shared<ChBodyEasyCylinder>(radE, 0.8, 1000, false, true);
    mphysicalSystem.Add(mbody_pulleyE);
    mbody_pulleyE->SetPos(ChVector<>(-10, -11, -9));
    mbody_pulleyE->SetRot(Q_from_AngAxis(CH_C_PI / 2, VECT_Z));
    mbody_pulleyE->AddAsset(cylinder_texture);

    // ... it is fixed to the truss using a revolute joint with horizontal axis (must rotate
    //     default ChLink creation coordys 90° on the Y vertical, since the revolute axis is the Z axis).
    auto link_revoluteE = std::make_shared<ChLinkLockRevolute>();
    link_revoluteE->Initialize(mbody_pulleyE, mbody_truss,
                               ChCoordsys<>(ChVector<>(-10, -11, -9), Q_from_AngAxis(CH_C_PI / 2, VECT_Y)));
    mphysicalSystem.AddLink(link_revoluteE);

    // ... Let's make a synchro belt constraint between pulley D and pulley E. The user must be
    //     sure that the two shafts are parallel in absolute space. Also, interaxial distance should not change.
    auto link_pulleyDE = std::make_shared<ChLinkPulley>();
    link_pulleyDE->Initialize(mbody_gearD, mbody_pulleyE, CSYSNORM);
    link_pulleyDE->Set_local_shaft1(ChFrame<>(VNULL, chrono::Q_from_AngAxis(-CH_C_PI / 2, VECT_X)));
    link_pulleyDE->Set_local_shaft2(ChFrame<>(VNULL, chrono::Q_from_AngAxis(-CH_C_PI / 2, VECT_X)));
    link_pulleyDE->Set_r1(radD);
    link_pulleyDE->Set_r2(radE);
    link_pulleyDE->Set_checkphase(true); // synchro belts don't tolerate slipping: this avoids it as numerical errors accumulate.
    mphysicalSystem.AddLink(link_pulleyDE);


    
    // Use this function for adding a ChIrrNodeAsset to all items
    // Otherwise use application.AssetBind(myitem); on a per-item basis.
    application.AssetBindAll();

    // Use this function for 'converting' assets into Irrlicht meshes
    application.AssetUpdateAll();

    // Prepare the physical system for the simulation

    mphysicalSystem.SetTimestepperType(ChTimestepper::Type::EULER_IMPLICIT_PROJECTED);

    //
    // THE SOFT-REAL-TIME CYCLE
    //
    application.SetStepManage(true);
    application.SetTimestep(0.01);
    application.SetTryRealtime(true);

    while (application.GetDevice()->run()) {
        application.BeginScene(true, true, SColor(255, 140, 161, 192));

        application.DrawAll();

        // .. draw also some circle lines representing gears - just for aesthetical reasons

        ChIrrTools::drawCircle(application.GetVideoDriver(), link_gearBC->Get_r2(),
                               (link_gearBC->Get_local_shaft2() >> *link_gearBC->GetBody2()).GetCoord(),
                               video::SColor(255, 255, 0, 0), 50, true);
        ChIrrTools::drawCircle(application.GetVideoDriver(), link_gearAD->Get_r1(),
                               (link_gearAD->Get_local_shaft1() >> *link_gearAD->GetBody1()).GetCoord(),
                               video::SColor(255, 255, 0, 0), 30, true);
        ChIrrTools::drawCircle(application.GetVideoDriver(), link_gearAD->Get_r2(),
                               (link_gearAD->Get_local_shaft2() >> *link_gearAD->GetBody2()).GetCoord(),
                               video::SColor(255, 255, 0, 0), 30, true);

        ChIrrTools::drawCircle(application.GetVideoDriver(), 0.1,
                               ChCoordsys<>(link_gearAB->GetMarker2()->GetAbsCoord().pos, QUNIT));
        ChIrrTools::drawCircle(application.GetVideoDriver(), 0.1,
                               ChCoordsys<>(link_gearAD->GetMarker2()->GetAbsCoord().pos, QUNIT));
        ChIrrTools::drawCircle(application.GetVideoDriver(), 0.1,
                               ChCoordsys<>(link_gearBC->GetMarker2()->GetAbsCoord().pos, QUNIT));

        // ..draw also some segments for a simplified representation of pulley
        ChIrrTools::drawSegment(application.GetVideoDriver(), link_pulleyDE->Get_belt_up1(),
                                link_pulleyDE->Get_belt_up2(), video::SColor(255, 0, 255, 0), true);
        ChIrrTools::drawSegment(application.GetVideoDriver(), link_pulleyDE->Get_belt_low1(),
                                link_pulleyDE->Get_belt_low2(), video::SColor(255, 0, 255, 0), true);

        // ADVANCE THE SIMULATION FOR ONE STEP

        application.DoStep();

        application.EndScene();
    }

    return 0;
}
예제 #3
0
int main(int argc, char* argv[]) {
    GetLog() << "Copyright (c) 2017 projectchrono.org\nChrono version: " << CHRONO_VERSION << "\n\n";

    // Create the system
    // Set gravitational acceleration to zero
    ChSystemNSC system;
    system.Set_G_acc(ChVector<>(0, 0, 0));

    // Create the ground body
    auto ground = std::make_shared<ChBodyEasyBox>(3, 2, 0.1, 10, false, true);
    system.AddBody(ground);
    ground->SetBodyFixed(true);

    // Create the sliding body
    // Give an initial angular velocity
    auto body = std::make_shared<ChBodyEasyBox>(0.5, 0.5, 0.5, 10, false, true);
    system.AddBody(body);
    body->SetBodyFixed(false);
    body->SetPos(ChVector<>(-1.25, -0.75, 0.1));
    body->SetWvel_loc(ChVector<>(0.1, 0.1, 0.1));

    auto body_col = std::make_shared<ChColorAsset>();
    body_col->SetColor(ChColor(0.6f, 0, 0));
    body->AddAsset(body_col);

    // Create the plane-plane constraint
    // Constrain the sliding body to move and rotate in the x-y plane
    // (i.e. the plane whose normal is the z-axis of the specified coord sys)
    auto plane_plane = std::make_shared<ChLinkLockPlanePlane>();
    plane_plane->Initialize(ground, body, ChCoordsys<>(ChVector<>(-1.25, -0.75, 0), ChQuaternion<>(1, 0, 0, 0)));
    system.AddLink(plane_plane);

    // Create a linear spring (with default spring & damping coefficients)
    auto spring = std::make_shared<ChLinkSpring>();
    spring->Initialize(ground, body, true, ChVector<>(0, 0, 2), ChVector<>(0, 0, 0), false, 1.9);
    system.AddLink(spring);

    // Create the Irrlicht application
    ChIrrApp application(&system, L"ChLinkLockPlanePlane", irr::core::dimension2d<irr::u32>(800, 600), false, true);
    application.AddTypicalLogo();
    application.AddTypicalSky();
    application.AddTypicalLights();
    application.AddTypicalCamera(irr::core::vector3df(3, 0, 3));

    application.AssetBindAll();
    application.AssetUpdateAll();

    // Simulation loop
    application.SetTimestep(0.005);

    while (application.GetDevice()->run()) {
        application.BeginScene();
        application.DrawAll();
        ChIrrTools::drawSpring(application.GetVideoDriver(), 0.05, spring->GetEndPoint1Abs(), spring->GetEndPoint2Abs(),
                               irr::video::SColor(0, 255, 255, 100), 80, 15, true);
        ChIrrTools::drawAllCOGs(system, application.GetVideoDriver(), 2);
        application.EndScene();
        application.DoStep();
    }

    return 0;
}
void create_some_falling_items(ChSystemNSC& mphysicalSystem, ISceneManager* msceneManager, IVideoDriver* driver) {
    for (int bi = 0; bi < 29; bi++) {
        // Create a bunch of ChronoENGINE rigid bodies (spheres and
        // boxes etc.) which will fall..

        auto msphereBody = std::make_shared<ChBodyEasySphere>(1.1,    // radius size
                                                              1000,   // density
                                                              true,   // collide enable?
                                                              true);  // visualization?
        msphereBody->SetPos(ChVector<>(-5 + ChRandom() * 10, 4 + bi * 0.05, -5 + ChRandom() * 10));
        msphereBody->GetMaterialSurfaceNSC()->SetFriction(0.2f);

        mphysicalSystem.Add(msphereBody);

        // optional, attach a texture for better visualization
        auto mtexture = std::make_shared<ChTexture>();
        mtexture->SetTextureFilename(GetChronoDataFile("bluwhite.png"));
        msphereBody->AddAsset(mtexture);

        auto mboxBody = std::make_shared<ChBodyEasyBox>(1.5, 1.5, 1.5,  // x,y,z size
                                                        100,            // density
                                                        true,           // collide enable?
                                                        true);          // visualization?
        mboxBody->SetPos(ChVector<>(-5 + ChRandom() * 10, 4 + bi * 0.05, -5 + ChRandom() * 10));

        mphysicalSystem.Add(mboxBody);

        // optional, attach a texture for better visualization
        auto mtexturebox = std::make_shared<ChTexture>();
        mtexturebox->SetTextureFilename(GetChronoDataFile("cubetexture_bluwhite.png"));
        mboxBody->AddAsset(mtexturebox);

        auto mcylBody = std::make_shared<ChBodyEasyCylinder>(0.75, 0.5,  // radius, height
                                                             100,        // density
                                                             true,       // collide enable?
                                                             true);      // visualization?
        mcylBody->SetPos(ChVector<>(-5 + ChRandom() * 10, 4 + bi * 0.05, -5 + ChRandom() * 10));

        mphysicalSystem.Add(mcylBody);

        // optional, attach a texture for better visualization
        auto mtexturecyl = std::make_shared<ChTexture>();
        mtexturecyl->SetTextureFilename(GetChronoDataFile("pinkwhite.png"));
        mcylBody->AddAsset(mtexturecyl);
    }

    // Create the five walls of the rectangular container, using
    // fixed rigid bodies of 'box' type:

    auto floorBody = std::make_shared<ChBodyEasyBox>(20, 1, 20, 1000, true, true);
    floorBody->SetPos(ChVector<>(0, -5, 0));
    floorBody->SetBodyFixed(true);

    mphysicalSystem.Add(floorBody);

    auto wallBody1 = std::make_shared<ChBodyEasyBox>(1, 10, 20.99, 1000, true, true);
    wallBody1->SetPos(ChVector<>(-10, 0, 0));
    wallBody1->SetBodyFixed(true);

    mphysicalSystem.Add(wallBody1);

    auto wallBody2 = std::make_shared<ChBodyEasyBox>(1, 10, 20.99, 1000, true, true);
    wallBody2->SetPos(ChVector<>(10, 0, 0));
    wallBody2->SetBodyFixed(true);

    mphysicalSystem.Add(wallBody2);

    auto wallBody3 = std::make_shared<ChBodyEasyBox>(20.99, 10, 1, 1000, true, true);
    wallBody3->SetPos(ChVector<>(0, 0, -10));
    wallBody3->SetBodyFixed(true);

    mphysicalSystem.Add(wallBody3);

    auto wallBody4 = std::make_shared<ChBodyEasyBox>(20.99, 10, 1, 1000, true, true);
    wallBody4->SetPos(ChVector<>(0, 0, 10));
    wallBody4->SetBodyFixed(true);

    mphysicalSystem.Add(wallBody4);

    // optional, attach  textures for better visualization
    auto mtexturewall = std::make_shared<ChTexture>();
    mtexturewall->SetTextureFilename(GetChronoDataFile("concrete.jpg"));
    wallBody1->AddAsset(mtexturewall);  // note: most assets can be shared
    wallBody2->AddAsset(mtexturewall);
    wallBody3->AddAsset(mtexturewall);
    wallBody4->AddAsset(mtexturewall);
    floorBody->AddAsset(mtexturewall);

    // Add the rotating mixer
    auto rotatingBody = std::make_shared<ChBodyEasyBox>(10, 5, 1,        // x,y,z size
                                                        4000,            // density
                                                        true,            // collide enable?
                                                        true);           // visualization?
    rotatingBody->SetPos(ChVector<>(0, -1.6, 0));
    rotatingBody->GetMaterialSurfaceNSC()->SetFriction(0.4f);

    mphysicalSystem.Add(rotatingBody);

    // .. a motor between mixer and truss

    auto my_motor = std::make_shared<ChLinkMotorRotationSpeed>();
    my_motor->Initialize(rotatingBody, floorBody, ChFrame<>(ChVector<>(0, 0, 0), Q_from_AngAxis(CH_C_PI_2, VECT_X)));
    auto mfun = std::make_shared<ChFunction_Const>(CH_C_PI / 2.0);  // speed w=90°/s
    my_motor->SetSpeedFunction(mfun);
    mphysicalSystem.AddLink(my_motor);

    /*

    /// NOTE: Instead of creating five separate 'box' bodies to make
    /// the walls of the bowl, you could have used a single body
    /// made of five box shapes, which build a single collision description,
    /// as in the alternative approach:

        // create a plain ChBody (no colliding shape nor visualization mesh is used yet)
    auto mrigidBody = std::make_shared<ChBody>();

        // set the ChBodySceneNode as fixed body, and turn collision ON, otherwise no collide by default
    mrigidBody->SetBodyFixed(true);
    mrigidBody->SetCollide(true);

        // Clear model. The colliding shape description MUST be between  ClearModel() .. BuildModel() pair.
    mrigidBody->GetCollisionModel()->ClearModel();
        // Describe the (invisible) colliding shape by adding five boxes (the walls and floor)
    mrigidBody->GetCollisionModel()->AddBox(20,1,20, ChVector<>(  0,-10,  0));
    mrigidBody->GetCollisionModel()->AddBox(1,40,20, ChVector<>(-11,  0,  0));
    mrigidBody->GetCollisionModel()->AddBox(1,40,20, ChVector<>( 11,  0,  0));
    mrigidBody->GetCollisionModel()->AddBox(20,40,1, ChVector<>(  0,  0,-11));
    mrigidBody->GetCollisionModel()->AddBox(20,40,1, ChVector<>(  0,  0, 11));
        // Complete the description of collision shape.
    mrigidBody->GetCollisionModel()->BuildModel();

        // Attach some visualization shapes if needed:
    auto vshape = std::make_shared<ChBoxShape>();
    vshape->GetBoxGeometry().SetLengths( ChVector<> (20,1,20) );
    vshape->GetBoxGeometry().Pos = ChVector<> (0,-5,0);
    this->AddAsset( vshape );
    // etc. for other 4 box shapes..
    */
}