示例#1
0
		// Build and initialize the tank, creating all bodies corresponding to
		// the various parts and adding them to the physical system - also creating
		// and adding constraints to the system.
	MySimpleTank(ChSystem&  my_system,	///< the chrono::engine physical system 
				ISceneManager* msceneManager, ///< the Irrlicht scene manager for 3d shapes
				IVideoDriver* mdriver	///< the Irrlicht video driver
				)
			{
				throttleL = throttleR = 0; // initially, gas throttle is 0.
				max_motor_speed = 10;

				double my = 0.5; // left back hub pos
				double mx = 0;

				double shoelength = 0.2;
				double shoethickness = 0.06;
				double shoewidth = 0.3;
				double shoemass = 2;
				double radiustrack = 0.31;
				double wheeldiameter = 0.280*2;	
				int nwrap = 6;
				int ntiles = 7;
				double rlwidth = 1.20;
				double passo = (ntiles+1)*shoelength;

				ChVector<> cyl_displA(0,  0.075+0.02,0);
				ChVector<> cyl_displB(0, -0.075-0.02,0);
				double cyl_hthickness = 0.045;

				// --- The tank body --- 

				IAnimatedMesh*	bulldozer_bodyMesh = msceneManager->getMesh("../data/bulldozerB10.obj");
				truss = (ChBodySceneNode*)addChBodySceneNode(
														&my_system, msceneManager, bulldozer_bodyMesh,
														350.0,
														ChVector<>(mx + passo/2, my + radiustrack , rlwidth/2),
														QUNIT);
				truss->GetBody()->SetInertiaXX(ChVector<>(13.8, 13.5, 10));
				truss->GetBody()->SetBodyFixed(false);
			    //truss->addShadowVolumeSceneNode();

				// --- Right Front suspension --- 

				// Load a triangle mesh for wheel visualization
				IAnimatedMesh* irmesh_wheel_view = msceneManager->getMesh("../data/wheel_view.obj");

				// ..the tank right-front wheel
				wheelRF = (ChBodySceneNode*) addChBodySceneNode(
													    &my_system, msceneManager, irmesh_wheel_view,
														9.0,
														ChVector<>(mx + passo, my+ radiustrack , 0),
														chrono::Q_from_AngAxis(CH_C_PI/2, VECT_X) );
				
				wheelRF->GetBody()->GetCollisionModel()->ClearModel();
				wheelRF->GetBody()->GetCollisionModel()->AddCylinder(wheeldiameter/2,wheeldiameter/2, cyl_hthickness, &cyl_displA);
				wheelRF->GetBody()->GetCollisionModel()->AddCylinder(wheeldiameter/2,wheeldiameter/2, cyl_hthickness, &cyl_displB);
				wheelRF->GetBody()->GetCollisionModel()->BuildModel();			// Creates the collision model
				wheelRF->GetBody()->SetCollide(true);
				wheelRF->GetBody()->SetInertiaXX(ChVector<>(1.2, 1.2, 1.2));
				wheelRF->GetBody()->SetFriction(1.0);
					video::ITexture* cylinderMap = mdriver->getTexture("../data/bluwhite.png");
				wheelRF->setMaterialTexture(0,	cylinderMap);
				wheelRF->addShadowVolumeSceneNode();

				// .. create the revolute joint between the wheel and the truss
				link_revoluteRF = ChSharedPtr<ChLinkLockRevolute>(new ChLinkLockRevolute); // right, front, upper, 1
				link_revoluteRF->Initialize(wheelRF->GetBody(), truss->GetBody(), 
					ChCoordsys<>(ChVector<>(mx + passo, my+ radiustrack , 0) , QUNIT ) );
				my_system.AddLink(link_revoluteRF);


				// --- Left Front suspension --- 

				// ..the tank left-front wheel

				wheelLF = (ChBodySceneNode*) addChBodySceneNode(
													    &my_system, msceneManager, irmesh_wheel_view,
														9.0,
														ChVector<>(mx + passo, my+ radiustrack , rlwidth),
														chrono::Q_from_AngAxis(CH_C_PI/2, VECT_X) );

				wheelLF->GetBody()->GetCollisionModel()->ClearModel();
				wheelLF->GetBody()->GetCollisionModel()->AddCylinder(wheeldiameter/2,wheeldiameter/2, cyl_hthickness, &cyl_displA);
				wheelLF->GetBody()->GetCollisionModel()->AddCylinder(wheeldiameter/2,wheeldiameter/2, cyl_hthickness, &cyl_displB);
				wheelLF->GetBody()->GetCollisionModel()->BuildModel();			// Creates the collision model
				wheelLF->GetBody()->SetCollide(true);
				wheelLF->GetBody()->SetInertiaXX(ChVector<>(1.2, 1.2, 1.2));
				wheelLF->GetBody()->SetFriction(1.0);
				wheelLF->setMaterialTexture(0,	cylinderMap);
				wheelLF->addShadowVolumeSceneNode();

				// .. create the revolute joint between the wheel and the truss
				link_revoluteLF = ChSharedPtr<ChLinkLockRevolute>(new ChLinkLockRevolute); // left, front, upper, 1
				link_revoluteLF->Initialize(wheelLF->GetBody(), truss->GetBody(), 
					ChCoordsys<>(ChVector<>(mx + passo, my+ radiustrack , rlwidth) , QUNIT ) );
				my_system.AddLink(link_revoluteLF);


				// --- Right Back suspension --- 

				// ..the tank right-back wheel

				wheelRB = (ChBodySceneNode*) addChBodySceneNode(
													    &my_system, msceneManager, irmesh_wheel_view,
														9.0,
														ChVector<>(mx , my+ radiustrack , 0),
														chrono::Q_from_AngAxis(CH_C_PI/2, VECT_X) );
				
				wheelRB->GetBody()->GetCollisionModel()->ClearModel();
				wheelRB->GetBody()->GetCollisionModel()->AddCylinder(wheeldiameter/2,wheeldiameter/2, cyl_hthickness, &cyl_displA);
				wheelRB->GetBody()->GetCollisionModel()->AddCylinder(wheeldiameter/2,wheeldiameter/2, cyl_hthickness, &cyl_displB);
				wheelRB->GetBody()->GetCollisionModel()->BuildModel();			// Creates the collision model
				wheelRB->GetBody()->SetCollide(true);
				wheelRB->GetBody()->SetInertiaXX(ChVector<>(1.2, 1.2, 1.2));
				wheelRB->GetBody()->SetFriction(1.0);
					cylinderMap = mdriver->getTexture("../data/bluwhite.png");
				wheelRB->setMaterialTexture(0,	cylinderMap);
				wheelRB->addShadowVolumeSceneNode();

				// .. create the motor joint between the wheel and the truss (simplified motor model: just impose speed..)
				link_revoluteRB = ChSharedPtr<ChLinkEngine>(new ChLinkEngine); // right, back, upper, 1
				link_revoluteRB->Initialize(wheelRB->GetBody(), truss->GetBody(), 
					ChCoordsys<>(ChVector<>(mx , my+ radiustrack , 0) , QUNIT ) );
				link_revoluteRB->Set_eng_mode(ChLinkEngine::ENG_MODE_SPEED);
				my_system.AddLink(link_revoluteRB);


				// --- Left Back suspension --- 

				// ..the tank left-back wheel

				wheelLB = (ChBodySceneNode*) addChBodySceneNode(
													    &my_system, msceneManager, irmesh_wheel_view,
														9.0,
														ChVector<>(mx , my+ radiustrack , rlwidth),
														chrono::Q_from_AngAxis(CH_C_PI/2, VECT_X) );
				
				wheelLB->GetBody()->GetCollisionModel()->ClearModel();
				wheelLB->GetBody()->GetCollisionModel()->AddCylinder(wheeldiameter/2,wheeldiameter/2, cyl_hthickness, &cyl_displA);
				wheelLB->GetBody()->GetCollisionModel()->AddCylinder(wheeldiameter/2,wheeldiameter/2, cyl_hthickness, &cyl_displB);
				wheelLB->GetBody()->GetCollisionModel()->BuildModel();			// Creates the collision model
				wheelLB->GetBody()->SetCollide(true);
				wheelLB->GetBody()->SetInertiaXX(ChVector<>(1.2, 1.2, 1.2));
				wheelLB->GetBody()->SetFriction(1.0);
				wheelLB->setMaterialTexture(0,	cylinderMap);
				wheelLB->addShadowVolumeSceneNode();

				// .. create the motor joint between the wheel and the truss (simplified motor model: just impose speed..)
				link_revoluteLB = ChSharedPtr<ChLinkEngine>(new ChLinkEngine); // left, back, upper, 1
				link_revoluteLB->Initialize(wheelLB->GetBody(), truss->GetBody(), 
					ChCoordsys<>(ChVector<>(mx , my+ radiustrack , rlwidth) ,  QUNIT ) );
				link_revoluteLB->Set_eng_mode(ChLinkEngine::ENG_MODE_SPEED);
				my_system.AddLink(link_revoluteLB);


				//--- TRACKS ---
				
				// Load a triangle mesh for visualization
				IAnimatedMesh* irmesh_shoe_view = msceneManager->getMesh("../data/shoe_view.obj");
				
				// Load a triangle mesh for collision
				IAnimatedMesh* irmesh_shoe_collision = msceneManager->getMesh("../data/shoe_collision.obj");
				ChTriangleMeshSoup temp_trianglemesh; 
				fillChTrimeshFromIrlichtMesh(&temp_trianglemesh, irmesh_shoe_collision->getMesh(0));


				chrono::ChVector<> mesh_displacement(shoelength*0.5,0,0);  // since mesh origin is not in body center of mass
				chrono::ChVector<> joint_displacement(-shoelength*0.5,0,0); // position of shoe-shoe constraint, relative to COG.

				chrono::ChVector<> position;
				chrono::ChQuaternion<> rotation;
				
				

				for (int side = 0; side <2; side ++)
				{
					mx = 0;
					mx += shoelength;

					double mz = 0;

					if (side == 0)
						mz = 0;
					else
						mz = rlwidth;

					position.Set(mx, my, mz);
					rotation = QUNIT;

					// Create sample body (with empty collision shape; later create the collision model by adding the coll.shapes)
					ChBodySceneNode* firstBodyShoe = (ChBodySceneNode*)addChBodySceneNode(
														&my_system, msceneManager, 0,   
														shoemass, 
														position, 	
														rotation);
					// Creates the collision model with a (simplified) mesh
					ChVector<> pin_displacement = mesh_displacement + ChVector<>(0,0.05,0);
					firstBodyShoe->GetBody()->GetCollisionModel()->SetSafeMargin(0.004);	// inward safe margin
					firstBodyShoe->GetBody()->GetCollisionModel()->SetEnvelope(0.010);		// distance of the outward "collision envelope"
					firstBodyShoe->GetBody()->GetCollisionModel()->ClearModel();
					 // ...try to use a concave (simplified) mesh plus automatic convex decomposition?? ...
					 firstBodyShoe->GetBody()->GetCollisionModel()->AddTriangleMesh(temp_trianglemesh, false, false, &mesh_displacement);	// not static, not convex
					 // .. or rather use few 'primitive' shapes to approximate with cubes/etc?? 
					 //firstBodyShoe->GetBody()->GetCollisionModel()->AddBox(shoelength/2, shoethickness/2, shoewidth/2, &mesh_displacement);
					 //firstBodyShoe->GetBody()->GetCollisionModel()->AddBox(0.04, 0.02, 0.02, &pin_displacement);
					firstBodyShoe->GetBody()->GetCollisionModel()->BuildModel();			// Creates the collision model
					firstBodyShoe->GetBody()->SetCollide(true);

					/*  // alternative: use box as a collision geometry (but wheels will slip..)
					ChBodySceneNode* firstBodyShoe =  (ChBodySceneNode*)addChBodySceneNode_easyBox(
															&my_system, msceneManager,
															shoemass,
															position,
															rotation, 
															ChVector<>(shoelength, 0.02, 0.2) );
					*/

					// Add a mesh for visualization purposes
					msceneManager->addAnimatedMeshSceneNode(irmesh_shoe_view, firstBodyShoe,-1, vector3dfCH(mesh_displacement));

					// Avoid creation of contacts with neighbouring shoes, using
					// a collision family (=3) that does not collide with itself 
					firstBodyShoe->GetBody()->GetCollisionModel()->SetFamily(3);
					firstBodyShoe->GetBody()->GetCollisionModel()->SetFamilyMaskNoCollisionWithFamily(3);
	 
					// Other settings
					firstBodyShoe->GetBody()->SetInertiaXX(ChVector<>(0.1, 0.1, 0.1));

					ChBodySceneNode* previous_rigidBodyShoe = firstBodyShoe;

					for (int nshoe = 1; nshoe < ntiles; nshoe++)
					{
						mx += shoelength;
						position.Set(mx, my, mz);

						ChBodySceneNode* rigidBodyShoe = MakeShoe(previous_rigidBodyShoe, 
							firstBodyShoe, 
							position, rotation, 
							irmesh_shoe_view, 
							my_system, msceneManager, mdriver,
							mesh_displacement, joint_displacement, shoemass);

						previous_rigidBodyShoe = rigidBodyShoe;
					}
					for (int nshoe = 0; nshoe < nwrap; nshoe++)
					{
						double alpha = (CH_C_PI/((double)(nwrap-1.0)))*((double)nshoe);
						
						double lx = mx + shoelength + radiustrack * sin(alpha);
						double ly = my + radiustrack - radiustrack * cos(alpha);
						position.Set(lx, ly, mz);
						rotation = chrono::Q_from_AngAxis(alpha,ChVector<>(0,0,1));
						ChBodySceneNode* rigidBodyShoe = MakeShoe(previous_rigidBodyShoe, 
							firstBodyShoe, 
							position, rotation, 
							irmesh_shoe_view, 
							my_system, msceneManager, mdriver,
							mesh_displacement, joint_displacement, shoemass);

						previous_rigidBodyShoe = rigidBodyShoe;
					}
					for (int nshoe = (ntiles-1); nshoe >= 0; nshoe--)
					{
						position.Set(mx, my+2*radiustrack, mz);

						ChBodySceneNode* rigidBodyShoe = MakeShoe(previous_rigidBodyShoe, 
							firstBodyShoe, 
							position, rotation, 
							irmesh_shoe_view, 
							my_system, msceneManager, mdriver,
							mesh_displacement, joint_displacement, shoemass);

						previous_rigidBodyShoe = rigidBodyShoe;

						mx -= shoelength;
					}
					for (int nshoe = 0; nshoe < nwrap; nshoe++)
					{
						double alpha = CH_C_PI + (CH_C_PI/((double)(nwrap-1.0)))*((double)nshoe);
						
						double lx = mx + 0 + radiustrack * sin(alpha);
						double ly = my + radiustrack - radiustrack * cos(alpha);
						position.Set(lx, ly, mz);
						rotation = chrono::Q_from_AngAxis(alpha,ChVector<>(0,0,1));
						ChBodySceneNode* rigidBodyShoe = MakeShoe(previous_rigidBodyShoe, 
							firstBodyShoe, 
							position, rotation, 
							irmesh_shoe_view, 
							my_system, msceneManager, mdriver,
							mesh_displacement, joint_displacement, shoemass);

						previous_rigidBodyShoe = rigidBodyShoe;
					}
					// close track
					ChVector<> linkpos = firstBodyShoe->GetBody()->Point_Body2World(&joint_displacement);
					ChSharedPtr<ChLinkLockRevolute> link_revolute_shoeshoe(new ChLinkLockRevolute); 
					link_revolute_shoeshoe->Initialize(firstBodyShoe->GetBody(), previous_rigidBodyShoe->GetBody(), 
								ChCoordsys<>( linkpos , QUNIT) );
					my_system.AddLink(link_revolute_shoeshoe);
				

				}

		
			} 
示例#2
0
MySimpleCar::MySimpleCar(ChSystem&  my_system,	///< the chrono::engine physical system 
				ISceneManager* msceneManager,	///< the Irrlicht scene manager for 3d shapes
				IVideoDriver* mdriver			///< the Irrlicht video driver
				)
{
	throttle = 0; // initially, gas throttle is 0.
	conic_tau = 0.2; 

	gears[0] = -0.3; // rear gear<
	gears[1] =  0.3; // 1st gear
	gears[2] =  0.4; // 2nd gear
	gears[3] =  0.6; // 3rd gear
	gears[4] =  0.8; // 4th gear
	gears[5] =  1.0; // 5th gear

	actual_gear = 1;
	gear_tau = gears[actual_gear];

	// Define the torque curve with some polygonal approximation, entering 
	// a sequence of x-y pairs (speed-torque, with speed in [rad/s] and torque in [Nm])
	// (Of course a real engine should have not-null torque only from some positive value, but
	// here we start from -50 rad/s otherwise we cannot start - given we don't model the clutch)
	torque_curve.AddPoint(-50, 35);  
	torque_curve.AddPoint(0,  45);
	torque_curve.AddPoint(400,50);
	torque_curve.AddPoint(700,54);
	torque_curve.AddPoint(850, 0);
	torque_curve.AddPoint(1000, -54); // finish in 4th quadrant
	torque_curve.AddPoint(2000, -60); // finish in 4th quadrant
	
	ChStreamOutAsciiFile myfiletq("data_torquecurve.dat");
	torque_curve.FileAsciiPairsSave(myfiletq,-100,1000,200);
	
	motorspeed= motortorque=0;

	passo = 1.73162;
	carr  = 0.59963;

	wanted_steer = 0;
	actual_steer = 0;
	max_steer_speed = 0.5;

	convergenza_anteriore = 0;
	convergenza_posteriore = 0;
 
	max_brake_torque_post = 200;
	max_brake_torque_ant  = 300;
	braking = 0;

	// --- The car body ---

		// Set the position of the center of gravity of the truss, respect to the auxiliary reference that
		// we will use to measure all relative positions of joints on the truss. 
	truss_COG.Set( 0, 0, 0); 

	truss = (ChBodySceneNode*)addChBodySceneNode(
											&my_system, msceneManager, 0,
											150.0,
											ChVector<>(0, 0.016 ,1.99) +truss_COG,
											QUNIT);
	truss->GetBody()->SetInertiaXX(ChVector<>(4.8, 4.5, 1));
	truss->GetBody()->SetBodyFixed(false);
	 


		// Add some 'invisible' boxes which roughly define the collision shape of
		// the car truss. Each colliding box must be defined in x y z half-sizes and position of 
		// box center respect to the truss COG.
	truss->GetBody()->GetCollisionModel()->ClearModel();
	truss->GetBody()->GetCollisionModel()->AddBox(0.3, 0.3, 1.5,   &(ChVector<>(0,0.2,0)-truss_COG) ); // just example.. roughly the body
	truss->GetBody()->GetCollisionModel()->AddBox(0.1, 0.3, 0.1,   &(ChVector<>(0,0.4,0)-truss_COG) ); // just example.. roughly the rollbar
	truss->GetBody()->GetCollisionModel()->BuildModel();
	truss->GetBody()->SetCollide(true);

		// Add a visible mesh for Irrlicht representation of the
		// car - it must be found on disk with the relative path as indicated..
	IAnimatedMesh* scocca_mesh = msceneManager->getMesh("../data/mycar.obj");
	IAnimatedMeshSceneNode* scocca_node = msceneManager->addAnimatedMeshSceneNode( scocca_mesh, truss );
	scocca_node->setPosition(vector3dfCH(-truss_COG)); // if COG is not the reference we use for all stuff in truss..
	scocca_node->addShadowVolumeSceneNode();

	// --- Right Front suspension --- 

	// ..the car right-front spindle
	spindleRF = (ChBodySceneNode*)addChBodySceneNode_easyBox(
											&my_system, msceneManager,
											8.0,// mass of the spindle
											ChVector<>(-(carr-0.05216), 0.02865 ,0.93534),
											QUNIT, 
											ChVector<>(0.05, 0.22, 0.16) );
	spindleRF->GetBody()->SetInertiaXX(ChVector<>(0.2, 0.2, 0.2));
	spindleRF->GetBody()->SetCollide(false);

	// ..the car right-front wheel
	wheelRF = (ChBodySceneNode*)addChBodySceneNode_easyCylinder(
											&my_system, msceneManager,
											3.0,
											ChVector<>(-carr ,0.02865 ,0.93534),
											chrono::Q_from_AngAxis(CH_C_PI/2, VECT_Z),  //rotate, otherwise flat,horizontal
											ChVector<>(0.42, 0.17, 0.42) );
	wheelRF->GetBody()->SetInertiaXX(ChVector<>(0.2, 0.2, 0.2));
	wheelRF->GetBody()->SetCollide(true);
	wheelRF->GetBody()->SetFriction(1.3);;
	wheelRF->GetBody()->SetName("wheelRF");
		video::ITexture* cylinderMap = mdriver->getTexture("../data/bluwhite.png");
	wheelRF->setMaterialTexture(0,	cylinderMap);
	wheelRF->addShadowVolumeSceneNode();

	// .. create the revolute joint between the wheel and the spindle
	//    Note that we specify two ChCoordinates of two markers which will be added in the two bodies,
	//    but both rotated with Z their axes pointing laterally thank to the Q_from_AngAxis() 90 degrees 
	//    rotations if necessary, because ChLinkLockRevolute will use the Z axes of markers as shafts.
	link_revoluteRF = ChSharedPtr<ChLinkLockRevolute>(new ChLinkLockRevolute); // right, front, upper, 1
	link_revoluteRF->Initialize(wheelRF->GetBody(), spindleRF->GetBody(), 
		true,			// 'true' means: following two positions are relative to wheel and body
		ChCoordsys<>(ChVector<>(0,0,0) , chrono::Q_from_AngAxis(CH_C_PI/2, VECT_X)) ,		  // shaft in wheel coords
		ChCoordsys<>(ChVector<>(-0.05216,0,0) , chrono::Q_from_AngAxis(CH_C_PI/2, VECT_Y)) ); // shaft in spindle coords
	my_system.AddLink(link_revoluteRF);

		// .. create the brake between the wheel and the spindle, using the same markers already created for wheel-spindle revolute joint:
	link_brakeRF = ChSharedPtr<ChLinkBrake>(new ChLinkBrake); 
	link_revoluteRF->GetMarker1()->AddRef();
	link_revoluteRF->GetMarker2()->AddRef();
	link_brakeRF->Initialize(ChSharedMarkerPtr(link_revoluteRF->GetMarker1()), 
							 ChSharedMarkerPtr(link_revoluteRF->GetMarker2()) );
	my_system.AddLink(link_brakeRF);

	// .. impose distance between two parts (as a massless rod with two spherical joints at the end)
	link_distRFU1 = ChSharedPtr<ChLinkDistance>(new ChLinkDistance); // right, front, upper, 1
	link_distRFU1->Initialize(truss->GetBody(), spindleRF->GetBody(), 
		true,										// false = positions are relative to COG csystems of bodies, true = absolute positions
		ChVector<>(-0.24708, 0.09313, -1.17789)-truss_COG,  // position of 1st end rod in truss COG coordinate
		ChVector<>( 0.04263,0.0925,0),   			        // position of 2nd end rod in spindle COG coordinates
		false, 0.2895 );									// no auto-distance computation: use imposed distance (length of rod).
	my_system.AddLink(link_distRFU1);
	
	link_distRFU2 = ChSharedPtr<ChLinkDistance>(new ChLinkDistance); // right, front, upper, 2 
	link_distRFU2->Initialize(truss->GetBody(), spindleRF->GetBody(), 
		true, 
		ChVector<>(-0.24708,0.09313,-0.71972)-truss_COG,
		ChVector<>( 0.04263,0.0925,0),
		false, 0.4228 );								    // no auto-distance computation: use imposed distance (length of rod).
	my_system.AddLink(link_distRFU2);

	link_distRFL1 = ChSharedPtr<ChLinkDistance>(new ChLinkDistance); // right, front, lower, 1
	link_distRFL1->Initialize(truss->GetBody(), spindleRF->GetBody(), 
		true, 
		ChVector<>(-0.24708,-0.10273,-1.17789)-truss_COG, 
		ChVector<>( 0.04263,-0.1225,0),
		false, 0.2857 );								    // no auto-distance computation: use imposed distance (length of rod).
	my_system.AddLink(link_distRFL1);

	link_distRFL2 = ChSharedPtr<ChLinkDistance>(new ChLinkDistance); // right, front, lower, 2
	link_distRFL2->Initialize(truss->GetBody(), spindleRF->GetBody(), 
		true, 
		ChVector<>(-0.24708,-0.10273,-0.71972)-truss_COG, 
		ChVector<>( 0.04263,-0.1225,0),
		false, 0.4227 );								    // no auto-distance computation: use imposed distance (length of rod).
	my_system.AddLink(link_distRFL2);
	
	// .. create the spring between the truss and the spindle
	link_springRF = ChSharedPtr<ChLinkSpring>(new ChLinkSpring);
	link_springRF->Initialize(truss->GetBody(), spindleRF->GetBody(), 
		true, 
		ChVector<>(-0.31394,0.19399,-1.06243)-truss_COG, 
		ChVector<>( 0.06983,-0.08962,-0.00777), 
		false, 0.316);										// no auto-distance computation: use imposed spring restlength
	link_springRF->Set_SpringK(28300);
	link_springRF->Set_SpringR(80);
	my_system.AddLink(link_springRF);


	// .. create the rod for steering the wheel
	link_distRSTEER = ChSharedPtr<ChLinkDistance>(new ChLinkDistance); // right steer
	link_distRSTEER->Initialize(truss->GetBody(), spindleRF->GetBody(), 
		true, 
		ChVector<>(-0.25457,0.10598,-1.24879)-truss_COG, 
		ChVector<>( 0.06661,0.09333,-0.15003),
		false, 0.2330);										// no auto-distance computation: use imposed distance (rod length)
	my_system.AddLink(link_distRSTEER);


	// --- Left Front suspension --- 

	// ..the car left-front spindle
	spindleLF = (ChBodySceneNode*)addChBodySceneNode_easyBox(
											&my_system, msceneManager,
											8.0,// mass of the spindle
											ChVector<>( (carr-0.05216), 0.02865 ,0.93534),
											QUNIT, 
											ChVector<>(0.05, 0.22, 0.16) );
	spindleLF->GetBody()->SetInertiaXX(ChVector<>(0.2, 0.2, 0.2));
	spindleLF->GetBody()->SetCollide(false);

	// ..the car left-front wheel
	wheelLF = (ChBodySceneNode*)addChBodySceneNode_easyCylinder(
											&my_system, msceneManager,
											3.0,
											ChVector<>( carr ,0.02865 ,0.93534),
											chrono::Q_from_AngAxis(-CH_C_PI/2, VECT_Z),   //rotate, otherwise flat,horizontal
											ChVector<>(0.42, 0.17, 0.42) );
	wheelLF->GetBody()->SetInertiaXX(ChVector<>(0.2, 0.2, 0.2));
	wheelLF->GetBody()->SetCollide(true);
	wheelLF->GetBody()->SetFriction(1.3);
	wheelLF->GetBody()->SetName("wheelLF");
	wheelLF->setMaterialTexture(0,	cylinderMap);
	wheelLF->addShadowVolumeSceneNode();

	// .. create the revolute joint between the wheel and the spindle
	link_revoluteLF = ChSharedPtr<ChLinkLockRevolute>(new ChLinkLockRevolute); // left, front, upper, 1
	link_revoluteLF->Initialize(wheelLF->GetBody(), spindleLF->GetBody(), 
		true,			// 'true' means: following two positions are relative to wheel and body
		ChCoordsys<>(ChVector<>(0,0,0) , chrono::Q_from_AngAxis(-CH_C_PI/2, VECT_X)) ,  // shaft in wheel coords
		ChCoordsys<>(ChVector<>( 0.05216,0,0) , chrono::Q_from_AngAxis(CH_C_PI/2, VECT_Y)) ); // shaft in spindle coords
	my_system.AddLink(link_revoluteLF);

	// .. create the brake between the wheel and the spindle, using the same markers already created for wheel-spindle revolute joint:
	link_brakeLF = ChSharedPtr<ChLinkBrake>(new ChLinkBrake); 
	link_revoluteLF->GetMarker1()->AddRef();
	link_revoluteLF->GetMarker2()->AddRef();
	link_brakeLF->Initialize(ChSharedMarkerPtr(link_revoluteLF->GetMarker1()), 
							 ChSharedMarkerPtr(link_revoluteLF->GetMarker2()) );
	my_system.AddLink(link_brakeLF);

	// .. impose distance between two parts (as a massless rod with two spherical joints at the end)
	link_distLFU1 = ChSharedPtr<ChLinkDistance>(new ChLinkDistance); // left, front, upper, 1
	link_distLFU1->Initialize(truss->GetBody(), spindleLF->GetBody(), 
		true,										// false = positions are relative to COG csystems of bodies, true = absolute positions
		ChVector<>( 0.24708, 0.09313, -1.17789)-truss_COG,	// position of 1st end rod in truss COG coordinate
		ChVector<>(-0.04263,0.0925,0),   			        // position of 2nd end rod in spindle COG coordinates
		false, 0.2895 );									// no auto-distance computation: use imposed distance (length of rod).
	my_system.AddLink(link_distLFU1);

	link_distLFU2 = ChSharedPtr<ChLinkDistance>(new ChLinkDistance); // left, front, upper, 2 
	link_distLFU2->Initialize(truss->GetBody(), spindleLF->GetBody(), 
		true, 
		ChVector<>( 0.24708,0.09313, -0.71972)-truss_COG,
		ChVector<>(-0.04263,0.0925,0),
		false, 0.4228 );								    // no auto-distance computation: use imposed distance (length of rod).
	my_system.AddLink(link_distLFU2);


	link_distLFL1 = ChSharedPtr<ChLinkDistance>(new ChLinkDistance); // left, front, lower, 1
	link_distLFL1->Initialize(truss->GetBody(), spindleLF->GetBody(), 
		true, 
		ChVector<>( 0.24708,-0.10273,-1.17789)-truss_COG, 
		ChVector<>(-0.04263,-0.1225,0),
		false, 0.2857 );								    // no auto-distance computation: use imposed distance (length of rod).
	my_system.AddLink(link_distLFL1);


	link_distLFL2 = ChSharedPtr<ChLinkDistance>(new ChLinkDistance); // left, front, lower, 2
	link_distLFL2->Initialize(truss->GetBody(), spindleLF->GetBody(), 
		true, 
		ChVector<>( 0.24708,-0.10273,-0.71972)-truss_COG, 
		ChVector<>(-0.04263,-0.1225,0),
		false, 0.4227 );								    // no auto-distance computation: use imposed distance (length of rod).
	my_system.AddLink(link_distLFL2);
	
	// .. create the spring between the truss and the spindle
	link_springLF = ChSharedPtr<ChLinkSpring>(new ChLinkSpring);
	link_springLF->Initialize(truss->GetBody(), spindleLF->GetBody(), 
		true, 
		ChVector<>( 0.31394,0.19399,-1.06243)-truss_COG, 
		ChVector<>(-0.06983,-0.08962,-0.00777), 
		false, 0.316);										// no auto-distance computation: use imposed spring restlength
	link_springLF->Set_SpringK(28300);
	link_springLF->Set_SpringR(80);
	my_system.AddLink(link_springLF);


	// .. create the rod for steering the wheel
	link_distLSTEER = ChSharedPtr<ChLinkDistance>(new ChLinkDistance); // right steer
	link_distLSTEER->Initialize(truss->GetBody(), spindleLF->GetBody(), 
		true, 
		ChVector<>( 0.25457,0.10598,-1.24879)-truss_COG, 
		ChVector<>(-0.06661,0.09333,-0.15003),
		false, 0.2330);										// no auto-distance computation: use imposed distance (rod length)
	my_system.AddLink(link_distLSTEER);




	// --- Right Back suspension --- 


	// ..the car right-back spindle
	spindleRB = (ChBodySceneNode*)addChBodySceneNode_easyBox(
											&my_system, msceneManager,
											8.0,
											ChVector<>(-(carr-0.05216), 0.02865 ,(0.93534+passo)),
											QUNIT, 
											ChVector<>(0.05, 0.22, 0.16) );
	spindleRB->GetBody()->SetInertiaXX(ChVector<>(0.2, 0.2, 0.2));
	spindleRB->GetBody()->SetCollide(false);

	// ..the car right-back wheel
	wheelRB = (ChBodySceneNode*)addChBodySceneNode_easyCylinder(
											&my_system, msceneManager,
											3.0,
											ChVector<>(-carr ,0.02865 ,(0.93534+passo)),
											chrono::Q_from_AngAxis(CH_C_PI/2, VECT_Z),    //rotate, otherwise flat,horizontal
											ChVector<>(0.42, 0.17, 0.42) );
	wheelRB->GetBody()->SetInertiaXX(ChVector<>(1.2, 1.2, 1.2));
	wheelRB->GetBody()->SetCollide(true);
	wheelRB->GetBody()->SetFriction(1.3);
	wheelRB->GetBody()->SetName("wheelRB");
		cylinderMap = mdriver->getTexture("../data/bluwhite.png");
	wheelRB->setMaterialTexture(0,	cylinderMap);
	wheelRB->addShadowVolumeSceneNode();

	// .. create the revolute joint between the wheel and the spindle
	link_revoluteRB = ChSharedPtr<ChLinkLockRevolute>(new ChLinkLockRevolute); // right, back, upper, 1
	link_revoluteRB->Initialize(wheelRB->GetBody(), spindleRB->GetBody(), 
		true,			// 'true' means: following two positions are relative to wheel and body
		ChCoordsys<>(ChVector<>(0,0,0) , chrono::Q_from_AngAxis(CH_C_PI/2, VECT_X)) ,		  // shaft in wheel coords
		ChCoordsys<>(ChVector<>(-0.05216,0,0) , chrono::Q_from_AngAxis(CH_C_PI/2, VECT_Y)) ); // shaft in spindle coords
	my_system.AddLink(link_revoluteRB);

	// .. create the brake between the wheel and the spindle, using the same markers already created for wheel-spindle revolute joint:
	link_brakeRB = ChSharedPtr<ChLinkBrake>(new ChLinkBrake); 
	link_revoluteRB->GetMarker1()->AddRef();
	link_revoluteRB->GetMarker2()->AddRef();
	link_brakeRB->Initialize(ChSharedMarkerPtr(link_revoluteRB->GetMarker1()), 
							 ChSharedMarkerPtr(link_revoluteRB->GetMarker2()) );
	my_system.AddLink(link_brakeRB);

	// .. create the motor transmission joint between the wheel and the truss (assuming small changes of alignment)
	link_engineR = ChSharedPtr<ChLinkEngine>(new ChLinkEngine); 
	link_engineR->Initialize(wheelRB->GetBody(), truss->GetBody(), 
		ChCoordsys<>(ChVector<>(-carr,0.02865,(0.93534+passo)) , chrono::Q_from_AngAxis(CH_C_PI/2, VECT_Y)) );
	link_engineR->Set_shaft_mode(ChLinkEngine::ENG_SHAFT_CARDANO); // approx as a double Rzeppa joint
	link_engineR->Set_eng_mode(ChLinkEngine::ENG_MODE_TORQUE);
	my_system.AddLink(link_engineR);

	// .. impose distance between two parts (as a massless rod with two spherical joints at the end)
	link_distRBU1 = ChSharedPtr<ChLinkDistance>(new ChLinkDistance); // right, back, upper, 1
	link_distRBU1->Initialize(truss->GetBody(), spindleRB->GetBody(), 
		true,										
		ChVector<>(-0.24708, 0.09313, -1.17789+passo)-truss_COG,	
		ChVector<>( 0.04263,0.0925,0),   			        // position of 2nd end rod in spindle COG coordinates
		false, 0.2895 );									// no auto-distance computation: use imposed distance (length of rod).			
	my_system.AddLink(link_distRBU1);
 
	link_distRBU2 = ChSharedPtr<ChLinkDistance>(new ChLinkDistance); // right, back, upper, 2
	link_distRBU2->Initialize(truss->GetBody(), spindleRB->GetBody(), 
		true, 
		ChVector<>(-0.24708,0.09313,-0.71972+passo)-truss_COG,
		ChVector<>( 0.04263,0.0925,0),
		false, 0.4228 );								    // no auto-distance computation: use imposed distance (length of rod).
	my_system.AddLink(link_distRBU2);

	link_distRBL1 = ChSharedPtr<ChLinkDistance>(new ChLinkDistance); // right, back, lower, 1
	link_distRBL1->Initialize(truss->GetBody(), spindleRB->GetBody(), 
		true, 
		ChVector<>(-0.24708,-0.10273,-1.17789+passo)-truss_COG, 
		ChVector<>( 0.04263,-0.1225,0),
		false, 0.2857 );								    // no auto-distance computation: use imposed distance (length of rod).
	my_system.AddLink(link_distRBL1);

	link_distRBL2 = ChSharedPtr<ChLinkDistance>(new ChLinkDistance); // right, back, lower, 2
	link_distRBL2->Initialize(truss->GetBody(), spindleRB->GetBody(), 
		true, 
		ChVector<>(-0.24708,-0.10273,-0.71972+passo)-truss_COG, 
		ChVector<>( 0.04263,-0.1225,0),
		false, 0.4227 );								    // no auto-distance computation: use imposed distance (length of rod).
	my_system.AddLink(link_distRBL2);
	
	// .. create the spring between the truss and the spindle
	link_springRB = ChSharedPtr<ChLinkSpring>(new ChLinkSpring);
	link_springRB->Initialize(truss->GetBody(), spindleRB->GetBody(), 
		true, 
		ChVector<>(-0.31394,0.19399,-1.06243+passo)-truss_COG, 
		ChVector<>( 0.06983,-0.08962,-0.00777), 
		false, 0.316);										// no auto-distance computation: use imposed spring restlength
	link_springRB->Set_SpringK(28300);
	link_springRB->Set_SpringR(80);
	my_system.AddLink(link_springRB);

	// .. create the rod for avoid the steering of the wheel
	link_distRBlat = ChSharedPtr<ChLinkDistance>(new ChLinkDistance); // right rod
	link_distRBlat->Initialize(truss->GetBody(), spindleRB->GetBody(), 
		true, 
		ChVector<>(-0.25457,0.10598,-1.24879+passo)-truss_COG, 
		ChVector<>( 0.06661,0.09333,-0.10003),
		false, 0.2450);										// no auto-distance computation: use imposed distance (rod length)						
	my_system.AddLink(link_distRBlat);


	// --- Left Back suspension --- 

	// ..the car right-back spindle
	spindleLB = (ChBodySceneNode*)addChBodySceneNode_easyBox(
											&my_system, msceneManager,
											8.0,
											ChVector<>((carr-0.05216), 0.02865 ,(0.93534+passo)),
											QUNIT, 
											ChVector<>(0.05, 0.22, 0.16) );
	spindleLB->GetBody()->SetInertiaXX(ChVector<>(0.2, 0.2, 0.2));
	spindleLB->GetBody()->SetCollide(false);

	// ..the car left-back wheel
	wheelLB = (ChBodySceneNode*)addChBodySceneNode_easyCylinder(
											&my_system, msceneManager,
											3.0,
											ChVector<>(carr ,0.02865 ,(0.93534+passo)),
											chrono::Q_from_AngAxis(-CH_C_PI/2, VECT_Z),  //rotate, otherwise flat,horizontal
											ChVector<>(0.42, 0.17, 0.42) );
	wheelLB->GetBody()->SetInertiaXX(ChVector<>(1.2, 1.2, 1.2));
	wheelLB->GetBody()->SetCollide(true);
	wheelLB->GetBody()->SetFriction(1.3);
	wheelLB->GetBody()->SetName("wheelLB");
	wheelLB->setMaterialTexture(0,	cylinderMap);
	wheelLB->addShadowVolumeSceneNode();

	// .. create the revolute joint between the wheel and the spindle
	link_revoluteLB = ChSharedPtr<ChLinkLockRevolute>(new ChLinkLockRevolute); // left, back, upper, 1
	link_revoluteLB->Initialize(wheelLB->GetBody(), spindleLB->GetBody(), 
		true,			// 'true' means: following two positions are relative to wheel and body
		ChCoordsys<>(ChVector<>(0,0,0) , chrono::Q_from_AngAxis(-CH_C_PI/2, VECT_X)) ,		  // shaft in wheel coords
		ChCoordsys<>(ChVector<>(0.05216,0,0) , chrono::Q_from_AngAxis(CH_C_PI/2, VECT_Y)) ); // shaft in spindle coords
	my_system.AddLink(link_revoluteLB);

	// .. create the brake between the wheel and the spindle, using the same markers already created for wheel-spindle revolute joint:
	link_brakeLB = ChSharedPtr<ChLinkBrake>(new ChLinkBrake); 
	link_revoluteLB->GetMarker1()->AddRef();
	link_revoluteLB->GetMarker2()->AddRef();
	link_brakeLB->Initialize(ChSharedMarkerPtr(link_revoluteLB->GetMarker1()), 
							 ChSharedMarkerPtr(link_revoluteLB->GetMarker2()) );
	my_system.AddLink(link_brakeLB);

	// .. create the motor transmission joint between the wheel and the truss (assuming small changes of alignment)
	link_engineL = ChSharedPtr<ChLinkEngine>(new ChLinkEngine); 
	link_engineL->Initialize(wheelLB->GetBody(), truss->GetBody(), 
		ChCoordsys<>(ChVector<>(carr,0.02865,(0.93534+passo)) , chrono::Q_from_AngAxis(CH_C_PI/2, VECT_Y)) );
	link_engineL->Set_shaft_mode(ChLinkEngine::ENG_SHAFT_CARDANO); // approx as a double Rzeppa joint
	link_engineL->Set_eng_mode(ChLinkEngine::ENG_MODE_TORQUE);
	my_system.AddLink(link_engineL);

	// .. impose distance between two parts (as a massless rod with two spherical joints at the end)
	link_distLBU1 = ChSharedPtr<ChLinkDistance>(new ChLinkDistance); // left, back, upper, 1
	link_distLBU1->Initialize(truss->GetBody(), spindleLB->GetBody(), 
		true,										
		ChVector<>( 0.24708, 0.09313, -1.17789+passo)-truss_COG,
		ChVector<>(-0.04263,0.0925,0),   			        // position of 2nd end rod in spindle COG coordinates
		false, 0.2895 );									// no auto-distance computation: use imposed distance (length of rod).		
	my_system.AddLink(link_distLBU1);
 
	link_distLBU2 = ChSharedPtr<ChLinkDistance>(new ChLinkDistance); // left, back, upper, 2
	link_distLBU2->Initialize(truss->GetBody(), spindleLB->GetBody(), 
		true, 
		ChVector<>( 0.24708,0.09313, -0.71972+passo)-truss_COG,
		ChVector<>(-0.04263,0.0925,0),
		false, 0.4228 );								    // no auto-distance computation: use imposed distance (length of rod).
	my_system.AddLink(link_distLBU2);

	link_distLBL1 = ChSharedPtr<ChLinkDistance>(new ChLinkDistance); // left, back, lower, 1
	link_distLBL1->Initialize(truss->GetBody(), spindleLB->GetBody(), 
		true, 
		ChVector<>( 0.24708,-0.10273,-1.17789+passo)-truss_COG, 
		ChVector<>(-0.04263,-0.1225,0),
		false, 0.2857 );								    // no auto-distance computation: use imposed distance (length of rod).
	my_system.AddLink(link_distLBL1);

	link_distLBL2 = ChSharedPtr<ChLinkDistance>(new ChLinkDistance); // left, back, lower, 2
	link_distLBL2->Initialize(truss->GetBody(), spindleLB->GetBody(), 
		true, 
		ChVector<>( 0.24708,-0.10273,-0.71972+passo)-truss_COG, 
		ChVector<>(-0.04263,-0.1225,0),
		false, 0.4227 );								    // no auto-distance computation: use imposed distance (length of rod).
	my_system.AddLink(link_distLBL2);
	
	// .. create the spring between the truss and the spindle
	link_springLB = ChSharedPtr<ChLinkSpring>(new ChLinkSpring);
	link_springLB->Initialize(truss->GetBody(), spindleLB->GetBody(), 
		true, 
		ChVector<>( 0.31394,0.19399,-1.06243+passo)-truss_COG, 
		ChVector<>(-0.06983,-0.08962,-0.00777), 
		false, 0.316);										// no auto-distance computation: use imposed spring restlength
	link_springLB->Set_SpringK(28300);
	link_springLB->Set_SpringR(80);
	my_system.AddLink(link_springLB);

	// .. create the rod for avoid the steering of the wheel
	link_distLBlat = ChSharedPtr<ChLinkDistance>(new ChLinkDistance); // right 
	link_distLBlat->Initialize(truss->GetBody(), spindleLB->GetBody(), 
		true, 
		ChVector<>( 0.25457,0.10598,-1.24879+passo)-truss_COG, 
		ChVector<>(-0.06661,0.09333,-0.10003),
		false, 0.2450);										// no auto-distance computation: use imposed distance (rod length)						
	my_system.AddLink(link_distLBlat);


	// Create also the motor sound
	//
	
	 // start the sound engine with default parameters
	sound_engine = irrklang::createIrrKlangDevice();

	if (!sound_engine)
	{
		GetLog() << "Cannot start sound engine Irrklang \n";
	}

	// To play a sound, we only to call play2D(). The second parameter
	// tells the engine to play it looped.

	// play some sound stream, looped
	if (sound_engine)
		car_sound = sound_engine->play2D("../data/carsound.ogg", true, false, true);
	else 
		car_sound = 0;

}
示例#3
0
int main(int argc, char* argv[])
{
  ChSystem system;

  // Disable gravity
  system.Set_G_acc(ChVector<>(0, 0, 0));

  // Set the half-length of the two shafts
  double hl = 2;

  // Set the bend angle between the two shafts (positive rotation about the
  // global X axis)
  double angle = CH_C_PI / 6;
  double cosa = std::cos(angle);
  double sina = std::sin(angle);
  ChQuaternion<> rot = Q_from_AngX(angle);

  // Create the ground (fixed) body
  // ------------------------------

  ChSharedPtr<ChBody> ground(new ChBody);
  system.AddBody(ground);
  ground->SetIdentifier(-1);
  ground->SetBodyFixed(true);
  ground->SetCollide(false);

  // attach visualization assets to represent the revolute and cylindrical
  // joints that connect the two shafts to ground
  {
    ChSharedPtr<ChCylinderShape> cyl_1(new ChCylinderShape);
    cyl_1->GetCylinderGeometry().p1 = ChVector<>(0, 0, -hl - 0.2);
    cyl_1->GetCylinderGeometry().p2 = ChVector<>(0, 0, -hl + 0.2);
    cyl_1->GetCylinderGeometry().rad = 0.3;
    ground->AddAsset(cyl_1);

    ChSharedPtr<ChCylinderShape> cyl_2(new ChCylinderShape);
    cyl_2->GetCylinderGeometry().p1 = ChVector<>(0, -(hl - 0.2) * sina, (hl - 0.2) * cosa);
    cyl_2->GetCylinderGeometry().p2 = ChVector<>(0, -(hl + 0.2) * sina, (hl + 0.2) * cosa);
    cyl_2->GetCylinderGeometry().rad = 0.3;
    ground->AddAsset(cyl_2);
  }

  // Create the first shaft body
  // ---------------------------

  ChSharedPtr<ChBody> shaft_1(new ChBody);
  system.AddBody(shaft_1);
  shaft_1->SetIdentifier(1);
  shaft_1->SetBodyFixed(false);
  shaft_1->SetCollide(false);
  shaft_1->SetMass(1);
  shaft_1->SetInertiaXX(ChVector<>(1, 1, 0.2));
  shaft_1->SetPos(ChVector<>(0, 0, -hl));
  shaft_1->SetRot(ChQuaternion<>(1, 0, 0, 0));

  // Add visualization assets to represent the shaft (a box) and the arm of the
  // universal joint's cross associated with this shaft (a cylinder)
  {
    ChSharedPtr<ChBoxShape> box_1(new ChBoxShape);
    box_1->GetBoxGeometry().Size = ChVector<>(0.15, 0.15, 0.9 * hl);
    shaft_1->AddAsset(box_1);

    ChSharedPtr<ChCylinderShape> cyl_2(new ChCylinderShape);
    cyl_2->GetCylinderGeometry().p1 = ChVector<>(-0.2, 0, hl);
    cyl_2->GetCylinderGeometry().p2 = ChVector<>(0.2, 0, hl);
    cyl_2->GetCylinderGeometry().rad = 0.05;
    shaft_1->AddAsset(cyl_2);

    ChSharedPtr<ChColorAsset> col(new ChColorAsset);
    col->SetColor(ChColor(0.6f, 0, 0));
    shaft_1->AddAsset(col);
  }


  // Create the second shaft body
  // ----------------------------

  // The second shaft is identical to the first one, but initialized at an angle
  // equal to the specified bend angle.

  ChSharedPtr<ChBody> shaft_2(new ChBody);
  system.AddBody(shaft_2);
  shaft_2->SetIdentifier(1);
  shaft_2->SetBodyFixed(false);
  shaft_2->SetCollide(false);
  shaft_2->SetMass(1);
  shaft_2->SetInertiaXX(ChVector<>(1, 1, 0.2));
  shaft_2->SetPos(ChVector<>(0, -hl * sina, hl * cosa));
  shaft_2->SetRot(rot);

  // Add visualization assets to represent the shaft (a box) and the arm of the
  // universal joint's cross associated with this shaft (a cylinder)
  {
    ChSharedPtr<ChBoxShape> box_1(new ChBoxShape);
    box_1->GetBoxGeometry().Size = ChVector<>(0.15, 0.15, 0.9 * hl);
    shaft_2->AddAsset(box_1);

    ChSharedPtr<ChCylinderShape> cyl_2(new ChCylinderShape);
    cyl_2->GetCylinderGeometry().p1 = ChVector<>(0, -0.2, -hl);
    cyl_2->GetCylinderGeometry().p2 = ChVector<>(0, 0.2, -hl);
    cyl_2->GetCylinderGeometry().rad = 0.05;
    shaft_2->AddAsset(cyl_2);

    ChSharedPtr<ChColorAsset> col(new ChColorAsset);
    col->SetColor(ChColor(0, 0, 0.6f));
    shaft_2->AddAsset(col);
  }

  // Connect the first shaft to ground
  // ---------------------------------

  // Use a ChLinkEngine to impose both the revolute joint constraints, as well
  // as constant angular velocity.  The joint is located at the origin of the
  // first shaft.

  ChSharedPtr<ChLinkEngine> motor(new ChLinkEngine);
  system.AddLink(motor);
  motor->Initialize(ground, shaft_1, ChCoordsys<>(ChVector<>(0, 0, -hl), ChQuaternion<>(1, 0, 0, 0)));
  motor->Set_eng_mode(ChLinkEngine::ENG_MODE_ROTATION);
  motor->Set_rot_funct(ChSharedPtr<ChFunction>(new ChFunction_Ramp(0, 1)));

  // Connect the second shaft to ground through a cylindrical joint
  // --------------------------------------------------------------

  // Use a cylindrical joint so that we do not have redundant constraints
  // (note that, technically Chrono could deal with a revolute joint here).
  // the joint is located at the origin of the second shaft.

  ChSharedPtr<ChLinkLockCylindrical> cyljoint(new ChLinkLockCylindrical);
  system.AddLink(cyljoint);
  cyljoint->Initialize(ground, shaft_2, ChCoordsys<>(ChVector<>(0, -hl * sina, hl * cosa), rot));

  // Connect the two shafts through a universal joint
  // ------------------------------------------------

  // The joint is located at the global origin.  Its kinematic constraints will
  // enforce orthogonality of the associated cross.

  ChSharedPtr<ChLinkUniversal> ujoint(new ChLinkUniversal);
  system.AddLink(ujoint);
  ujoint->Initialize(shaft_1, shaft_2, ChFrame<>(ChVector<>(0, 0, 0), rot));

  // Create the Irrlicht application
  // -------------------------------

  ChIrrApp application(&system, L"ChBodyAuxRef demo", core::dimension2d<u32>(800, 600), false, true);
  application.AddTypicalLogo();
  application.AddTypicalSky();
  application.AddTypicalLights();
  application.AddTypicalCamera(core::vector3df(3, 1, -1.5));

  application.AssetBindAll();
  application.AssetUpdateAll();

  // Simulation loop
  application.SetTimestep(0.001);

  int frame = 0;

  while (application.GetDevice()->run())
  {
    application.BeginScene();
    application.DrawAll();
    application.DoStep();
    application.EndScene();
    frame++;

    if (frame % 20 == 0) {
      // Output the shaft angular velocities at the current time
      double omega_1 = shaft_1->GetWvel_loc().z;
      double omega_2 = shaft_2->GetWvel_loc().z;
      GetLog() << system.GetChTime() << "   " << omega_1 << "   " << omega_2 << "\n";
    }
  }

  return 0;
}
int main(int argc, char* argv[]) {
	DLL_CreateGlobals();

	ChSystem * system = new ChSystem();
	system->SetMaxiter(100);
	system->SetIterLCPmaxItersSpeed(100);
	system->SetTol(0);
	system->SetTolSpeeds(0);

	ChLcpSystemDescriptor *mdescriptor = new ChLcpSystemDescriptor();
	ChContactContainer *mcontactcontainer = new ChContactContainer();
	//ChCollisionSystemBulletGPU *mcollisionengine = new ChCollisionSystemBulletGPU();
	ChCollisionSystemBullet *mcollisionengine = new ChCollisionSystemBullet();
	system->ChangeLcpSystemDescriptor(mdescriptor);
	system->ChangeContactContainer(mcontactcontainer);
	system->ChangeCollisionSystem(mcollisionengine);
	system->SetIntegrationType(ChSystem::INT_ANITESCU);
	system->SetLcpSolverType(ChSystem::LCP_ITERATIVE_APGD);
	system->SetStep(timestep);
	system->Set_G_acc(ChVector<>(0, gravity, 0));

	ChSharedBodyPtr floor(new ChBody);

	ChSharedBodyPtr chassis(new ChBody);

	ChSharedBodyPtr axle_F(new ChBody);
	ChSharedBodyPtr axle_C(new ChBody);
	ChSharedBodyPtr axle_R(new ChBody);

	ChSharedBodyPtr leg_FR(new ChBody);
	ChSharedBodyPtr leg_FL(new ChBody);
	ChSharedBodyPtr leg_CR(new ChBody);
	ChSharedBodyPtr leg_CL(new ChBody);
	ChSharedBodyPtr leg_RR(new ChBody);
	ChSharedBodyPtr leg_RL(new ChBody);

	InitObject(floor, 1.0, ChVector<>(0, -3.5, 0), Quaternion(1, 0, 0, 0), 1, 1, 0, true, true, -20, -20);
	InitObject(chassis, 1, ChVector<>(0, 0, 0), Quaternion(1, 0, 0, 0), 1, 1, 0, true, false, 0, 1);
	InitObject(axle_F, 1, ChVector<>(0, 0, chassisL / 2), Q_from_AngZ(CH_C_PI / 2.0), 1, 1, 0, false, false, -2, -2);
	InitObject(axle_C, 1, ChVector<>(0, 0, 0), Q_from_AngZ(CH_C_PI / 2.0), 1, 1, 0, false, false, -2, -2);
	InitObject(axle_R, 1, ChVector<>(0, 0, -chassisL / 2), Q_from_AngZ(CH_C_PI / 2.0), 1, 1, 0, false, false, -2, -2);
	InitObject(leg_FR, 1, ChVector<>((axleL + legW) / 2.0, -legL / 2.0, chassisL / 2), Quaternion(1, 0, 0, 0), 1, 1, 0, true, false, 2, 2);
	InitObject(leg_FL, 1, ChVector<>(-(axleL + legW) / 2.0, legL / 2.0, chassisL / 2), Quaternion(1, 0, 0, 0), 1, 1, 0, true, false, 2, 2);
	InitObject(leg_CR, 1, ChVector<>(-(axleL + legW) / 2.0, -legL / 2.0, 0), Quaternion(1, 0, 0, 0), 1, 1, 0, true, false, 2, 2);
	InitObject(leg_CL, 1, ChVector<>((axleL + legW) / 2.0, legL / 2.0, 0), Quaternion(1, 0, 0, 0), 1, 1, 0, true, false, 2, 2);
	InitObject(leg_RR, 1, ChVector<>((axleL + legW) / 2.0, -legL / 2.0, -chassisL / 2), Quaternion(1, 0, 0, 0), 1, 1, 0, true, false, 2, 2);
	InitObject(leg_RL, 1, ChVector<>(-(axleL + legW) / 2.0, legL / 2.0, -chassisL / 2), Quaternion(1, 0, 0, 0), 1, 1, 0, true, false, 2, 2);

	AddCollisionGeometry(floor, BOX, ChVector<>(10, 1 / 2.0, 10), Vector(0, 0, 0), Quaternion(1, 0, 0, 0));
	AddCollisionGeometry(chassis, ELLIPSOID, ChVector<>(1, 1, 1), Vector(0, 0, 0), Quaternion(1, 0, 0, 0));
	AddCollisionGeometry(axle_F, ELLIPSOID, ChVector<>(0.5 / 2.0, axleL / 2.0, 0.5 / 2.0), Vector(0, 0, 0), Quaternion(1, 0, 0, 0));
	AddCollisionGeometry(axle_C, ELLIPSOID, ChVector<>(0.5 / 2.0, axleL / 2.0, 0.5 / 2.0), Vector(0, 0, 0), Quaternion(1, 0, 0, 0));
	AddCollisionGeometry(axle_R, ELLIPSOID, ChVector<>(0.5 / 2.0, axleL / 2.0, 0.5 / 2.0), Vector(0, 0, 0), Quaternion(1, 0, 0, 0));
	AddCollisionGeometry(leg_FR, ELLIPSOID, ChVector<>(legW / 2.0, legL / 2.0, 0.5 / 2.0), Vector(0, 0, 0), Quaternion(1, 0, 0, 0));
	AddCollisionGeometry(leg_FL, ELLIPSOID, ChVector<>(legW / 2.0, legL / 2.0, 0.5 / 2.0), Vector(0, 0, 0), Quaternion(1, 0, 0, 0));
	AddCollisionGeometry(leg_CR, ELLIPSOID, ChVector<>(legW / 2.0, legL / 2.0, 0.5 / 2.0), Vector(0, 0, 0), Quaternion(1, 0, 0, 0));
	AddCollisionGeometry(leg_CL, ELLIPSOID, ChVector<>(legW / 2.0, legL / 2.0, 0.5 / 2.0), Vector(0, 0, 0), Quaternion(1, 0, 0, 0));
	AddCollisionGeometry(leg_RR, ELLIPSOID, ChVector<>(legW / 2.0, legL / 2.0, 0.5 / 2.0), Vector(0, 0, 0), Quaternion(1, 0, 0, 0));
	AddCollisionGeometry(leg_RL, ELLIPSOID, ChVector<>(legW / 2.0, legL / 2.0, 0.5 / 2.0), Vector(0, 0, 0), Quaternion(1, 0, 0, 0));

	floor->SetInertiaXX(Vector(1,1,1));
	chassis->SetInertiaXX(Vector(1,1,1));
	axle_F->SetInertiaXX(Vector(1,1,1));
	axle_C->SetInertiaXX(Vector(1,1,1));
	axle_R->SetInertiaXX(Vector(1,1,1));
	leg_FR->SetInertiaXX(Vector(1,1,1));
	leg_FL->SetInertiaXX(Vector(1,1,1));
	leg_CR->SetInertiaXX(Vector(1,1,1));
	leg_CL->SetInertiaXX(Vector(1,1,1));
	leg_RR->SetInertiaXX(Vector(1,1,1));
	leg_RL->SetInertiaXX(Vector(1,1,1));

	FinalizeObject(floor, (ChSystem *) system);
	FinalizeObject(chassis, (ChSystem *) system);
	FinalizeObject(axle_F, (ChSystem *) system);
	FinalizeObject(axle_C, (ChSystem *) system);
	FinalizeObject(axle_R, (ChSystem *) system);
	FinalizeObject(leg_FR, (ChSystem *) system);
	FinalizeObject(leg_FL, (ChSystem *) system);
	FinalizeObject(leg_CR, (ChSystem *) system);
	FinalizeObject(leg_CL, (ChSystem *) system);
	FinalizeObject(leg_RR, (ChSystem *) system);
	FinalizeObject(leg_RL, (ChSystem *) system);

	ChSharedBodyPtr chassis_ptr = ChSharedBodyPtr(chassis);
	ChSharedBodyPtr axle_F_ptr = ChSharedBodyPtr(axle_F);
	ChSharedBodyPtr axle_C_ptr = ChSharedBodyPtr(axle_C);
	ChSharedBodyPtr axle_R_ptr = ChSharedBodyPtr(axle_R);
	ChSharedBodyPtr leg_FR_ptr = ChSharedBodyPtr(leg_FR);
	ChSharedBodyPtr leg_FL_ptr = ChSharedBodyPtr(leg_FL);
	ChSharedBodyPtr leg_CR_ptr = ChSharedBodyPtr(leg_CR);
	ChSharedBodyPtr leg_CL_ptr = ChSharedBodyPtr(leg_CL);
	ChSharedBodyPtr leg_RR_ptr = ChSharedBodyPtr(leg_RR);
	ChSharedBodyPtr leg_RL_ptr = ChSharedBodyPtr(leg_RL);

//	ChSharedPtr<ChLinkLockLock> axle_FR(new ChLinkLockLock);
//	axle_FR->Initialize(leg_FR_ptr, axle_F_ptr, ChCoordsys<>(VNULL));
//	system->AddLink(axle_FR);
////
//	ChSharedPtr<ChLinkLockLock> axle_FL(new ChLinkLockLock);
//	axle_FL->Initialize(leg_FL_ptr, axle_F_ptr, ChCoordsys<>(VNULL));
//	system->AddLink(axle_FL);
//
//	ChSharedPtr<ChLinkLockLock> axle_CR(new ChLinkLockLock);
//	axle_CR->Initialize(leg_CR_ptr, axle_C_ptr, ChCoordsys<>(VNULL));
//	system->AddLink(axle_CR);
//
//	ChSharedPtr<ChLinkLockLock> axle_CL(new ChLinkLockLock);
//	axle_CL->Initialize(leg_CL_ptr, axle_C_ptr, ChCoordsys<>(VNULL));
//	system->AddLink(axle_CL);
//
//	ChSharedPtr<ChLinkLockLock> axle_RR(new ChLinkLockLock);
//	axle_RR->Initialize(leg_RR_ptr, axle_R_ptr, ChCoordsys<>(VNULL));
//	system->AddLink(axle_RR);
//
//	ChSharedPtr<ChLinkLockLock> axle_RL(new ChLinkLockLock);
//	axle_RL->Initialize(leg_RL_ptr, axle_R_ptr, ChCoordsys<>(VNULL));
//	system->AddLink(axle_RL);

	// Create engine between axles and chassis
	GetLog() << "Creating Motors\n";

//	ChSharedPtr<ChLinkEngine> eng_F(new ChLinkEngine);
//	eng_F->Initialize(axle_F_ptr, chassis_ptr, ChCoordsys<>(ChVector<>(0, 0, chassisL / 2), Q_from_AngY(CH_C_PI / 2)));
//	eng_F->Set_shaft_mode(ChLinkEngine::ENG_SHAFT_LOCK); // also works as revolute support
//	eng_F->Set_eng_mode(ChLinkEngine::ENG_MODE_SPEED);
//	if (ChFunction_Const* mfun = dynamic_cast<ChFunction_Const*>(eng_F->Get_spe_funct()))
//		mfun->Set_yconst(1); // rad/s  angular speed
//	system->AddLink(eng_F);

	ChSharedPtr<ChLinkEngine> eng_C(new ChLinkEngine);
	eng_C->Initialize(axle_C_ptr, chassis_ptr, ChCoordsys<>(ChVector<>(0, 0, 0), Q_from_AngY(CH_C_PI / 2)));
	eng_C->Set_shaft_mode(ChLinkEngine::ENG_SHAFT_LOCK); // also works as revolute support
	eng_C->Set_eng_mode(ChLinkEngine::ENG_MODE_SPEED);
	if (ChFunction_Const* mfun = dynamic_cast<ChFunction_Const*>(eng_C->Get_spe_funct()))
		mfun->Set_yconst(1); // rad/s  angular speed
	system->AddLink(eng_C);

//	ChSharedPtr<ChLinkEngine> eng_R(new ChLinkEngine);
//	eng_R->Initialize(axle_R_ptr, chassis_ptr, ChCoordsys<>(ChVector<>(0, 0, -chassisL / 2), Q_from_AngY(CH_C_PI / 2)));
//	eng_R->Set_shaft_mode(ChLinkEngine::ENG_SHAFT_LOCK); // also works as revolute support
//	eng_R->Set_eng_mode(ChLinkEngine::ENG_MODE_SPEED);
//	if (ChFunction_Const* mfun = dynamic_cast<ChFunction_Const*>(eng_R->Get_spe_funct()))
//		mfun->Set_yconst(1); // rad/s  angular speed
//	system->AddLink(eng_R);

	system->DoStepDynamics(timestep);
	system->DoStepDynamics(timestep);

	exit(0);

	ChOpenGLManager * window_manager = new ChOpenGLManager();
	ChOpenGL openGLView(window_manager, system, 800, 600, 0, 0, "Test_Solvers");
	openGLView.render_camera->camera_position = glm::vec3(0, -5, -10);
	openGLView.render_camera->camera_look_at = glm::vec3(0, -5, 0);
	openGLView.render_camera->camera_scale = .5;
	openGLView.SetCustomCallback(RunTimeStep);
	openGLView.StartSpinning(window_manager);
	window_manager->CallGlutMainLoop();

	DLL_DeleteGlobals();

	return 0;
}