Pendulum example (demo_MBS_pendulum.cpp)

Create some swinging pendulums, anchored to sliding joints. They move when the fan pushes some air toward them.

This tutorial shows how to:

  • create a pendulum
  • apply custom forces using 'force accumulators' (the simplified aereodinamic drag, in this case)
  • create constraints with upper-lower limits (the horizontal sliding joints between pendula and truss)
// =============================================================================
// 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
// - creating a pendulum
// - apply custom forces using accumulators
// - creating constraints with limits
// - 3D viewing with the Irrlicht library
//
// =============================================================================
#include "chrono/physics/ChSystemNSC.h"
#include "chrono/physics/ChBodyEasy.h"
#include "chrono/core/ChTimer.h"
#include "chrono/core/ChRealtimeStep.h"
#include "chrono_irrlicht/ChVisualSystemIrrlicht.h"
// Use the namespaces of Chrono
using namespace chrono;
using namespace chrono::irrlicht;
// This function will be used to apply forces caused by
// a rotating fan, to all objects in front of it (a simple
// example just to demonstrate how to apply custom forces).
void apply_fan_force(ChSystemNSC* msystem, // contains all bodies
ChCoordsys<>& fan_csys, // pos and rotation of fan
double aradius, // radius of fan
double aspeed, // speed of fan
double adensity) // density (heuristic)
{
for (auto body : msystem->Get_bodylist()) {
// Remember to reset 'user forces accumulators':
body->Empty_forces_accumulators();
// initialize speed of air (steady, if outside fan stream):
ChVector<> abs_wind(0, 0, 0);
// calculate the position of body COG in fan coordinates:
ChVector<> mrelpos = fan_csys.TransformParentToLocal(body->GetPos());
ChVector<> mrelpos_ondisc = mrelpos;
mrelpos_ondisc.z() = 0;
if (mrelpos.z() > 0) // if not behind fan..
if (mrelpos_ondisc.Length() < aradius) {
// OK! we are inside wind stream cylinder..
// wind is directed as normal to the fan disc
abs_wind = fan_csys.TransformLocalToParent(ChVector<>(0, 0, 1));
// wind inside fan stream is constant speed
abs_wind *= -aspeed;
}
// force proportional to relative speed body-wind
// and fluid density (NOTE! pretty simplified physics..)
ChVector<> abs_force = (abs_wind - body->GetPos_dt()) * adensity;
// apply this force at the body COG
body->Accumulate_force(abs_force, body->GetPos(), false);
}
}
int main(int argc, char* argv[]) {
GetLog() << "Copyright (c) 2017 projectchrono.org\nChrono version: " << CHRONO_VERSION << "\n\n";
// Create a ChronoENGINE physical system
// Create all the rigid bodies
// ..create the five pendulums
for (int k = 0; k < 5; k++) {
double z_step = (double)k * 2.;
// .. the truss
auto mrigidBody0 = chrono_types::make_shared<ChBodyEasyBox>(5, 1, 0.5, // x,y,z size
100, // density
true, // visualization?
false); // collision?
mrigidBody0->SetPos(ChVector<>(0, 0, z_step));
mrigidBody0->SetBodyFixed(true); // the truss does not move!
sys.Add(mrigidBody0);
auto mrigidBody1 = chrono_types::make_shared<ChBodyEasyBox>(1, 6, 1, // x,y,z size
1, // density
true, // visualization?
false); // collision?
mrigidBody1->SetPos(ChVector<>(0, -3, z_step));
sys.Add(mrigidBody1);
auto mrigidBody2 = chrono_types::make_shared<ChBodyEasyBox>(1, 6, 1, // x,y,z size
1, // density
true, // visualization?
false); // collision?
mrigidBody2->SetPos(ChVector<>(0, -9, z_step));
sys.Add(mrigidBody2);
auto mrigidBody3 = chrono_types::make_shared<ChBodyEasyBox>(6, 1, 1, // x,y,z size
1, // density
true, // visualization?
false); // collision?
mrigidBody3->SetPos(ChVector<>(3, -12, z_step));
sys.Add(mrigidBody3);
//
// Create the links between bodies!!!!
//
// .. a joint of type 'point on a line', with upper and lower limits on
// the X sliding direction, for the pendulum-ground constraint.
auto my_link_01 = chrono_types::make_shared<ChLinkLockPointLine>();
my_link_01->Initialize(mrigidBody1, mrigidBody0, ChCoordsys<>(ChVector<>(0, 0, z_step)));
my_link_01->GetLimit_X().SetActive(true);
my_link_01->GetLimit_X().SetMax(1.0);
my_link_01->GetLimit_X().SetMin(-1.0);
sys.AddLink(my_link_01);
// .. a spherical joint
auto my_link_12 = chrono_types::make_shared<ChLinkLockSpherical>();
my_link_12->Initialize(mrigidBody2, mrigidBody1, ChCoordsys<>(ChVector<>(0, -6, z_step)));
sys.AddLink(my_link_12);
// .. a spherical joint
auto my_link_23 = chrono_types::make_shared<ChLinkLockSpherical>();
my_link_23->Initialize(mrigidBody3, mrigidBody2, ChCoordsys<>(ChVector<>(0, -12, z_step)));
sys.AddLink(my_link_23);
}
// Create the Irrlicht visualization system
auto vis = chrono_types::make_shared<ChVisualSystemIrrlicht>();
vis->AttachSystem(&sys);
vis->SetWindowSize(800, 600);
vis->SetWindowTitle("A simple pendulum example");
vis->Initialize();
vis->AddLogo();
vis->AddSkyBox();
vis->AddCamera(ChVector<>(0, 14, -20));
// Create a 'fan ventilator' object, using Irrlicht mesh loading and handling
// (this object is here for aesthetical reasons, it is NOT handled by Chrono)
double fan_radius = 5.3;
irr::scene::IAnimatedMesh* fanMesh = vis->GetSceneManager()->getMesh(GetChronoDataFile("models/fan2.obj").c_str());
irr::scene::IAnimatedMeshSceneNode* fanNode = vis->GetSceneManager()->addAnimatedMeshSceneNode(fanMesh);
fanNode->setScale(irr::core::vector3df((irr::f32)fan_radius, (irr::f32)fan_radius, (irr::f32)fan_radius));
// Simulation loop
double timestep = 0.01;
ChRealtimeStepTimer realtime_timer;
while (vis->Run()) {
vis->BeginScene();
vis->Render();
tools::drawGrid(vis.get(), 2, 2, 20, 20, ChCoordsys<>(ChVector<>(0, -20, 0), Q_from_AngX(CH_C_PI_2)),
ChColor(0.3f, 0.5f, 0.5f), true);
// Update the position of the spinning fan (an Irrlicht
// node, which is here just for aesthetical reasons!)
ChQuaternion<> my_fan_rotation;
my_fan_rotation.Q_from_AngY(sys.GetChTime() * -0.5);
ChQuaternion<> my_fan_spin;
my_fan_spin.Q_from_AngZ(sys.GetChTime() * 4);
ChCoordsys<> my_fan_coord(ChVector<>(12, -6, 0), my_fan_rotation);
ChFrame<> my_fan_framerotation(my_fan_coord);
ChFrame<> my_fan_framespin(ChCoordsys<>(VNULL, my_fan_spin));
ChCoordsys<> my_fan_coordsys = (my_fan_framespin >> my_fan_framerotation).GetCoord();
tools::alignIrrlichtNode(fanNode, my_fan_coordsys);
vis->EndScene();
// Apply forces caused by fan & wind if Chrono rigid bodies are
// in front of the fan, using a simple tutorial function (see above):
apply_fan_force(&sys, my_fan_coord, fan_radius, 5.2, 0.5);
sys.DoStepDynamics(timestep);
realtime_timer.Spin(timestep);
}
return 0;
}
void AddTypicalLights()
Simple shortcut to set two point lights in the scene.
Definition: ChVisualSystemIrrlicht.cpp:286
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:179
COORDSYS:
Definition: ChCoordsys.h:38
void AddSkyBox(const std::string &texture_dir=GetChronoDataFile("skybox/"))
Add a sky box in a 3D scene.
Definition: ChVisualSystemIrrlicht.cpp:299
virtual void Initialize()
Initialize the visualization system.
Definition: ChVisualSystemIrrlicht.cpp:160
ChLog & GetLog()
Global function to get the current ChLog object.
Definition: ChLog.cpp:39
bool Run()
Run the Irrlicht device.
Definition: ChVisualSystemIrrlicht.cpp:217
virtual void AddLink(std::shared_ptr< ChLinkBase > link)
Attach a link to the underlying assembly.
Definition: ChSystem.cpp:164
void AddCamera(const ChVector<> &pos, ChVector<> targ=VNULL)
Add a camera in an Irrlicht 3D scene.
Definition: ChVisualSystemIrrlicht.cpp:268
Representation of a 3D transform.
Definition: ChFrame.h:34
virtual void BeginScene(bool backBuffer=true, bool zBuffer=true, ChColor color=ChColor(0, 0, 0))
Clean the canvas at the beginning of each animation frame.
Definition: ChVisualSystemIrrlicht.cpp:501
Namespace with classes for the Irrlicht module.
Definition: ChApiIrr.h:48
Class for a timer which attempts to enforce soft real-time.
Definition: ChRealtimeStep.h:25
void Q_from_AngY(Real angleY)
Set the quaternion from an angle of rotation about Y axis.
Definition: ChQuaternion.h:333
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 a visual color.
Definition: ChColor.h:26
const std::vector< std::shared_ptr< ChBody > > & Get_bodylist() const
Get the list of bodies.
Definition: ChSystem.h:309
Definition of general purpose 3d vector variables, such as points in 3D.
Definition: ChVector.h:35
void drawGrid(ChVisualSystemIrrlicht *vis, double ustep, double vstep, int nu, int nv, ChCoordsys<> pos, chrono::ChColor col, bool use_Zbuffer)
Draw grids in 3D space with given orientation, color, and spacing.
Definition: ChIrrTools.cpp:794
void Q_from_AngZ(Real angleZ)
Set the quaternion from an angle of rotation about Z axis.
Definition: ChQuaternion.h:336
int DoStepDynamics(double step_size)
Advances the dynamical simulation for a single step, of length step_size.
Definition: ChSystem.cpp:1422
virtual void EndScene()
End the scene draw at the end of each animation frame.
Definition: ChVisualSystemIrrlicht.cpp:546
ChVector< Real > TransformParentToLocal(const ChVector< Real > &parent) const
This function transforms a point from the parent coordinate system to a local coordinate system,...
Definition: ChCoordsys.h:249
void SetWindowTitle(const std::string &win_title)
Set the windoiw title (default "").
Definition: ChVisualSystemIrrlicht.cpp:124
virtual void AttachSystem(ChSystem *sys) override
Attach another Chrono system to the run-time visualization system.
Definition: ChVisualSystemIrrlicht.cpp:144
Class defining quaternion objects, that is four-dimensional numbers, also known as Euler parameters.
Definition: ChQuaternion.h:45
virtual void Render()
Draw all 3D shapes and GUI elements at the current frame.
Definition: ChVisualSystemIrrlicht.cpp:556
Main namespace for the Chrono package.
Definition: ChBarrelShape.cpp:17
double GetChTime() const
Get the simulation time of this system.
Definition: ChSystem.h:214
void AddLogo(const std::string &logo_filename=GetChronoDataFile("logo_chronoengine_alpha.png"))
Add a logo in a 3D scene.
Definition: ChVisualSystemIrrlicht.cpp:260
Class for a physical system in which contact is modeled using a non-smooth (complementarity-based) me...
Definition: ChSystemNSC.h:29
void SetWindowSize(unsigned int width, unsigned int height)
Set the window size (default 640x480).
Definition: ChVisualSystemIrrlicht.cpp:120
ChVector< Real > TransformLocalToParent(const ChVector< Real > &local) const
This function transforms a point from the local coordinate system to the parent coordinate system.
Definition: ChCoordsys.h:241
Real Length() const
Compute the euclidean norm of the vector, that is its length or magnitude.
Definition: ChVector.h:835