Forklift example (demo_IRR_forklift.cpp)
Advanced tutorial.
Create a forklift and control it using the keyboard. The forklift collides with a pallet, that can be moved with the fork.
Learn about:
- how to use collisions for complex shapes
- how to use the Irrlicht GUI keyboard events
- how to create some constraints, including a simplified motor
- how to load .OBJ meshes for visualization etc.
// =============================================================================
// 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, Radu Serban
// =============================================================================
//
// Demo code about
// - modeling a complex mechanism: a forklift
// - loading .obj 3D meshes for 3d viewing
//
// =============================================================================
#include "chrono/assets/ChTexture.h"
#include "chrono/core/ChRealtimeStep.h"
#include "chrono/physics/ChBodyEasy.h"
#include "chrono/physics/ChLinkLinActuator.h"
#include "chrono/physics/ChLinkMotorRotationAngle.h"
#include "chrono/physics/ChLinkMotorRotationSpeed.h"
#include "chrono/physics/ChSystemNSC.h"
#include "chrono_irrlicht/ChBodySceneNodeTools.h"
#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;
using namespace irr::scene;
using namespace irr::video;
using namespace irr::io;
using namespace irr::gui;
// First of all, define a class for the 'forklift' (that is, a set of
// bodies and links which are grouped within this class; so it is
// easier to manage data structures in this example).
class MySimpleForklift {
public:
// THE DATA
double throttle; // actual value 0...1 of gas throttle.
double steer; // actual value of steering
double lift; // actual value of fork lifting
// The parts making the forklift, as 3d Irrlicht scene nodes, each containing
// the ChBody object
// .. truss:
std::shared_ptr<ChBody> truss;
// .. right front wheel:
std::shared_ptr<ChBody> wheelRF;
std::shared_ptr<ChLinkLockRevolute> link_revoluteRF;
// .. left front wheel:
std::shared_ptr<ChBody> wheelLF;
std::shared_ptr<ChLinkLockRevolute> link_revoluteLF;
// .. back wheel:
std::shared_ptr<ChBody> spindleB;
std::shared_ptr<ChBody> wheelB;
std::shared_ptr<ChLinkMotorRotationAngle> link_steer_engineB;
std::shared_ptr<ChLinkMotorRotationSpeed> link_engineB;
// ..the vertical arm
std::shared_ptr<ChBody> arm;
std::shared_ptr<ChLinkMotorRotationAngle> link_engineArm;
// ..the fork
std::shared_ptr<ChBody> fork;
std::shared_ptr<ChLinkLinActuator> link_actuatorFork;
std::shared_ptr<ChLinkLockPrismatic> link_prismaticFork;
video::ITexture* forkliftTiremap;
// THE FUNCTIONS
// Build and initialize the forklift, creating all bodies corresponding to
// the various parts and adding them to the physical system - also creating
// and adding constraints to the system.
throttle = 0; // initially, gas throttle is 0.
steer = 0;
lift = 0;
ChVector<> COG_truss(0, 0.4, 0.5);
ChVector<> COG_wheelRF(-0.566, 0.282, 1.608);
ChVector<> COG_wheelLF(0.566, 0.282, 1.608);
ChVector<> COG_arm(0, 1.300, 1.855);
ChVector<> COG_fork(0, 0.362, 2.100);
ChVector<> COG_wheelB(0, 0.282, 0.003);
ChVector<> POS_pivotarm(0, 0.150, 1.855);
ChVector<> POS_prismatic(0, 0.150, 1.855);
double RAD_back_wheel = 0.28;
double RAD_front_wheel = 0.28;
forkliftTiremap = app->GetVideoDriver()->getTexture(GetChronoDataFile("tire_truck.png").c_str());
// --- The car body ---
truss = chrono_types::make_shared<ChBody>();
app->GetSystem()->Add(truss);
truss->SetPos(COG_truss);
truss->SetMass(200);
truss->SetInertiaXX(ChVector<>(100, 100, 100));
// collision properties:
truss->GetCollisionModel()->ClearModel();
truss->GetCollisionModel()->AddBox(1.227 / 2., 1.621 / 2., 1.864 / 2., ChVector<>(-0.003, 1.019, 0.192));
truss->GetCollisionModel()->AddBox(0.187 / 2., 0.773 / 2., 1.201 / 2., ChVector<>(0.486, 0.153, -0.047));
truss->GetCollisionModel()->AddBox(0.187 / 2., 0.773 / 2., 1.201 / 2., ChVector<>(-0.486, 0.153, -0.047));
truss->GetCollisionModel()->BuildModel();
truss->SetCollide(true);
// visualization properties:
auto truss_asset_assembly = chrono_types::make_shared<ChAssetLevel>();
truss_asset_assembly->GetFrame().SetPos(-COG_truss);
truss->AddAsset(truss_asset_assembly);
auto truss_mesh = chrono_types::make_shared<ChObjShapeFile>();
truss_mesh->SetFilename(GetChronoDataFile("forklift_body.obj"));
truss_asset_assembly->AddAsset(truss_mesh);
truss_asset_assembly->AddAsset(truss_texture);
// ..the right-front wheel
wheelRF = chrono_types::make_shared<ChBody>();
app->GetSystem()->Add(wheelRF);
wheelRF->SetPos(COG_wheelRF);
wheelRF->SetMass(20);
wheelRF->SetInertiaXX(ChVector<>(2, 2, 2));
// collision properties:
ChMatrix33<> Arot(chrono::Q_from_AngAxis(CH_C_PI / 2, VECT_Z));
wheelRF->GetCollisionModel()->ClearModel();
wheelRF->GetCollisionModel()->AddCylinder(RAD_front_wheel, RAD_front_wheel, 0.1, ChVector<>(0, 0, 0), Arot);
wheelRF->GetCollisionModel()->BuildModel();
wheelRF->SetCollide(true);
// visualization properties:
auto wheelRF_asset_assembly = chrono_types::make_shared<ChAssetLevel>();
wheelRF_asset_assembly->GetFrame().SetPos(-COG_wheelRF);
wheelRF->AddAsset(wheelRF_asset_assembly);
auto wheelRF_mesh = chrono_types::make_shared<ChObjShapeFile>();
wheelRF_mesh->SetFilename(GetChronoDataFile("wheel.obj"));
wheelRF_asset_assembly->AddAsset(wheelRF_mesh);
wheelRF_asset_assembly->AddAsset(wheelRF_texture);
// .. create the revolute joint between the wheel and the truss
link_revoluteRF = chrono_types::make_shared<ChLinkLockRevolute>(); // right, front, upper, 1
link_revoluteRF->Initialize(wheelRF, truss,
ChCoordsys<>(COG_wheelRF, chrono::Q_from_AngAxis(CH_C_PI / 2, VECT_Y)));
app->GetSystem()->AddLink(link_revoluteRF);
// ..the left-front wheel
wheelLF = chrono_types::make_shared<ChBody>();
app->GetSystem()->Add(wheelLF);
wheelLF->SetPos(COG_wheelLF);
wheelLF->SetRot(chrono::Q_from_AngAxis(CH_C_PI, VECT_Y)); // reuse RF wheel shape, flipped
wheelLF->SetMass(20);
wheelLF->SetInertiaXX(ChVector<>(2, 2, 2));
// collision properties:
wheelLF->GetCollisionModel()->ClearModel();
wheelLF->GetCollisionModel()->AddCylinder(RAD_front_wheel, RAD_front_wheel, 0.1, ChVector<>(0, 0, 0), Arot);
wheelLF->GetCollisionModel()->BuildModel();
wheelLF->SetCollide(true);
// visualization properties:
auto wheelLF_asset_assembly = chrono_types::make_shared<ChAssetLevel>();
wheelLF_asset_assembly->GetFrame().SetPos(-COG_wheelRF);
wheelLF->AddAsset(wheelLF_asset_assembly);
auto wheelLF_mesh = chrono_types::make_shared<ChObjShapeFile>();
wheelLF_mesh->SetFilename(GetChronoDataFile("wheel.obj"));
wheelLF_asset_assembly->AddAsset(wheelLF_mesh);
wheelLF_asset_assembly->AddAsset(wheelLF_texture);
// .. create the revolute joint between the wheel and the truss
link_revoluteLF = chrono_types::make_shared<ChLinkLockRevolute>(); // right, front, upper, 1
link_revoluteLF->Initialize(wheelLF, truss,
ChCoordsys<>(COG_wheelLF, chrono::Q_from_AngAxis(CH_C_PI / 2, VECT_Y)));
app->GetSystem()->AddLink(link_revoluteLF);
// ..the back steering spindle (invisible, no mesh)
spindleB = chrono_types::make_shared<ChBody>();
app->GetSystem()->Add(spindleB);
spindleB->SetPos(COG_wheelB);
spindleB->SetMass(10);
spindleB->SetInertiaXX(ChVector<>(1, 1, 1));
// .. create the vertical steering link between the spindle structure and the truss
link_steer_engineB = chrono_types::make_shared<ChLinkMotorRotationAngle>();
link_steer_engineB->SetAngleFunction(chrono_types::make_shared<ChFunction_Const>(0));
link_steer_engineB->Initialize(spindleB, truss,
ChFrame<>(COG_wheelB, chrono::Q_from_AngAxis(CH_C_PI / 2, VECT_X)));
app->GetSystem()->AddLink(link_steer_engineB);
// ..the back wheel
wheelB = chrono_types::make_shared<ChBody>();
app->GetSystem()->Add(wheelB);
wheelB->SetPos(COG_wheelB);
wheelB->SetRot(chrono::Q_from_AngAxis(CH_C_PI, VECT_Y)); // reuse RF wheel shape, flipped
wheelB->SetMass(20);
wheelB->SetInertiaXX(ChVector<>(2, 2, 2));
// collision properties:
wheelB->GetCollisionModel()->ClearModel();
wheelB->GetCollisionModel()->AddCylinder(RAD_back_wheel, RAD_back_wheel, 0.1, ChVector<>(0, 0, 0), Arot);
wheelB->GetCollisionModel()->BuildModel();
wheelB->SetCollide(true);
// visualization properties:
auto wheelB_asset_assembly = chrono_types::make_shared<ChAssetLevel>();
wheelB_asset_assembly->GetFrame().SetPos(-COG_wheelRF);
wheelB->AddAsset(wheelB_asset_assembly);
auto wheelB_mesh = chrono_types::make_shared<ChObjShapeFile>();
wheelB_mesh->SetFilename(GetChronoDataFile("wheel.obj"));
wheelB_asset_assembly->AddAsset(wheelB_mesh);
wheelB_asset_assembly->AddAsset(wheelB_texture);
// .. create the motor between the back wheel and the steering spindle structure
link_engineB = chrono_types::make_shared<ChLinkMotorRotationSpeed>();
link_engineB->SetSpeedFunction(chrono_types::make_shared<ChFunction_Const>(0));
link_engineB->Initialize(wheelB, spindleB, ChFrame<>(COG_wheelB, chrono::Q_from_AngAxis(CH_C_PI / 2, VECT_Y)));
app->GetSystem()->AddLink(link_engineB);
// ..the arm
arm = chrono_types::make_shared<ChBody>();
app->GetSystem()->Add(arm);
arm->SetPos(COG_arm);
arm->SetMass(100);
arm->SetInertiaXX(ChVector<>(30, 30, 30));
// visualization properties:
auto arm_asset_assembly = chrono_types::make_shared<ChAssetLevel>();
arm_asset_assembly->GetFrame().SetPos(-COG_arm);
arm->AddAsset(arm_asset_assembly);
auto arm_mesh = chrono_types::make_shared<ChObjShapeFile>();
arm_mesh->SetFilename(GetChronoDataFile("forklift_arm.obj"));
arm_asset_assembly->AddAsset(arm_mesh);
// .. create the revolute joint between the arm and the truss
link_engineArm = chrono_types::make_shared<ChLinkMotorRotationAngle>();
link_engineArm->SetAngleFunction(chrono_types::make_shared<ChFunction_Const>(0));
link_engineArm->Initialize(arm, truss, ChFrame<>(POS_pivotarm, chrono::Q_from_AngAxis(CH_C_PI / 2, VECT_Y)));
app->GetSystem()->AddLink(link_engineArm);
// ..the fork
fork = chrono_types::make_shared<ChBody>();
app->GetSystem()->Add(fork);
fork->SetPos(COG_fork);
fork->SetMass(60);
fork->SetInertiaXX(ChVector<>(15, 15, 15));
// collision properties:
fork->GetCollisionModel()->ClearModel();
fork->GetCollisionModel()->AddBox(0.1 / 2., 0.032 / 2., 1.033 / 2.,ChVector<>(-0.352, -0.312, 0.613));
fork->GetCollisionModel()->AddBox(0.1 / 2., 0.032 / 2., 1.033 / 2., ChVector<>(0.352, -0.312, 0.613));
fork->GetCollisionModel()->AddBox(0.344 / 2., 1.134 / 2., 0.101 / 2., ChVector<>(-0.000, 0.321, -0.009));
fork->GetCollisionModel()->BuildModel();
fork->SetCollide(true);
// visualization properties:
auto fork_asset_assembly = chrono_types::make_shared<ChAssetLevel>();
fork_asset_assembly->GetFrame().SetPos(-COG_fork);
fork->AddAsset(fork_asset_assembly);
auto fork_mesh = chrono_types::make_shared<ChObjShapeFile>();
fork_mesh->SetFilename(GetChronoDataFile("forklift_forks.obj"));
fork_asset_assembly->AddAsset(fork_mesh);
// .. create the prismatic joint between the fork and arm
link_prismaticFork = chrono_types::make_shared<ChLinkLockPrismatic>();
link_prismaticFork->Initialize(
fork, arm,
POS_prismatic,
chrono::Q_from_AngAxis(CH_C_PI / 2,
VECT_X))); // set prism as vertical (default would be aligned to z, horizontal
app->GetSystem()->AddLink(link_prismaticFork);
// .. create the linear actuator that pushes upward the fork
link_actuatorFork = chrono_types::make_shared<ChLinkLinActuator>();
link_actuatorFork->Initialize(fork, arm, false,
ChCoordsys<>(POS_prismatic, QUNIT));
app->GetSystem()->AddLink(link_actuatorFork);
// ..a pallet
auto pallet = chrono_types::make_shared<ChBodyEasyMesh>(
300, // density
true, // compute mass, inertia & COG from the mesh (must be a closed watertight mesh!)
true, // enable collision with mesh
0.001, // sphere swept inflate of mesh - improves robustness of collision detection
true); // enable visualization of mesh
app->GetSystem()->Add(pallet);
pallet->SetPos(ChVector<>(0, 0.4, 3));
// apply also a texture to the pallet:
auto pallet_texture = chrono_types::make_shared<ChTexture>();
pallet_texture->SetTextureFilename(GetChronoDataFile("cubetexture.png"));
pallet->AddAsset(pallet_texture);
//
// Move the forklift to initial offset position
//
// pallet->GetBody()->Move(offset);
truss->Move(offset);
wheelRF->Move(offset);
wheelLF->Move(offset);
wheelB->Move(offset);
spindleB->Move(offset);
arm->Move(offset);
fork->Move(offset);
}
// Delete the car object, deleting also all bodies corresponding to
// the various parts and removing them from the physical system. Also
// removes constraints from the system.
~MySimpleForklift() {
mysystem->Remove(link_revoluteRF);
mysystem->Remove(link_revoluteLF);
mysystem->Remove(link_steer_engineB);
mysystem->Remove(link_engineB);
mysystem->Remove(link_engineArm);
mysystem->Remove(link_prismaticFork);
mysystem->Remove(link_actuatorFork);
mysystem->Remove(truss);
mysystem->Remove(wheelRF);
mysystem->Remove(wheelLF);
mysystem->Remove(wheelB);
mysystem->Remove(spindleB);
mysystem->Remove(arm);
mysystem->Remove(fork);
}
};
// Define a MyEventReceiver class which will be used to manage input
// from the GUI graphical user interface (the interface will
// be created with the basic -yet flexible- platform
// independent toolset of Irrlicht).
class MyEventReceiver : public IEventReceiver {
public:
MyEventReceiver(ChIrrAppInterface* myapp, MySimpleForklift* mlift) {
// store pointer to physical system & other stuff so we can tweak them by user keyboard
app = myapp;
forklift = mlift;
}
bool OnEvent(const SEvent& event) {
// check if user presses keys
if (event.EventType == irr::EET_KEY_INPUT_EVENT && !event.KeyInput.PressedDown) {
switch (event.KeyInput.Key) {
case irr::KEY_KEY_Q:
if (auto mfun = std::dynamic_pointer_cast<ChFunction_Const>(forklift->link_steer_engineB->GetAngleFunction()))
mfun->Set_yconst(-0.6 + mfun->Get_yconst());
return true;
case irr::KEY_KEY_W:
if (auto mfun = std::dynamic_pointer_cast<ChFunction_Const>(forklift->link_steer_engineB->GetAngleFunction()))
mfun->Set_yconst(+0.3 + mfun->Get_yconst());
return true;
case irr::KEY_KEY_A:
if (auto mfun = std::dynamic_pointer_cast<ChFunction_Const>(forklift->link_engineB->GetSpeedFunction()))
mfun->Set_yconst(0.5 + mfun->Get_yconst());
return true;
case irr::KEY_KEY_Z:
if (auto mfun = std::dynamic_pointer_cast<ChFunction_Const>(forklift->link_engineB->GetSpeedFunction()))
mfun->Set_yconst(-0.5 + mfun->Get_yconst());
return true;
case irr::KEY_KEY_S:
if (auto mfun = std::dynamic_pointer_cast<ChFunction_Const>(forklift->link_actuatorFork->Get_dist_funct()))
mfun->Set_yconst(0.05 + mfun->Get_yconst());
return true;
case irr::KEY_KEY_X:
if (auto mfun = std::dynamic_pointer_cast<ChFunction_Const>(forklift->link_actuatorFork->Get_dist_funct()))
mfun->Set_yconst(-0.05 + mfun->Get_yconst());
return true;
case irr::KEY_KEY_D:
if (auto mfun = std::dynamic_pointer_cast<ChFunction_Const>(forklift->link_engineArm->GetAngleFunction()))
mfun->Set_yconst(0.005 + mfun->Get_yconst());
return true;
case irr::KEY_KEY_C:
if (auto mfun = std::dynamic_pointer_cast<ChFunction_Const>(forklift->link_engineArm->GetAngleFunction()))
mfun->Set_yconst(-0.005 + mfun->Get_yconst());
return true;
default:
break;
}
}
return false;
}
private:
ChIrrAppInterface* app;
MySimpleForklift* forklift;
};
//
// This is the program which is executed
//
int main(int argc, char* argv[]) {
// Create a ChronoENGINE physical system
ChSystemNSC my_system;
// Create the Irrlicht visualization (open the Irrlicht device,
// bind a simple user interface, etc. etc.)
// add text with info
IGUIStaticText* textFPS = application.GetIGUIEnvironment()->addStaticText(
L"Keys: steer=Q,W; throttle=A,Z; lift=S,X; bank=D,C", rect<s32>(150, 10, 430, 40), true);
// Easy shortcuts to add logo, camera, lights 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(-6, 3, -6));
// ..the world
auto my_ground = chrono_types::make_shared<ChBodyEasyBox>(40, 2, 40, 1000, true, true);
my_system.Add(my_ground);
my_ground->SetBodyFixed(true);
my_ground->SetPos(ChVector<>(0, -1, 0));
my_ground->GetMaterialSurfaceNSC()->SetSfriction(1.0);
my_ground->GetMaterialSurfaceNSC()->SetKfriction(1.0);
my_ground->AddAsset(mtexture);
// ..some obstacles on the ground:
for (int i = 0; i < 6; i++) {
auto my_obstacle = chrono_types::make_shared<ChBodyEasyBox>(1, 0.5, 1, 200, true, true);
my_system.Add(my_obstacle);
my_obstacle->GetMaterialSurfaceNSC()->SetFriction(1.0);
my_obstacle->AddAsset(mtexture);
}
// ..the forklift (this class - see above - is a 'set' of bodies and links, automatically added at creation)
MySimpleForklift* myforklift = new MySimpleForklift(&application);
// 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();
//
// USER INTERFACE
//
// Create some graphical-user-interface (GUI) items to show on the screen.
// This requires an event receiver object -see above.
// This is for GUI tweaking of system parameters..
MyEventReceiver receiver(&application, myforklift);
// note how to add a custom event receiver to the default interface:
application.SetUserEventReceiver(&receiver);
//
// SETTINGS
//
my_system.SetSolverType(ChSolver::Type::PSOR);
my_system.SetSolverMaxIterations(20); // the higher, the easier to keep the constraints satisfied.
//
// THE SOFT-REAL-TIME CYCLE, SHOWING THE SIMULATION
//
// This will help choosing an integration step which matches the
// real-time step of the simulation..
application.SetStepManage(true);
application.SetTimestep(0.005);
while (application.GetDevice()->run()) {
// Irrlicht must prepare frame to draw
// Irrlicht application draws all 3D objects and all GUI items
application.DrawAll();
// Advance the simulation time step
application.DoStep();
// Irrlicht must finish drawing the frame
application.EndScene();
}
if (myforklift)
delete myforklift;
return 0;
}
void Remove(std::shared_ptr< ChPhysicsItem > item)
Remove arbitrary ChPhysicsItem that was added to the assembly.
Definition: ChAssembly.cpp:223
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
static void add_typical_Camera(irr::IrrlichtDevice *device, irr::core::vector3df mpos=irr::core::vector3df(0, 0, -8), irr::core::vector3df mtarg=irr::core::vector3df(0, 0, 0))
A very basic and simple function which is just a shortcut to avoid lot of typing when someone wants t...
Definition: ChIrrWizard.cpp:53
ChLog & GetLog()
Global function to get the current ChLog object.
Definition: ChLog.cpp:39
void SetTimestep(double val)
Set/Get the time step for time integration.
Definition: ChIrrAppInterface.cpp:532
virtual void AddLink(std::shared_ptr< ChLinkBase > link)
Attach a link to this assembly.
Definition: ChAssembly.cpp:125
Definition of a 3x3 fixed size matrix to represent 3D rotations and inertia tensors.
Definition: ChMatrix33.h:31
static void add_typical_Logo(irr::IrrlichtDevice *device, const std::string &mlogofilename=GetChronoDataFile("logo_chronoengine_alpha.png"))
A very basic and simple function which is just a shortcut to avoid lot of typing when someone wants t...
Definition: ChIrrWizard.cpp:20
static void add_typical_Sky(irr::IrrlichtDevice *device, const std::string &mtexturedir=GetChronoDataFile("skybox/"))
A very basic and simple function which is just a shortcut to avoid lot of typing when someone wants t...
Definition: ChIrrWizard.cpp:40
void SetStepManage(bool val)
If set to true, you can use DoStep() in the simulation loop to advance the simulation by one timestep...
Definition: ChIrrAppInterface.h:84
static void add_typical_Lights(irr::IrrlichtDevice *device, irr::core::vector3df pos1=irr::core::vector3df(30.f, 100.f, 30.f), irr::core::vector3df pos2=irr::core::vector3df(30.f, 80.f, -30.f), double rad1=290, double rad2=190, irr::video::SColorf col1=irr::video::SColorf(0.7f, 0.7f, 0.7f, 1.0f), irr::video::SColorf col2=irr::video::SColorf(0.7f, 0.8f, 0.8f, 1.0f))
A very basic and simple function which is just a shortcut to avoid lot of typing when someone wants t...
Definition: ChIrrWizard.cpp:25
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
const ChApi ChQuaternion< double > QUNIT
Constant unit quaternion: {1, 0, 0, 0} , corresponds to no rotation (diagonal rotation matrix)
virtual void EndScene()
Call this to end the scene draw at the end of each animation frame.
Definition: ChIrrAppInterface.cpp:578
Projected SOR (Successive Over-Relaxation)
Definition of general purpose 3d vector variables, such as points in 3D.
Definition: ChVector.h:35
virtual void DoStep()
Call this important function inside a cycle like while(application.GetDevice()->run()) {....
Definition: ChIrrAppInterface.cpp:590
virtual 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:149
void Add(std::shared_ptr< ChPhysicsItem > item)
Attach an arbitrary ChPhysicsItem (e.g.
Definition: ChAssembly.cpp:190
void SetSolverMaxIterations(int max_iters)
Set the maximum number of iterations, if using an iterative solver.
Definition: ChSystem.cpp:123
ChSystem * GetSystem() const
Get the pointer to the parent ChSystem()
Definition: ChPhysicsItem.h:58
double ChRandom()
Returns random value in (0..1) interval with Park-Miller method.
Definition: ChMathematics.cpp:53
Class to add some GUI to Irrlicht + ChronoEngine applications.
Definition: ChIrrAppInterface.h:40
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:559
virtual void DrawAll()
Call this important function inside a loop like while(application.GetDevice()->run()) {....
Definition: ChIrrAppInterface.cpp:699
Class for a physical system in which contact is modeled using a non-smooth (complementarity-based) me...
Definition: ChSystemNSC.h:29
void SetUserEventReceiver(irr::IEventReceiver *mreceiver)
Use this function to hook a custom event receiver to the application.
Definition: ChIrrAppInterface.h:133