Tutorial:
demo_buildsystem.cpp
Note that the revolute joints are two ChLink objects, referencing pairs of
ChMarker objects belonging to the ChBody rigid bodies. Also the truss (i.e. the
'absolute reference frame') is a ChBody.
In Chrono::Engine, this concept is used to build mechanisms of whatever
complexity: in this tutorial we will build a slider-crank mechanism, for example.
#include "physics/CHapidll.h" #include "physics/CHsystem.h" using namespace chrono; int main(int argc, char* argv[]) { // The DLL_CreateGlobals() - DLL_DeleteGlobals(); pair is needed if // global functions are needed. ChGlobals* GLOBAL_Vars = DLL_CreateGlobals();
Example 1: manage the hierarchy of rigid bodies
The following few statements teach how to dreate a ChSystem, how to add rigid
bodies to it, and how to remove rigid bodies. Also, see how ChMarker objects are
added/removed from rigid bodies.
{ // The physical system: it contains all physical objects. ChSystem my_system; // Create a bunch of rigid bodies.. // Note that we use shared pointers, so you don't // have to care about the deletion (never use delete.. for // objects managed with shared pointers! it will be automatic!) ChSharedBodyPtr my_body_A(new ChBody); ChSharedBodyPtr my_body_B(new ChBody); ChSharedBodyPtr my_body_C(new ChBody); // Create some markers.. // Markers are 'auxiliary coordinate systems' to be added // to rigid bodies. // Again, note that they are managed by shared pointers. ChSharedMarkerPtr my_marker_a1(new ChMarker); ChSharedMarkerPtr my_marker_a2(new ChMarker); ChSharedMarkerPtr my_marker_b1(new ChMarker); ChSharedMarkerPtr my_marker_b2(new ChMarker); // You can create some forces too... ChSharedForcePtr my_force_a1(new ChForce); ChSharedForcePtr my_force_a2(new ChForce); // Here you will add forces and markers to rigid // bodies. // Note: the same marker shouldn't be added to multiple bodies. my_body_A->AddMarker(my_marker_a1); my_body_A->AddMarker(my_marker_a2); my_body_A->AddForce (my_force_a1); my_body_A->AddForce (my_force_a2); my_body_B->AddMarker(my_marker_b1); my_body_B->AddMarker(my_marker_b2); // Ok, remember that rigid bodies must be added to // the physical system. my_system.AddBody(my_body_A); my_system.AddBody(my_body_B); my_system.AddBody(my_body_C); // Show the hierarchy in the shell window... GetLog() << "Here's the system hierarchy which you built: \n\n "; my_system.ShowHierarchy( GetLog() ); // Do you want to remove items? Use the // Remove...() functions. my_body_A->RemoveAllForces(); // Remove a single body.. my_system.RemoveBody(my_body_A); // Add markers to another body... my_body_B->AddMarker(my_marker_a1); my_body_B->AddMarker(my_marker_a2); my_body_B->AddForce(my_force_a1); my_body_B->AddForce(my_force_a2); GetLog() << "\n\n\nHere's the system hierarchy after modifications: \n\n "; my_system.ShowHierarchy( GetLog()); }
Example 2: now that you have learned how to manage the database of
rigid bodies, you can easily understand the following block of code, which is
used to create a meaningful mechanism: the SLIDER-CRANK mechanism.
A slider-crank is made of a rotating crank (or a flywheel) and a rod, like in
pumps, piston engines, etc.
In our simple example there is no piston: we have only 3 rigid bodies:
- the truss (fixed, as an absolute reference),
- the crank
- the rod.
Also, there are three 3D mechanical constraints, represented by objects of
classes inherited from ChLink:
- the engine, between the truss and the crank,
- the revolute joint between the crank and the rod,
- the sliding joint between the other end of the rod and the truss.
We assume that the sliding motion of the rod is on the horizontal plane.
{ // // EXAMPLE 2: // GetLog() << " Example: create a slider-crank system: \n"; // The physical system: it contains all physical objects. ChSystem my_system; // Create three rigid bodies and add them to the system: ChSharedBodyPtr my_body_A(new ChBody); // truss ChSharedBodyPtr my_body_B(new ChBody); // crank ChSharedBodyPtr my_body_C(new ChBody); // rod my_system.AddBody(my_body_A); my_system.AddBody(my_body_B); my_system.AddBody(my_body_C); // Set initial position of the bodies (center of mass) my_body_A->SetBodyFixed(true); // truss does not move! my_body_B->SetPos(ChVector<>(1,0,0)); my_body_C->SetPos(ChVector<>(4,0,0)); // Create two markers and add them to two bodies: // they will be used as references for 'rod-crank'link. ChSharedMarkerPtr my_marker_b(new ChMarker); ChSharedMarkerPtr my_marker_c(new ChMarker); my_body_B->AddMarker(my_marker_b); my_body_C->AddMarker(my_marker_c); // Set absolute position of the two markers, // for the initial position of the 'rod-crank' link: my_marker_b->Impose_Abs_Coord(ChCoordsys<>(ChVector<>(2,0,0))); my_marker_c->Impose_Abs_Coord(ChCoordsys<>(ChVector<>(2,0,0))); // Now create a mechanical link (a revolute joint) // between these two markers, and insert in system: ChSharedPtr<ChLinkLockRevolute> my_link_BC(new ChLinkLockRevolute); my_link_BC->Initialize(my_marker_b, my_marker_c); my_system.AddLink(my_link_BC); // Phew! All this 'marker' stuff is boring! // Note that there's an easier way to create a link, // without needing the two markers (they will be // automatically created and added to the two bodies) // i.e. is using two bodies and a position as arguments.. // For example, to create the rod-truss constraint: ChSharedPtr<ChLinkLockPointLine> my_link_CA(new ChLinkLockPointLine); my_link_CA->Initialize(my_body_C, my_body_A, ChCoordsys<>(ChVector<>(6,0,0))); my_system.AddLink(my_link_CA); // Now create a 'motor' link between crank and truss, // in 'imposed speed' mode: ChSharedPtr<ChLinkEngine> my_link_AB(new ChLinkEngine); my_link_AB->Initialize(my_body_A, my_body_B, ChCoordsys<>(ChVector<>(0,0,0))); my_link_AB->Set_eng_mode(ChLinkEngine::ENG_MODE_SPEED); my_link_AB->Get_spe_funct()->Set_yconst(CH_C_PI); // speed w=3.145 rad/sec my_system.AddLink(my_link_AB); GetLog() << "\n\n\nHere's the system hierarchy for slider-crank: \n\n "; my_system.ShowHierarchy( GetLog()); // OK! NOW GET READY FOR THE DYNAMICAL SIMULATION! my_system.Setup(); // Allocate and resize auxiliary system data my_system.Update_B2Y(); // Current body positions -> initial system state // A very simple simulation loop.. double chronoTime = 0; while(chronoTime<2.5) { chronoTime +=0.01; // PERFORM SIMULATION UP TO chronoTime my_system.FrameDynamics(chronoTime); // Print something on the console.. GetLog() << "Time: " << chronoTime << " Slider X position: " << my_link_CA->GetMarker1()->GetAbsCoord().pos.x << " Engine torque: " << my_link_AB->Get_mot_retorque() << "\n"; } } // Remember this at the end of the program, if you started // with DLL_CreateGlobals(); DLL_DeleteGlobals(); return 0; }