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, Radu Serban
// =============================================================================
//
// 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/ChRealtimeStep.h"
#include "chrono_irrlicht/ChVisualSystemIrrlicht.h"
using namespace chrono;
using namespace chrono::irrlicht;
// -----------------------------------------------------------------------------
// Apply forces caused by a rotating fan, to all objects in front of it.
ChCoordsys<>& fan_csys, // pos and rotation of fan
double aradius, // radius of fan
double aspeed, // speed of fan
double adensity) // density (heuristic)
{
// Add forces to the body accumulator (only one accumulator defined for each body)
// Reset accumulator
body->EmptyAccumulator(0);
// Initialize speed of air (steady, if outside fan stream)
ChVector3d abs_wind(0, 0, 0);
// Calculate the position of body COG in fan coordinates
ChVector3d mrelpos = fan_csys.TransformPointParentToLocal(body->GetPos());
ChVector3d mrelpos_ondisc = mrelpos;
mrelpos_ondisc.z() = 0;
if (mrelpos.z() > 0) // if not behind fan..
if (mrelpos_ondisc.Length() < aradius) {
// Inside wind stream cylinder; wind is directed as normal to the fan disc
abs_wind = fan_csys.TransformPointLocalToParent(ChVector3d(0, 0, 1));
// Wind inside fan stream is constant speed
abs_wind *= -aspeed;
}
// Simple force proportional to relative speed body-wind and fluid density
ChVector3d abs_force = (abs_wind - body->GetPosDt()) * adensity;
// apply this force at the body COG
body->AccumulateForce(0, abs_force, body->GetPos(), false);
}
}
// -----------------------------------------------------------------------------
int main(int argc, char* argv[]) {
std::cout << "Copyright (c) 2017 projectchrono.org\nChrono version: " << CHRONO_VERSION << std::endl;
// Create a Chrono physical system
ChSystemNSC sys;
// Create five pendulum chains
for (int k = 0; k < 5; k++) {
double z_step = (double)k * 2.;
// Create pendulum bodies
auto body0 = chrono_types::make_shared<ChBodyEasyBox>(5, 1, 0.5, // x,y,z size
100, // density
true, // visualization?
false); // collision?
body0->SetPos(ChVector3d(0, 0, z_step));
body0->SetFixed(true);
sys.Add(body0);
auto body1 = chrono_types::make_shared<ChBodyEasyBox>(1, 6, 1, // x,y,z size
1, // density
true, // visualization?
false); // collision?
body1->SetPos(ChVector3d(0, -3, z_step));
sys.Add(body1);
auto body2 = chrono_types::make_shared<ChBodyEasyBox>(1, 6, 1, // x,y,z size
1, // density
true, // visualization?
false); // collision?
body2->SetPos(ChVector3d(0, -9, z_step));
sys.Add(body2);
auto body3 = chrono_types::make_shared<ChBodyEasyBox>(6, 1, 1, // x,y,z size
1, // density
true, // visualization?
false); // collision?
body3->SetPos(ChVector3d(3, -12, z_step));
sys.Add(body3);
// Create a joint of type 'point on a line', with upper and lower limits on the X sliding direction=
auto point_line_01 = chrono_types::make_shared<ChLinkLockPointLine>();
point_line_01->Initialize(body1, body0, ChFrame<>(ChVector3d(0, 0, z_step)));
point_line_01->LimitX().SetActive(true);
point_line_01->LimitX().SetMax(1.0);
point_line_01->LimitX().SetMin(-1.0);
sys.AddLink(point_line_01);
// Create a spherical joint
auto spherical_12 = chrono_types::make_shared<ChLinkLockSpherical>();
spherical_12->Initialize(body2, body1, ChFrame<>(ChVector3d(0, -6, z_step)));
sys.AddLink(spherical_12);
// Create a second spherical joint
auto spherical_23 = chrono_types::make_shared<ChLinkLockSpherical>();
spherical_23->Initialize(body3, body2, ChFrame<>(ChVector3d(0, -12, z_step)));
sys.AddLink(spherical_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(ChVector3d(0, 14, -20));
vis->AddTypicalLights();
// Create a 'fan ventilator' object (visualization only)
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));
// Add one force accumulator to each body in the system
body->AddAccumulator();
}
// 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<>(ChVector3d(0, -20, 0), QuatFromAngleX(CH_PI_2)),
ChColor(0.3f, 0.5f, 0.5f), true);
// Update the position of the spinning fan (for visualization purposes only)
ChQuaternion<> my_fan_rotation;
my_fan_rotation.SetFromAngleY(sys.GetChTime() * -0.5);
ChQuaternion<> my_fan_spin;
my_fan_spin.SetFromAngleZ(sys.GetChTime() * 4);
ChCoordsys<> my_fan_coord(ChVector3d(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).GetCoordsys();
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 function
apply_fan_force(sys, my_fan_coord, fan_radius, 5.2, 0.5);
sys.DoStepDynamics(timestep);
realtime_timer.Spin(timestep);
}
return 0;
}
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
ChQuaterniond QuatFromAngleX(double angle)
Convert from a rotation about X axis to a quaternion.
Definition: ChRotation.cpp:188
void Add(std::shared_ptr< ChPhysicsItem > item)
Attach an arbitrary ChPhysicsItem (e.g.
Definition: ChSystem.cpp:200
ChVector3< Real > TransformPointLocalToParent(const ChVector3< Real > &v) const
Transform a point from the local coordinate system to the parent coordinate system.
Definition: ChCoordsys.h:195
Representation of a transform with translation and rotation.
Definition: ChCoordsys.h:28
const std::vector< std::shared_ptr< ChBody > > & GetBodies() const
Get the list of bodies.
Definition: ChSystem.h:351
virtual void AddLink(std::shared_ptr< ChLinkBase > link)
Attach a link to the underlying assembly.
Definition: ChSystem.cpp:148
Class for a timer which attempts to enforce soft real-time.
Definition: ChRealtimeStep.h:25
Real Length() const
Compute the euclidean norm of the vector, that is its length or magnitude.
Definition: ChVector3.h:847
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
void SetFromAngleY(Real angleY)
Set the quaternion from an angle of rotation about Y axis.
Definition: ChQuaternion.h:320
void SetFromAngleZ(Real angleZ)
Set the quaternion from an angle of rotation about Z axis.
Definition: ChQuaternion.h:323
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:879
int DoStepDynamics(double step_size)
Advance the dynamics simulation by a single time step of given length.
Definition: ChSystem.cpp:1636
ChVector3< Real > TransformPointParentToLocal(const ChVector3< Real > &v) const
Transforms a point from the parent coordinate system to local coordinate system.
Definition: ChCoordsys.h:198
ChVector3< double > ChVector3d
Alias for double-precision vectors.
Definition: ChVector3.h:283
Class defining quaternion objects, that is four-dimensional numbers.
Definition: ChQuaternion.h:34
double GetChTime() const
Get the simulation time of this system.
Definition: ChSystem.h:160
Class for a physical system in which contact is modeled using a non-smooth (complementarity-based) me...
Definition: ChSystemNSC.h:29