Collision example (demo_IRR_collisionNSC.cpp)
An introductory tutorial about collisions using Non-Smooth Contacts (NSC).
A bunch of random shapes will fall into a box, stacking in random order, while a mixer blade rotates.
Learn about:
- how to enable collisions
- how to change the settings of the stepper in sake of higher precision or higher computing speed.
- create a motor between two parts.
// =============================================================================
// 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 code about
// - collisions and contacts
// - using Irrlicht to display objects.
//
// =============================================================================
#include "chrono/physics/ChSystemNSC.h"
#include "chrono/physics/ChBodyEasy.h"
#include "chrono/physics/ChLinkMotorRotationSpeed.h"
#include "chrono/assets/ChTexture.h"
#include "chrono/core/ChRealtimeStep.h"
#ifdef CHRONO_COLLISION
#include "chrono/collision/ChCollisionSystemChrono.h"
#endif
#include "chrono_irrlicht/ChIrrApp.h"
// Use the namespaces of Chrono
using namespace chrono;
using namespace chrono::irrlicht;
// Use the main namespaces of Irrlicht
using namespace irr;
using namespace irr::core;
collision::ChCollisionSystemType collision_type = collision::ChCollisionSystemType::BULLET;
void AddFallingItems(ChSystemNSC& sys) {
// Shared contact materials for falling objects
auto sph_mat = chrono_types::make_shared<ChMaterialSurfaceNSC>();
sph_mat->SetFriction(0.2f);
auto box_mat = chrono_types::make_shared<ChMaterialSurfaceNSC>();
auto cyl_mat = chrono_types::make_shared<ChMaterialSurfaceNSC>();
// Create falling rigid bodies (spheres and boxes etc.)
for (int bi = 0; bi < 29; bi++) {
auto msphereBody = chrono_types::make_shared<ChBodyEasySphere>(1.1, // radius size
1000, // density
sph_mat, // contact material
collision_type);
sys.Add(msphereBody);
auto mtexture = chrono_types::make_shared<ChTexture>();
mtexture->SetTextureFilename(GetChronoDataFile("textures/bluewhite.png"));
msphereBody->AddAsset(mtexture);
auto mboxBody = chrono_types::make_shared<ChBodyEasyBox>(1.5, 1.5, 1.5, // x,y,z size
100, // density
box_mat, // contact material
collision_type);
sys.Add(mboxBody);
auto mtexturebox = chrono_types::make_shared<ChTexture>();
mtexturebox->SetTextureFilename(GetChronoDataFile("textures/cubetexture_bluewhite.png"));
mboxBody->AddAsset(mtexturebox);
auto mcylBody = chrono_types::make_shared<ChBodyEasyCylinder>(0.75, 0.5, // radius, height
100, // density
cyl_mat, // contact material
collision_type);
sys.Add(mcylBody);
// optional, attach a texture for better visualization
auto mtexturecyl = chrono_types::make_shared<ChTexture>();
mtexturecyl->SetTextureFilename(GetChronoDataFile("textures/pinkwhite.png"));
mcylBody->AddAsset(mtexturecyl);
}
}
std::shared_ptr<ChBody> AddContainer(ChSystemNSC& sys) {
// Contact material for container
auto ground_mat = chrono_types::make_shared<ChMaterialSurfaceNSC>();
// Create the five walls of the rectangular container, using fixed rigid bodies of 'box' type
auto floorBody = chrono_types::make_shared<ChBodyEasyBox>(20, 1, 20, 1000, ground_mat, collision_type);
floorBody->SetPos(ChVector<>(0, -5, 0));
floorBody->SetBodyFixed(true);
sys.Add(floorBody);
auto wallBody1 = chrono_types::make_shared<ChBodyEasyBox>(1, 10, 20.99, 1000, ground_mat, collision_type);
wallBody1->SetPos(ChVector<>(-10, 0, 0));
wallBody1->SetBodyFixed(true);
sys.Add(wallBody1);
auto wallBody2 = chrono_types::make_shared<ChBodyEasyBox>(1, 10, 20.99, 1000, ground_mat, collision_type);
wallBody2->SetPos(ChVector<>(10, 0, 0));
wallBody2->SetBodyFixed(true);
sys.Add(wallBody2);
auto wallBody3 = chrono_types::make_shared<ChBodyEasyBox>(20.99, 10, 1, 1000, ground_mat, collision_type);
wallBody3->SetPos(ChVector<>(0, 0, -10));
wallBody3->SetBodyFixed(true);
sys.Add(wallBody3);
auto wallBody4 = chrono_types::make_shared<ChBodyEasyBox>(20.99, 10, 1, 1000, ground_mat, collision_type);
wallBody4->SetPos(ChVector<>(0, 0, 10));
wallBody4->SetBodyFixed(true);
sys.Add(wallBody4);
// optional, attach textures for better visualization
auto mtexturewall = chrono_types::make_shared<ChTexture>();
mtexturewall->SetTextureFilename(GetChronoDataFile("textures/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 mixer_mat = chrono_types::make_shared<ChMaterialSurfaceNSC>();
mixer_mat->SetFriction(0.4f);
auto rotatingBody = chrono_types::make_shared<ChBodyEasyBox>(10, 5, 1, // x,y,z size
4000, // density
mixer_mat, // contact material
collision_type);
rotatingBody->SetPos(ChVector<>(0, -1.6, 0));
sys.Add(rotatingBody);
// .. a motor between mixer and truss
auto my_motor = chrono_types::make_shared<ChLinkMotorRotationSpeed>();
my_motor->Initialize(rotatingBody, floorBody, ChFrame<>(ChVector<>(0, 0, 0), Q_from_AngAxis(CH_C_PI_2, VECT_X)));
auto mfun = chrono_types::make_shared<ChFunction_Const>(CH_C_PI / 4.0); // speed 45 deg/s
my_motor->SetSpeedFunction(mfun);
sys.AddLink(my_motor);
/*
// create a plain ChBody (no colliding shape nor visualization mesh is used yet)
auto mrigidBody = chrono_types::make_shared<ChBody>(collision_type);
// set 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(ground_mat, 20, 1, 20, ChVector<>(0, -10, 0));
mrigidBody->GetCollisionModel()->AddBox(ground_mat, 1, 40, 20, ChVector<>(-11, 0, 0));
mrigidBody->GetCollisionModel()->AddBox(ground_mat, 1, 40, 20, ChVector<>(11, 0, 0));
mrigidBody->GetCollisionModel()->AddBox(ground_mat, 20, 40, 1, ChVector<>(0, 0, -11));
mrigidBody->GetCollisionModel()->AddBox(ground_mat, 20, 40, 1, ChVector<>(0, 0, 11));
// Complete the description of collision shape.
mrigidBody->GetCollisionModel()->BuildModel();
// Attach some visualization shapes if needed:
auto vshape = chrono_types::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..
*/
return rotatingBody;
}
int main(int argc, char* argv[]) {
// Create the physical system
ChSystemNSC sys;
sys.SetCollisionSystemType(collision_type);
// Settings specific to Chrono multicore collision system
if (collision_type == collision::ChCollisionSystemType::CHRONO) {
#ifdef CHRONO_COLLISION
auto collsys = std::static_pointer_cast<collision::ChCollisionSystemChrono>(sys.GetCollisionSystem());
// Change the default number of broadphase bins
collsys->SetBroadphaseGridResolution(ChVector<int>(10, 10, 2));
// Change default narrowphase algorithm
collsys->SetEnvelope(0.005);
// Enable active bounding box
collsys->EnableActiveBoundingBox(ChVector<>(-10, -10, -20), ChVector<>(+10, +10, +10));
// Set number of threads used by the collision detection system
collsys->SetNumThreads(4);
#endif
}
// Create the Irrlicht visualization
ChIrrApp application(&sys, L"Collisions between objects", core::dimension2d<u32>(800, 600));
// Add camera, lights, logo and sky in Irrlicht scene
application.AddTypicalLogo();
application.AddTypicalSky();
application.AddTypicalLights();
application.AddTypicalCamera(core::vector3df(0, 14, -20));
// Add fixed and moving bodies
auto mixer = AddContainer(sys);
AddFallingItems(sys);
// Complete asset specification: convert all assets to Irrlicht
application.AssetBindAll();
application.AssetUpdateAll();
// Modify some setting of the physical system for the simulation, if you want
sys.SetSolverMaxIterations(50);
// Simulation loop
double step_size = 0.003;
application.SetTimestep(step_size);
while (application.GetDevice()->run()) {
application.BeginScene();
application.DrawAll();
application.DoStep();
application.EndScene();
rt.Spin(step_size);
}
return 0;
}
std::string GetChronoDataFile(const std::string &filename)
Obtain the complete path to the specified filename, given relative to the Chrono data directory (thre...
Definition: ChGlobal.cpp:95
void Add(std::shared_ptr< ChPhysicsItem > item)
Attach an arbitrary ChPhysicsItem (e.g.
Definition: ChSystem.cpp:170
void AssetUpdateAll()
For all items in a ChSystem, this function sets up the Irrlicht nodes corresponding to the geometric ...
Definition: ChIrrApp.cpp:50
ChLog & GetLog()
Global function to get the current ChLog object.
Definition: ChLog.cpp:39
std::shared_ptr< collision::ChCollisionSystem > GetCollisionSystem() const
Access the underlying collision system.
Definition: ChSystem.h:688
virtual void SetCollisionSystemType(collision::ChCollisionSystemType type)
Change the underlying collision detection system to the specified type.
Definition: ChSystem.cpp:312
void SetTimestep(double val)
Set/Get the time step for time integration.
Definition: ChIrrAppInterface.cpp:552
virtual void AddLink(std::shared_ptr< ChLinkBase > link)
Attach a link to the underlying assembly.
Definition: ChSystem.cpp:155
Class to add some GUI to Irrlicht+ChronoEngine applications.
Definition: ChIrrApp.h:29
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
virtual void EndScene()
Call this to end the scene draw at the end of each animation frame.
Definition: ChIrrAppInterface.cpp:627
Class for a timer which attempts to enforce soft real-time.
Definition: ChRealtimeStep.h:25
Projected SOR (Successive Over-Relaxation)
Chrono multicore collision detection system.
void Spin(double step)
Call this function INSIDE the simulation loop, just ONCE per loop (preferably as the last call in the...
Definition: ChRealtimeStep.h:34
Definition of general purpose 3d vector variables, such as points in 3D.
Definition: ChVector.h:35
Bullet-based collision detection system.
virtual void DoStep()
Call this function inside a loop such as.
Definition: ChIrrAppInterface.cpp:637
void SetSolverType(ChSolver::Type type)
Choose the solver type, to be used for the simultaneous solution of the constraints in dynamical simu...
Definition: ChSystem.cpp:238
void SetSolverMaxIterations(int max_iters)
Set the maximum number of iterations, if using an iterative solver.
Definition: ChSystem.cpp:212
double ChRandom()
Returns random value in (0..1) interval with Park-Miller method.
Definition: ChMathematics.cpp:53
ChCollisionSystemType
Collision engine type.
Definition: ChCollisionModel.h:44
void AssetBindAll()
Shortcut to add and bind a ChIrrNodeAsset to all items in a ChSystem.
Definition: ChIrrApp.cpp:42
virtual void BeginScene(bool backBuffer=true, bool zBuffer=true, irr::video::SColor color=irr::video::SColor(255, 0, 0, 0))
Call this to clean the canvas at the beginning of each animation frame.
Definition: ChIrrAppInterface.cpp:610
virtual void DrawAll()
Call this function inside a loop such as.
Definition: ChIrrAppInterface.cpp:750
Class for a physical system in which contact is modeled using a non-smooth (complementarity-based) me...
Definition: ChSystemNSC.h:29