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); }
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; }
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.. */ }