Conveyor belt example (demo_MBS_conveyor.cpp)
Demonstration of the conveyor belt primitive.
// =============================================================================
// 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
// =============================================================================
//
// Demonstration of the conveyor belt primitive.
// For more advanced features regarding feeding devices, look at demo_IRR_feeder.cpp
//
// =============================================================================
#include "chrono/physics/ChSystemNSC.h"
#include "chrono/physics/ChBodyEasy.h"
#include "chrono/physics/ChConveyor.h"
#include "chrono/core/ChRealtimeStep.h"
#include "chrono/core/ChRandom.h"
#include "chrono_irrlicht/ChVisualSystemIrrlicht.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;
using namespace irr::scene;
using namespace irr::video;
using namespace irr::io;
using namespace irr::gui;
// Static values valid through the entire program (bad
// programming practice, but enough for quick tests)
double STATIC_flow = 100;
double STATIC_speed = 2;
std::vector<std::shared_ptr<ChBody> > particlelist;
// Define a MyEventReceiver class which will be used to manage input
// from the GUI graphical user interface
class MyEventReceiver : public IEventReceiver {
public:
MyEventReceiver(ChVisualSystemIrrlicht& vsys) : vis(vsys), paused(false) {
// ..add a GUI slider to control particles flow
scrollbar_flow = vis.GetGUIEnvironment()->addScrollBar(true, rect<s32>(510, 85, 650, 100), 0, 101);
scrollbar_flow->setMax(300);
scrollbar_flow->setPos(150);
text_flow = vis.GetGUIEnvironment()->addStaticText(L"Flow [particles/s]", rect<s32>(650, 85, 750, 100), false);
// ..add GUI slider to control the speed
scrollbar_speed = vis.GetGUIEnvironment()->addScrollBar(true, rect<s32>(510, 125, 650, 140), 0, 102);
scrollbar_speed->setMax(100);
scrollbar_speed->setPos(100);
text_speed =
vis.GetGUIEnvironment()->addStaticText(L"Conveyor speed [m/s]:", rect<s32>(650, 125, 750, 140), false);
}
bool OnEvent(const SEvent& event) {
// check if user moved the sliders with mouse..
if (event.EventType == EET_GUI_EVENT) {
s32 id = event.GUIEvent.Caller->getID();
switch (event.GUIEvent.EventType) {
case EGET_SCROLL_BAR_CHANGED:
if (id == 101) // id of 'flow' slider..
{
s32 pos = ((IGUIScrollBar*)event.GUIEvent.Caller)->getPos();
STATIC_flow = (double)pos;
}
if (id == 102) // id of 'speed' slider..
{
s32 pos = ((IGUIScrollBar*)event.GUIEvent.Caller)->getPos();
STATIC_speed = (((double)pos) / 100) * 2;
}
break;
default:
break;
}
}
if (event.EventType == irr::EET_KEY_INPUT_EVENT && !event.KeyInput.PressedDown) {
switch (event.KeyInput.Key) {
case irr::KEY_SPACE:
paused = !paused;
return true;
default:
break;
}
}
return false;
}
bool paused;
private:
ChVisualSystemIrrlicht& vis;
IGUIScrollBar* scrollbar_flow;
IGUIStaticText* text_flow;
IGUIScrollBar* scrollbar_speed;
IGUIStaticText* text_speed;
};
// Function that creates debris that fall on the conveyor belt, to be called at each dt.
// In this example, all debris particles share the same contact material.
void create_debris(ChVisualSystemIrrlicht& vis, ChSystem& sys, double dt, double particles_second) {
double xnozzlesize = 0.2;
double znozzlesize = 0.56;
double ynozzle = 0.2;
double box_fraction = 0.3; // 30% cubes
double cyl_fraction = 0.4; // 40% cylinders
double sphrad = 0.013;
double exact_particles_dt = dt * particles_second;
double particles_dt = floor(exact_particles_dt);
double remaind = exact_particles_dt - particles_dt;
if (remaind > ChRandom::Get())
particles_dt += 1;
auto sphere_mat = chrono_types::make_shared<ChContactMaterialNSC>();
sphere_mat->SetFriction(0.2f);
sphere_mat->SetRestitution(0.8f);
auto box_mat = chrono_types::make_shared<ChContactMaterialNSC>();
box_mat->SetFriction(0.4f);
auto cyl_mat = chrono_types::make_shared<ChContactMaterialNSC>();
cyl_mat->SetFriction(0.2f);
for (int i = 0; i < particles_dt; i++) {
double rand_fract = ChRandom::Get();
if (rand_fract < box_fraction) {
auto rigidBody = chrono_types::make_shared<ChBodyEasySphere>(sphrad, // size
1000, // density
true, // visualization?
true, // collision?
sphere_mat); // contact material
rigidBody->SetPos(ChVector3d(-0.5 * xnozzlesize + ChRandom::Get() * xnozzlesize, ynozzle + i * 0.005,
-0.5 * znozzlesize + ChRandom::Get() * znozzlesize));
rigidBody->GetVisualShape(0)->SetTexture(GetChronoDataFile("textures/bluewhite.png"));
sys.Add(rigidBody);
vis.BindItem(rigidBody);
sys.GetCollisionSystem()->BindItem(rigidBody);
particlelist.push_back(rigidBody);
}
if ((rand_fract > box_fraction) && (rand_fract < box_fraction + cyl_fraction)) {
double xscale = 1.3 * (1 - 0.4 * ChRandom::Get()); // for oddly-shaped boxes..
double yscale = 1.3 * (1 - 0.4 * ChRandom::Get());
double zscale = 1.3 * (1 - 0.4 * ChRandom::Get());
auto rigidBody =
chrono_types::make_shared<ChBodyEasyBox>(sphrad * 2 * xscale, sphrad * 2 * yscale, sphrad * 2 * zscale,
1000, // density
true, // visualization?
true, // collision?
box_mat); // contact material
rigidBody->SetPos(ChVector3d(-0.5 * xnozzlesize + ChRandom::Get() * xnozzlesize, ynozzle + i * 0.005,
-0.5 * znozzlesize + ChRandom::Get() * znozzlesize));
rigidBody->GetVisualShape(0)->SetTexture(GetChronoDataFile("textures/cubetexture_bluewhite.png"));
sys.Add(rigidBody);
vis.BindItem(rigidBody);
sys.GetCollisionSystem()->BindItem(rigidBody);
particlelist.push_back(rigidBody);
}
if (rand_fract > box_fraction + cyl_fraction) {
sphrad, sphrad * 2, // rad, height
1000, // density
true, // visualization?
true, // collision?
cyl_mat); // contact material
rigidBody->SetPos(ChVector3d(-0.5 * xnozzlesize + ChRandom::Get() * xnozzlesize, ynozzle + i * 0.005,
-0.5 * znozzlesize + ChRandom::Get() * znozzlesize));
rigidBody->GetVisualShape(0)->SetTexture(GetChronoDataFile("textures/pinkwhite.png"));
sys.Add(rigidBody);
vis.BindItem(rigidBody);
sys.GetCollisionSystem()->BindItem(rigidBody);
particlelist.push_back(rigidBody);
}
}
}
// Function that deletes old debris (to avoid infinite creation that fills memory)
while (particlelist.size() > nmaxparticles) {
sys.Remove(particlelist[0]); // remove from physical simulation
particlelist.erase(particlelist.begin()); // remove also from our particle list (will also automatically delete
// object thank to shared pointer)
}
}
int main(int argc, char* argv[]) {
std::cout << "Copyright (c) 2017 projectchrono.org\nChrono version: " << CHRONO_VERSION << std::endl;
// Create a ChronoENGINE physical system
ChSystemNSC sys;
// Set small collision envelopes for objects that will be created from now on
// Create two conveyor fences
auto fence_mat = chrono_types::make_shared<ChContactMaterialNSC>();
fence_mat->SetFriction(0.1f);
auto fence1 = chrono_types::make_shared<ChBodyEasyBox>(2, 0.11, 0.04, 1000, true, true, fence_mat);
sys.Add(fence1);
fence1->SetPos(ChVector3d(0, 0, -0.325));
fence1->SetFixed(true);
auto fence2 = chrono_types::make_shared<ChBodyEasyBox>(2, 0.11, 0.04, 1000, true, true, fence_mat);
sys.Add(fence2);
fence2->SetPos(ChVector3d(0, 0, 0.325));
fence2->SetFixed(true);
// Create the conveyor belt (this is a pure Chrono::Engine object,
// because an Irrlicht 'SceneNode' wrapper is not yet available, so it is invisible - no 3D preview)
auto conveyor_mat = chrono_types::make_shared<ChContactMaterialNSC>();
conveyor_mat->SetFriction(0.35f);
auto conveyor = chrono_types::make_shared<ChConveyor>(2, 0.05, 0.6);
conveyor->SetFixed(true);
conveyor->SetMaterialSurface(conveyor_mat);
conveyor->SetConveyorSpeed(STATIC_speed);
conveyor->SetPos(ChVector3d(0, 0, 0));
sys.Add(conveyor);
// Create the Irrlicht visualization system
auto vis = chrono_types::make_shared<ChVisualSystemIrrlicht>();
vis->AttachSystem(&sys);
vis->SetWindowSize(800, 600);
vis->SetWindowTitle("Conveyor belt");
vis->Initialize();
vis->AddLogo();
vis->AddSkyBox();
vis->AddTypicalLights();
// Add the custom event receiver to the default interface
MyEventReceiver receiver(*vis);
vis->AddUserEventReceiver(&receiver);
// Simulation loop
ChRealtimeStepTimer realtime_timer;
double timestep = 0.005;
while (vis->Run()) {
vis->BeginScene();
vis->Render();
vis->EndScene();
sys.DoStepDynamics(timestep);
if (!receiver.paused) {
// Continuosly create debris that fall on the conveyor belt
create_debris(*vis, sys, timestep, STATIC_flow);
// Limit the max number of debris particles on the scene, deleting the oldest ones, for performance
purge_debris(sys, 300);
// Maybe the user played with the slider and changed STATIC_speed...
conveyor->SetConveyorSpeed(STATIC_speed);
}
realtime_timer.Spin(timestep);
}
return 0;
}
void AddTypicalLights()
Simple shortcut to set two point lights in the scene.
Definition: ChVisualSystemIrrlicht.cpp:344
std::string GetChronoDataFile(const std::string &filename)
Get the full path to the specified filename, given relative to the Chrono data directory (thread safe...
Definition: ChGlobal.cpp:37
void Add(std::shared_ptr< ChPhysicsItem > item)
Attach an arbitrary ChPhysicsItem (e.g.
Definition: ChSystem.cpp:196
virtual void Render() override
Draw all 3D shapes and GUI elements at the current frame.
Definition: ChVisualSystemIrrlicht.cpp:570
virtual void Initialize() override
Initialize the visualization system.
Definition: ChVisualSystemIrrlicht.cpp:181
void AddSkyBox(const std::string &texture_dir=GetChronoDataFile("skybox/"))
Add a sky box in a 3D scene.
Definition: ChVisualSystemIrrlicht.cpp:357
void Remove(std::shared_ptr< ChPhysicsItem > item)
Remove arbitrary ChPhysicsItem that was added to the underlying assembly.
Definition: ChSystem.cpp:220
std::shared_ptr< ChCollisionSystem > GetCollisionSystem() const
Access the underlying collision system.
Definition: ChSystem.h:103
Class for a timer which attempts to enforce soft real-time.
Definition: ChRealtimeStep.h:25
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
virtual void EndScene() override
End the scene draw at the end of each animation frame.
Definition: ChVisualSystemIrrlicht.cpp:560
virtual void BeginScene() override
Perform any necessary operations at the beginning of each rendering frame.
Definition: ChVisualSystemIrrlicht.cpp:543
virtual int AddCamera(const ChVector3d &pos, ChVector3d targ=VNULL) override
Add a camera in an Irrlicht 3D scene.
Definition: ChVisualSystemIrrlicht.cpp:290
void AddUserEventReceiver(irr::IEventReceiver *receiver)
Attach a custom event receiver to the application.
Definition: ChVisualSystemIrrlicht.cpp:438
static void SetDefaultSuggestedMargin(double margin)
Set the default margin (inward penetration).
Definition: ChCollisionModel.cpp:93
int DoStepDynamics(double step_size)
Advance the dynamics simulation by a single time step of given length.
Definition: ChSystem.cpp:1635
Bullet-based collision detection system.
ChVector3< double > ChVector3d
Alias for double-precision vectors.
Definition: ChVector3.h:283
void SetWindowTitle(const std::string &win_title)
Set the windoiw title (default "").
Definition: ChVisualSystemIrrlicht.cpp:138
y direction of a reference frame
virtual void AttachSystem(ChSystem *sys) override
Attach another Chrono system to the run-time visualization system.
Definition: ChVisualSystemIrrlicht.cpp:165
virtual bool Run() override
Run the Irrlicht device.
Definition: ChVisualSystemIrrlicht.cpp:243
virtual void BindItem(std::shared_ptr< ChPhysicsItem > item) override
Process the visual assets for the spcified physics item.
Definition: ChVisualSystemIrrlicht.cpp:609
void AddLogo(const std::string &logo_filename=GetChronoDataFile("logo_chronoengine_alpha.png"))
Add a logo in a 3D scene.
Definition: ChVisualSystemIrrlicht.cpp:336
virtual void SetCollisionSystemType(ChCollisionSystem::Type type)
Set the collision detection system used by this Chrono system to the specified type.
Definition: ChSystem.cpp:324
Class for a physical system in which contact is modeled using a non-smooth (complementarity-based) me...
Definition: ChSystemNSC.h:29
static void SetDefaultSuggestedEnvelope(double envelope)
Set the default envelope value.
Definition: ChCollisionModel.cpp:89
void SetWindowSize(unsigned int width, unsigned int height)
Set the window size (default 640x480).
Definition: ChVisualSystemIrrlicht.cpp:134
Irrlicht-based Chrono run-time visualization system.
Definition: ChVisualSystemIrrlicht.h:52