ChronoEngine:Demo buildsystem

From ChronoWiki

Jump to: navigation, search

Tutorial which teaches the basic approach to build and simulate mechanical systems. No 3D user interface is used here, so you compile this example even if you do not have Irrlicht 3D visualization library installed.

Learn how:

  • create a physical system (a slider-crank)
  • add/remove rigid bodies
  • create mechanical joints between bodies
  • perform a simulation


Example 1

Start with creating the physical system:

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);

The ChSharedBodyPtr is a shortcut for ChSharedPtr<ChBody>, as well as there are other shortcuts like ChSharedMarkerPtr for ChSharedPtr<ChMarker> etc. Use the second form if you prefer.

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.Add(my_body_A);
my_system.Add(my_body_B);
my_system.Add(my_body_C);

Show the hierarchy in the console 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);
By the way, you can set an Ascii name for objects as desired:

my_marker_a1->SetName("JohnFoo");
..so you can later use  my_system.SearchMarker("JohnFoo"); etc.

Example 2

In this more advanced example we also add joints and run a short simulation.

Start with creating a system:

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 the initial position of the bodies (their 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);

Maybe that this 'marker' stuff requires too much typing: so please 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.

Note that the ChLinkEngine can work in 'imposed torque' or 'imposed speed' or 'imposed rotation' mode, so we want to set it in 'imposed speed' mode.

Also, the imposed speed is set via one of the ChFunction classes, so we must fetch it, check if it is already a ChFunction_Const subclass (this is by default) and if so, change the its constant value.

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);
if (ChFunction_Const* mfun = dynamic_cast<ChFunction_Const*>(my_link_AB->Get_spe_funct()))
		mfun->Set_yconst(CH_C_PI); // speed w=3.145 rad/sec
my_system.AddLink(my_link_AB);

By the way, here we show how one can use an interator to scan through already-added constraints:

ChSystem::IteratorLinks myiter = my_system.IterBeginLinks();
while (myiter != my_system.IterEndLinks())
{
	GetLog() << "   Link class: " << (*myiter)->GetRTTI()->GetName() << "  , leaves n.DOFs: "  << (*myiter)->GetLeftDOF() << "\n";
	++myiter;
}

As a final step, we perform a very simple animation:

double chronoTime = 0;
while(chronoTime<2.5)
{
	chronoTime +=0.01;

		// PERFORM SIMULATION UP TO chronoTime
	my_system.DoFrameDynamics(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";
}

Note, alternatively to DoFrameDynamics(), one could use the more explicit

   my_system.DoStepDynamics(0.01);

Also, instead of doing while(chronoTime<2.5) , one could do

   while(my_system.GetChTime()<2.5)
Personal tools