void createTerrain(ChSystem & sys, double dia, double W, double H, double L)
{
	int x = W/dia-3;
	int y = H/dia;
	int z = L/dia-3;
	double mass = 0.05 * 4/3*CH_C_PI*pow(particleDiameter/2.0,3.0);// density * volume
	double inertia = 0.4*mass*particleDiameter*particleDiameter/4.0;

	ChSharedBodyPtr particle;
	for (int i=3; i<x; i++)
	{
		for (int j=0; j<y; j++)
		{
			for (int k=3; k<z; k++)
			{
				particle=ChSharedBodyPtr(new ChBody);
				particle->SetPos(ChVector<>(-W/2.0,-boxDrop,-(chassisL/2.0)-2.0) + ChVector<>(i+ChRandom()-0.5,j,k+ChRandom()-0.5) * dia);
				particle->SetMass(mass); 
				particle->SetInertiaXX(ChVector<>(inertia,inertia,inertia));
				particle->GetCollisionModel()->AddSphere(dia/2.0);
				particle->SetCollide(true);
				particle->SetPos_dt(ChVector<>(ChRandom()-0.5,-ChRandom(),ChRandom()-0.5)*10 );
				sys.AddBody(particle);
			}
		}
	}
}
Esempio n. 2
0
		// Delete the tank object, deleting also all bodies corresponding to
		// the various parts and removing them from the physical system.  Also
		// removes constraints from the system.
	~MySimpleTank()
			{
				ChSystem* mysystem = truss->GetBody()->GetSystem(); // trick to get the system here				
					// When a ChBodySceneNode is removed via ->remove() from Irrlicht 3D scene manager,
					// it is also automatically removed from the ChSystem (the ChSystem::RemoveBody() is
					// automatically called at Irrlicht node deletion - see ChBodySceneNode.h ).

					// For links, just remove them from the ChSystem using ChSystem::RemoveLink()
				mysystem->RemoveLink(link_revoluteRF);	
				mysystem->RemoveLink(link_revoluteLF);				
				mysystem->RemoveLink(link_revoluteRB);				
				mysystem->RemoveLink(link_revoluteLB);				

				truss->remove();
				wheelRF->remove();
				wheelLF->remove();
				wheelRB->remove();
				wheelLB->remove();
			}
Esempio n. 3
0
void ChEmitterAsset::Update(ChPhysicsItem* updater, const ChCoordsys<>& coords) {

    ChSystem* msys = updater->GetSystem();
    
    if (!msys) 
        return;

    double mt = msys->GetChTime();

    if (mt < this->last_t)
        last_t = mt;
    
    double dt = mt - last_t;
    last_t = mt;

    if (dt == 0)
        return;
    //***TODO*** a better way to deduce dt, ex. by using flags in Update(),
    // to know if Update really follows a t+dt update, etc. 

    // Create the particles!

    ChFrameMoving<> mframe(coords);

    // special case: the owner is a body? so use also speed info
    if(ChBody* mbody = dynamic_cast<ChBody*>(updater)) {

        ChFrameMoving<> bodyframe = mbody->GetFrame_REF_to_abs();
        ChFrameMoving<> relcoords;
        bodyframe.TransformParentToLocal(mframe, relcoords);
        relcoords.SetCoord_dt(CSYSNULL);
        relcoords.SetCoord_dtdt(CSYSNULL);
        bodyframe.TransformLocalToParent(relcoords, mframe);
    }

    this->memitter.EmitParticles(*msys, dt, mframe);
}
Esempio n. 4
0
		// Delete the car object, deleting also all bodies corresponding to
		// the various parts and removing them from the physical system.  Also
		// removes constraints from the system.
	~MySimpleForklift()
			{
				ChSystem* mysystem = truss->GetBody()->GetSystem(); // trick to get the system here				
					// When a ChBodySceneNode is removed via ->remove() from Irrlicht 3D scene manager,
					// it is also automatically removed from the ChSystem (the ChSystem::RemoveBody() is
					// automatically called at Irrlicht node deletion - see ChBodySceneNode.h ).

					// For links, just remove them from the ChSystem using ChSystem::RemoveLink()
				mysystem->RemoveLink(link_revoluteRF);	
				mysystem->RemoveLink(link_revoluteLF);				
				mysystem->RemoveLink(link_steer_engineB);				
				mysystem->RemoveLink(link_engineB);
				mysystem->RemoveLink(link_engineArm);
				mysystem->RemoveLink(link_prismaticFork);
				mysystem->RemoveLink(link_actuatorFork);

				truss->remove();
				wheelRF->remove();
				wheelLF->remove();
				wheelB->remove();
				spindleB->remove();
				arm->remove();
				fork->remove();
			}
Esempio n. 5
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;
}
Esempio n. 6
0
void ChPythonEngine::ImportSolidWorksSystem(const char* solidworks_py_file, ChSystem& msystem) throw(ChException)
{
	std::ostringstream sstream;

	//sstream << "from " << std::string(solidworks_py_file) << " import exported_items\n";

	sstream << "import builtins  \n";
	sstream << "import imp  \n";
	sstream << "import os  \n";
	sstream << "mdirname, mmodulename= os.path.split('" << std::string(solidworks_py_file) << "')  \n";
	sstream << "builtins.exported_system_relpath = mdirname + '/'  \n";
	sstream << "fp, pathname, description = imp.find_module(mmodulename,[builtins.exported_system_relpath])  \n";
	sstream << "try:  \n";
	sstream << "    imported_mod = imp.load_module('imported_mod', fp, pathname, description)  \n";
	sstream << "finally:  \n";
	sstream << "    if fp:  \n";
	sstream << "        fp.close()  \n";
	sstream << "exported_items = imported_mod.exported_items  \n";

	this->Run(sstream.str().c_str());
	
	PyObject * module = PyImport_AddModule("__main__"); // borrowed reference
	if (!module)
		throw ChException("ERROR. No Python __main__ module?"); 

	PyObject * dictionary = PyModule_GetDict(module);   // borrowed reference
	if (!dictionary) 
		throw ChException("ERROR. No Python dictionary?");                                 

	PyObject * result = PyDict_GetItemString(dictionary, "exported_items");   // borrowed reference
	if (!result) 
		throw ChException("ERROR. Missing Python object 'exported_items' in SolidWorks file");

	if (PyList_Check(result))
	{
		int nitems = PyList_Size(result);
		//GetLog() << "N.of list items: " << nitems << "\n";
		for (int i = 0; i< nitems; i++)
		{
			PyObject* mobj = PyList_GetItem(result,i);
			if (mobj)
			{	
				// GetLog() << "   Python type: " << mobj->ob_type->tp_name << "\n";
				
				SwigPyObject * mswigobj  = SWIG_Python_GetSwigThis(mobj);
				if (mswigobj) 
				{
					void* objptr = mswigobj->ptr;
					ChSharedPtr<ChPhysicsItem>* pt_to_shp = (ChSharedPtr<ChPhysicsItem>*)objptr;	
				
						/// Add the ChPhysicsItem to the ChSystem
					msystem.Add( (*pt_to_shp) );
				} 
				else
				{
					throw ChException("ERROR. Only shared pointers to ChPhysicsItem subclasses can be inside exported_items.");
				}
			}
		}

		msystem.Setup();
		msystem.Update();

	}
	else
	{
		throw ChException("ERROR. exported_items python object is not a list.");
	}

	
}
Esempio n. 7
0
int main(int argc, char* argv[]) {
    // Create a ChronoENGINE physical system
    ChSystem mphysicalSystem;

    // Create the Irrlicht visualization (open the Irrlicht device,
    // bind a simple user interface, etc. etc.)
    ChIrrApp application(&mphysicalSystem, L"Meshless deformable material", core::dimension2d<u32>(800, 600), false);

    // Easy shortcuts to add camera, lights, logo and sky in Irrlicht scene:
    ChIrrWizard::add_typical_Logo(application.GetDevice());
    ChIrrWizard::add_typical_Sky(application.GetDevice());
    ChIrrWizard::add_typical_Lights(application.GetDevice());
    ChIrrWizard::add_typical_Camera(application.GetDevice(), core::vector3df(0, 3, -3));

    // CREATE A FLOOR

    ChSharedPtr<ChBodyEasyBox> mfloorBody( new ChBodyEasyBox(20,1,20,1000,true,true));
    my_system.Add(mfloorBody);
    mfloorBody->SetBodyFixed(true);
    mfloorBody->SetPos(ChVector<>(0, -5, 0));

    ChSharedPtr<ChTexture> mtexture( new ChTexture(GetChronoDataFile("concrete.jpg").c_str()));
    mfloorBody->AddAsset(mtexture);

   
    // CREATE THE ELASTOPLASTIC MESHLESS CONTINUUM

    // Create elastoplastic matter
    ChSharedPtr<ChMatterMeshless> mymatter(new ChMatterMeshless);

    // Use the FillBox easy way to create the set of nodes in the meshless matter
    mymatter->FillBox(ChVector<>(4, 2, 4),                          // size of box
                      4.0 / 10.0,                                   // resolution step
                      1000,                                         // initial density
                      ChCoordsys<>(ChVector<>(0, -3.9, 0), QUNIT),  // position & rotation of box
                      true,                                         // do a centered cubic lattice initial arrangement
                      2.1);                                         // set the kernel radius (as multiples of step)

    GetLog() << "Added " << mymatter->GetNnodes() << " nodes \n";

    // Set some material properties of the meshless matter

    ChSharedPtr<ChContinuumDruckerPrager> mmaterial(new ChContinuumDruckerPrager);
    mymatter->ReplaceMaterial(mmaterial);
    mmaterial->Set_v(0.35);
    mmaterial->Set_E(30000.0);
    mmaterial->Set_elastic_yeld(0);
    mmaterial->Set_alpha(30 * CH_C_DEG_TO_RAD);
    // mmaterial->Set_from_MohrCoulomb(30 * CH_C_DEG_TO_RAD, 1000);
    mmaterial->Set_dilatancy(30 * CH_C_DEG_TO_RAD);
    mmaterial->Set_flow_rate(50000000.0);
    mmaterial->Set_hardening_limit(mmaterial->Get_elastic_yeld());
    mmaterial->Set_hardening_speed(100000000);

    /*
        ChSharedPtr<ChContinuumPlasticVonMises> mmaterial(new ChContinuumPlasticVonMises);
        mymatter->ReplaceMaterial(mmaterial);
        mmaterial->Set_v(0.38);
        mmaterial->Set_E(60000.0);
        mmaterial->Set_elastic_yeld(0.06);
        mmaterial->Set_flow_rate(300);
    */

    mymatter->SetViscosity(5000);

    // Add the matter to the physical system
    mymatter->SetCollide(true);
    mphysicalSystem.Add(mymatter);

    // Join some nodes of meshless matter to a ChBody
    /*
    ChSharedPtr<ChIndexedNodes> mnodes = mymatter;
    for (int ij = 0; ij < 120; ij++)
    {
        ChSharedPtr<ChLinkPointFrame> myjointnodebody(new ChLinkPointFrame);
        myjointnodebody->Initialize(mnodes,
                                    ij,
                                    mfloorBody->GetBody());
        mphysicalSystem.Add(myjointnodebody);
    }
    */

    // IMPORTANT!
    // This takes care of the interaction between the particles of the meshless material
    ChSharedPtr<ChProximityContainerMeshless> my_sph_proximity(new ChProximityContainerMeshless);
    mphysicalSystem.Add(my_sph_proximity);


    // CREATE A SPHERE PRESSING THE MATERIAL:

    ChSharedPtr<ChBodyEasySphere> msphere( new ChBodyEasySphere(2, 7000, true,true));
    my_system.Add(msphere);
    msphere->SetPos(ChVector<>(0, -0.5, 0));

    

    // Use this function for adding a ChIrrNodeAsset to all items
    // Otherwise use application.AssetBind(myitem); on a per-item basis.
    application.AssetBindAll();

    // Use this function for 'converting' assets into Irrlicht meshes
    application.AssetUpdateAll();


    // Modify some setting of the physical system for the simulation, if you want

    mphysicalSystem.SetMaxItersSolverSpeed(25);  // lower the LCP iters, no needed here

    //
    // THE SOFT-REAL-TIME CYCLE
    //

    static int printed_prox = 0;
    application.SetStepManage(true);
    application.SetTimestep(0.002);

    while (application.GetDevice()->run()) {
        application.BeginScene(true, true, SColor(255, 140, 161, 192));

        application.DrawAll();

        ChSystem::IteratorOtherPhysicsItems myiter = mphysicalSystem.IterBeginOtherPhysicsItems();

        while (myiter != mphysicalSystem.IterEndOtherPhysicsItems()) {
            if ((*myiter).IsType<ChMatterMeshless>()) {
                ChSharedPtr<ChMatterMeshless> mymatter((*myiter).DynamicCastTo<ChMatterMeshless>());

                for (unsigned int ip = 0; ip < mymatter->GetNnodes(); ip++) {
                    ChSharedPtr<ChNodeMeshless> mnode(mymatter->GetNode(ip).DynamicCastTo<ChNodeMeshless>());
                    ChVector<> mv = mnode->GetPos();
                    float rad = (float)mnode->GetKernelRadius();
                    core::vector3df mpos((irr::f32)mv.x, (irr::f32)mv.y, (irr::f32)mv.z);
                    core::position2d<s32> spos =
                        application.GetSceneManager()->getSceneCollisionManager()->getScreenCoordinatesFrom3DPosition(
                            mpos);
                    application.GetVideoDriver()->draw2DRectangle(
                        video::SColor(100, 200, 200, 230),
                        core::rect<s32>(spos.X - 2, spos.Y - 2, spos.X + 2, spos.Y + 2));
                    /*
                    application.GetVideoDriver()->setTransform(video::ETS_WORLD, core::matrix4());
                    application.GetVideoDriver()->draw3DBox( core::aabbox3d<f32>(
                                    (irr::f32)mv.x-rad ,(irr::f32)mv.y-rad , (irr::f32)mv.z-rad    ,
                                    (irr::f32)mv.x+rad ,(irr::f32)mv.y+rad , (irr::f32)mv.z+rad )   ,
                                    video::SColor(300,200,200,230) );
                    */

                    /*
                    double strain_scale =10;
                    ChIrrTools::drawSegment(application.GetVideoDriver(), mnode->GetPos(),
                    mnode->GetPos()+(VECT_X*mnode->p_strain.XX()* strain_scale), video::SColor(255,255,0,0),false);
                    ChIrrTools::drawSegment(application.GetVideoDriver(), mnode->GetPos(),
                    mnode->GetPos()+(VECT_Y*mnode->p_strain.YY()* strain_scale), video::SColor(255,0,255,0),false);
                    ChIrrTools::drawSegment(application.GetVideoDriver(), mnode->GetPos(),
                    mnode->GetPos()+(VECT_Z*mnode->p_strain.ZZ()* strain_scale), video::SColor(255,0,0,255),false);
                    */

                    /*
                    double stress_scale =0.008;
                    ChIrrTools::drawSegment(application.GetVideoDriver(), mnode->GetPos(),
                    mnode->GetPos()+(VECT_X*mnode->e_stress.XX()* stress_scale), video::SColor(100,255,0,0),false);
                    ChIrrTools::drawSegment(application.GetVideoDriver(), mnode->GetPos(),
                    mnode->GetPos()+(VECT_Y*mnode->e_stress.YY()* stress_scale), video::SColor(100,0,255,0),false);
                    ChIrrTools::drawSegment(application.GetVideoDriver(), mnode->GetPos(),
                    mnode->GetPos()+(VECT_Z*mnode->e_stress.ZZ()* stress_scale), video::SColor(100,0,0,255),false);
                    */

                    double stress_scale = 0.00001;
                    ChIrrTools::drawSegment(
                        application.GetVideoDriver(), mnode->GetPos(),
                        mnode->GetPos() + (VECT_X * mnode->e_stress.GetInvariant_I1() * stress_scale),
                        video::SColor(100, 255, 0, 0), false);

                    // GetLog() << "Mass i="<< ip << "   m=" << mnode->GetMass() << "\n";
                    // ChIrrTools::drawSegment(application.GetVideoDriver(), mnode->GetPos(),
                    // mnode->GetPos()+(mnode->UserForce * 0.1), video::SColor(100,0,0,0),false);
                }
            }
            ++myiter;
        }

        application.DoStep();

        application.EndScene();
    }

    return 0;
}
Esempio n. 8
0
		// Delete the car object, deleting also all bodies corresponding to
		// the various parts and removing them from the physical system.  Also
		// removes constraints from the system.
MySimpleCar::~MySimpleCar()
{
	ChSystem* mysystem = spindleRF->GetBody()->GetSystem(); // trick to get the system here	

		// When a ChBodySceneNode is removed via ->remove() from Irrlicht 3D scene manager,
		// it is also automatically removed from the ChSystem (the ChSystem::RemoveBody() is
		// automatically called at Irrlicht node deletion - see ChBodySceneNode.h ).

		// For links, just remove them from the ChSystem using ChSystem::RemoveLink()
	mysystem->RemoveLink(link_revoluteRF);
	mysystem->RemoveLink(link_brakeRF);
	mysystem->RemoveLink(link_distRFU1);
	mysystem->RemoveLink(link_distRFU2);
	mysystem->RemoveLink(link_distRFL1);
	mysystem->RemoveLink(link_distRFL2);
	mysystem->RemoveLink(link_springRF);
	mysystem->RemoveLink(link_distRSTEER);

	mysystem->RemoveLink(link_revoluteLF);
	mysystem->RemoveLink(link_brakeLF);
	mysystem->RemoveLink(link_distLFU1);
	mysystem->RemoveLink(link_distLFU2);
	mysystem->RemoveLink(link_distLFL1);
	mysystem->RemoveLink(link_distLFL2);
	mysystem->RemoveLink(link_springLF);
	mysystem->RemoveLink(link_distLSTEER);

	mysystem->RemoveLink(link_revoluteRB);
	mysystem->RemoveLink(link_brakeRB);
	mysystem->RemoveLink(link_distRBU1);
	mysystem->RemoveLink(link_distRBU2);
	mysystem->RemoveLink(link_distRBL1);
	mysystem->RemoveLink(link_distRBL2);
	mysystem->RemoveLink(link_springRB);
	mysystem->RemoveLink(link_distRBlat);
	mysystem->RemoveLink(link_engineR);

	mysystem->RemoveLink(link_revoluteLB);
	mysystem->RemoveLink(link_brakeLB);
	mysystem->RemoveLink(link_distLBU1);
	mysystem->RemoveLink(link_distLBU2);
	mysystem->RemoveLink(link_distLBL1);
	mysystem->RemoveLink(link_distLBL2);
	mysystem->RemoveLink(link_springLB);
	mysystem->RemoveLink(link_distLBlat);
	mysystem->RemoveLink(link_engineL);

	truss->remove();
	spindleRF->remove();
	wheelRF->remove();
	spindleLF->remove();
	wheelLF->remove();
	spindleRB->remove();
	wheelRB->remove();
	spindleLB->remove();
	wheelLB->remove();

	sound_engine->drop(); 
}
Esempio n. 9
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;

}
Esempio n. 10
0
int main(int argc, char* argv[])
{
	// Create a ChronoENGINE physical system
	ChSystem mphysicalSystem;

	// Create the Irrlicht visualization (open the Irrlicht device, 
	// bind a simple user interface, etc. etc.)
	ChIrrApp application(&mphysicalSystem, L"Critical cases for solver convergence",core::dimension2d<u32>(800,600),false,true);


	// Easy shortcuts to add camera, lights, logo and sky in Irrlicht scene:
	ChIrrWizard::add_typical_Logo(application.GetDevice());
	ChIrrWizard::add_typical_Sky(application.GetDevice());
	ChIrrWizard::add_typical_Lights(application.GetDevice());
	ChIrrWizard::add_typical_Camera(application.GetDevice(), core::vector3df(0,1.5,-3));

 
	// Create all the rigid bodies.

	create_items(application);
 

	class MyContactCallback : public ChSystem::ChCustomCollisionPointCallback
	{
		public:	virtual void ContactCallback(
								const collision::ChCollisionInfo& mcontactinfo, ///< get info about contact (cannot change it)				
								ChMaterialCouple&  material )			  		///< you can modify this!	
		{
			// Set compliance (normal and tangential at once)
			material.compliance  = STATIC_COMPLIANCE; 
			material.complianceT = material.compliance ;
			material.dampingf = 0.2f;
		};
		ChSystem* msystem;
	};

	MyContactCallback mycontact_callback;  // create the callback object
	mycontact_callback.msystem = &mphysicalSystem; // will be used by callback
	// Tell the system to use the callback above, per each created contact!
	mphysicalSystem.SetCustomCollisionPointCallback(&mycontact_callback);
 

	// Use this function for adding a ChIrrNodeAsset to all already created items (ex. a floor, a wall, etc.)
	// Otherwise use application.AssetBind(myitem); on a per-item basis.
	application.AssetBindAll();
	application.AssetUpdateAll();

	
	// Modify some setting of the physical system for the simulation, if you want

	mphysicalSystem.SetLcpSolverType(ChSystem::LCP_ITERATIVE_BARZILAIBORWEIN);
	//mphysicalSystem.SetLcpSolverType(ChSystem::LCP_ITERATIVE_SOR);
	mphysicalSystem.SetIterLCPmaxItersSpeed(60);
	mphysicalSystem.SetIterLCPmaxItersStab(5);
	mphysicalSystem.SetParallelThreadNumber(1);

	//mphysicalSystem.SetUseSleeping(true);

	application.SetStepManage(true);
	application.SetTimestep(0.01);
	application.SetPaused(true);

	// 
	// THE SOFT-REAL-TIME CYCLE
	//

	while(application.GetDevice()->run()) 
	{
		application.GetVideoDriver()->beginScene(true, true, SColor(255,140,161,192));

		application.DrawAll();
		
		align_spheres(application); // just to simplify test, on y axis only

		application.DoStep();
		
		application.GetVideoDriver()->endScene();  
	}
	

	return 0;
}
Esempio n. 11
0
void create_wall_bodies(ChSystem& mphysicalSystem)
{
	// Create a material that will be shared between bricks
	ChSharedPtr<ChMaterialSurface> mmaterial(new ChMaterialSurface);
	mmaterial->SetFriction(0.4f);
	mmaterial->SetCompliance (0.0000005f);
	mmaterial->SetComplianceT(0.0000005f);
	mmaterial->SetDampingF(0.2f);
		
	// Create bricks
	for (int ai = 0; ai < 1; ai++)  // N. of walls
	{ 
		for (int bi = 0; bi < 10; bi++)  // N. of vert. bricks
		{ 
			for (int ui = 0; ui < 15; ui++)  // N. of hor. bricks
			{ 
				ChSharedPtr<ChBodyEasyBox> mrigidBody(new ChBodyEasyBox(
											3.96, 2, 4, // x,y,z size
											 100,		// density
											true,		// collide enable?
											true));		// visualization?
				mrigidBody->SetPos(ChVector<>(-8+ui*4.0+2*(bi%2),  1.0+bi*2.0, ai*9));
				mrigidBody->SetMaterialSurface(mmaterial); // use shared surface properties
				
				mphysicalSystem.Add(mrigidBody);
				
				// optional, attach a texture for better visualization
				ChSharedPtr<ChTexture> mtexture(new ChTexture());
				mtexture->SetTextureFilename("../data/cubetexture_borders.png");
				mrigidBody->AddAsset(mtexture);
			}
		}
	}

	// Create the floor using
	// fixed rigid body of 'box' type:

	ChSharedPtr<ChBodyEasyBox> mrigidFloor(new ChBodyEasyBox(
											250, 4, 250, // x,y,z size
											1000,		// density
											true,		// collide enable?
											true));		// visualization?
	mrigidFloor->SetPos(ChVector<>(0,-2,0));
	mrigidFloor->SetMaterialSurface(mmaterial);
	mrigidFloor->SetBodyFixed(true);
	
	mphysicalSystem.Add(mrigidFloor);


	
	// Create a ball that will collide with wall
	ChSharedPtr<ChBodyEasySphere> mrigidBall(new ChBodyEasySphere(
											4,			// radius
											8000,		// density
											true,		// collide enable?
											true));		// visualization?
	mrigidBall->SetPos(ChVector<>(0,-2,0));
	mrigidBall->SetMaterialSurface(mmaterial);
	mrigidBall->SetPos(ChVector<>(0, 3, -8));
	mrigidBall->SetPos_dt(ChVector<>(0,0,16)); // set initial speed 
	mrigidBall->GetMaterialSurface()->SetFriction(0.4f); // use own (not shared) matrial properties
	mrigidBall->GetMaterialSurface()->SetCompliance(0.0);
	mrigidBall->GetMaterialSurface()->SetComplianceT(0.0);
	mrigidBall->GetMaterialSurface()->SetDampingF(0.2f);

	mphysicalSystem.Add(mrigidBall);

	// optional, attach a texture for better visualization
	ChSharedPtr<ChTexture> mtextureball(new ChTexture());
	mtextureball->SetTextureFilename("../data/bluwhite.png");
	mrigidBall->AddAsset(mtextureball);


}
Esempio n. 12
0
int main(int argc, char* argv[])
{ 

	// In CHRONO engine, The DLL_CreateGlobals() - DLL_DeleteGlobals(); pair is needed if
	// global functions are needed.
	DLL_CreateGlobals();

	// Create a ChronoENGINE physical system
	ChSystem mphysicalSystem; 

	// Create the Irrlicht visualization (open the Irrlicht device, 
	// bind a simple user interface, etc. etc.)
	ChIrrApp application(&mphysicalSystem, L"Bricks test",core::dimension2d<u32>(800,600),false, true); 

 
	// Easy shortcuts to add camera, lights, logo and sky in Irrlicht scene:
	ChIrrWizard::add_typical_Logo  (application.GetDevice());
	ChIrrWizard::add_typical_Sky   (application.GetDevice());
	ChIrrWizard::add_typical_Lights(application.GetDevice(), core::vector3df(70.f, 120.f, -90.f), core::vector3df(30.f, 80.f, 60.f), 290,  190);
	ChIrrWizard::add_typical_Camera(application.GetDevice(), core::vector3df(-15,14,-30), core::vector3df(0,5,0)); 

	// 
	// HERE YOU POPULATE THE MECHANICAL SYSTEM OF CHRONO... 
	// 

 
	// Create all the rigid bodies.
    create_wall_bodies (mphysicalSystem);
	//create_jengatower_bodies (mphysicalSystem);


	// Use this function for adding a ChIrrNodeAsset to all items
	// If you need a finer control on which item really needs a visualization proxy in 
	// Irrlicht, just use application.AssetBind(myitem); on a per-item basis.
	application.AssetBindAll();

	// Use this function for 'converting' into Irrlicht meshes the assets 
	// into Irrlicht-visualizable meshes
	application.AssetUpdateAll();


  
	// Prepare the physical system for the simulation 

	mphysicalSystem.SetLcpSolverType(ChSystem::LCP_ITERATIVE_SOR_MULTITHREAD);

	mphysicalSystem.SetUseSleeping(false);

	mphysicalSystem.SetMaxPenetrationRecoverySpeed(1.6); // used by Anitescu stepper only
	mphysicalSystem.SetIterLCPmaxItersSpeed(40);
	mphysicalSystem.SetIterLCPmaxItersStab(20); // unuseful for Anitescu, only Tasora uses this
	mphysicalSystem.SetIterLCPwarmStarting(true);
	mphysicalSystem.SetParallelThreadNumber(4);

	//
	// THE SOFT-REAL-TIME CYCLE
	//
 
	application.SetStepManage(true);
	application.SetTimestep(0.02);

	while(application.GetDevice()->run())
	{
		application.GetVideoDriver()->beginScene(true, true, SColor(255,140,161,192));

		ChIrrTools::drawGrid(application.GetVideoDriver(), 5,5, 20,20, 
			ChCoordsys<>(ChVector<>(0,0.2,0),Q_from_AngAxis(CH_C_PI/2,VECT_X)), video::SColor(50,90,90,150),true);

		application.DrawAll();

		application.DoStep();
 
		application.GetVideoDriver()->endScene();  
	}
	 

 	// Remember this at the end of the program, if you started
	// with DLL_CreateGlobals();
	DLL_DeleteGlobals();

	return 0;
}
Esempio n. 13
0
void create_jengatower_bodies(ChSystem& mphysicalSystem)
{
	// Create a material that will be shared between bricks
	ChSharedPtr<ChMaterialSurface> mmaterial(new ChMaterialSurface);
	mmaterial->SetFriction(0.4f);
	mmaterial->SetCompliance (0.0000005f);
	mmaterial->SetComplianceT(0.0000005f);
	mmaterial->SetDampingF(0.2f);

	// Create bricks
	for (int bi = 0; bi < 12; bi+=2) 
	{ 
		ChSharedPtr<ChBodyEasyBox> mrigidBody1(new ChBodyEasyBox(
											2, 2, 14,   // x,y,z size
											 100,		// density
											true,		// collide enable?
											true));		// visualization?
		mrigidBody1->SetPos( ChVector<>(-5, 1.0+bi*2.0,  0) );
		mrigidBody1->SetMaterialSurface(mmaterial); // use shared surface properties	
		mphysicalSystem.Add(mrigidBody1);


		ChSharedPtr<ChBodyEasyBox> mrigidBody2(new ChBodyEasyBox(
											2, 2, 14,   // x,y,z size
											 100,		// density
											true,		// collide enable?
											true));		// visualization?
		mrigidBody2->SetPos( ChVector<>( 5, 1.0+bi*2.0,  0) );
		mrigidBody2->SetMaterialSurface(mmaterial); // use shared surface properties	
		mphysicalSystem.Add(mrigidBody2);


		ChSharedPtr<ChBodyEasyBox> mrigidBody3(new ChBodyEasyBox(
											14, 2, 2,   // x,y,z size
											 100,		// density
											true,		// collide enable?
											true));		// visualization?
		mrigidBody3->SetPos( ChVector<>(0, 3.0+bi*2.0,  5) );
		mrigidBody3->SetMaterialSurface(mmaterial); // use shared surface properties	
		mphysicalSystem.Add(mrigidBody3);


		ChSharedPtr<ChBodyEasyBox> mrigidBody4(new ChBodyEasyBox(
											14, 2, 2,   // x,y,z size
											 100,		// density
											true,		// collide enable?
											true));		// visualization?
		mrigidBody4->SetPos( ChVector<>(0, 3.0+bi*2.0,  -5) );
		mrigidBody4->SetMaterialSurface(mmaterial); // use shared surface properties	
		mphysicalSystem.Add(mrigidBody4);
	}

	// Create the floor using
	// fixed rigid body of 'box' type:

	ChSharedPtr<ChBodyEasyBox> mrigidFloor(new ChBodyEasyBox(
											250, 4, 250, // x,y,z size
											1000,		// density
											true,		// collide enable?
											true));		// visualization?
	mrigidFloor->SetPos(ChVector<>(0,-2,0));
	mrigidFloor->SetMaterialSurface(mmaterial);
	mrigidFloor->SetBodyFixed(true);
	
	mphysicalSystem.Add(mrigidFloor);


	
	// Create a ball that will collide with tower
	ChSharedPtr<ChBodyEasySphere> mrigidBall(new ChBodyEasySphere(
											4,			// radius
											1000,		// density
											true,		// collide enable?
											true));		// visualization?
	mrigidBall->SetMaterialSurface(mmaterial);
	mrigidBall->SetPos(ChVector<>(0, 3, -8));
	mrigidBall->SetPos_dt(ChVector<>(0,0,2)); // set initial speed 
	mrigidBall->GetMaterialSurface()->SetFriction(0.4f); // use own (not shared) matrial properties
	mrigidBall->GetMaterialSurface()->SetCompliance(0.0);
	mrigidBall->GetMaterialSurface()->SetComplianceT(0.0);
	mrigidBall->GetMaterialSurface()->SetDampingF(0.2f);

	mphysicalSystem.Add(mrigidBall);

	// optional, attach a texture for better visualization
	ChSharedPtr<ChTexture> mtextureball(new ChTexture());
	mtextureball->SetTextureFilename("../data/bluwhite.png");
	mrigidBall->AddAsset(mtextureball);


}
Esempio n. 14
0
    // Delete the car object, deleting also all bodies corresponding to
    // the various parts and removing them from the physical system.  Also
    // removes constraints from the system.
    ~MySimpleForklift() {
        ChSystem* mysystem = truss->GetSystem();  // trick to get the system here

        mysystem->Remove(link_revoluteRF);
        mysystem->Remove(link_revoluteLF);
        mysystem->Remove(link_steer_engineB);
        mysystem->Remove(link_engineB);
        mysystem->Remove(link_engineArm);
        mysystem->Remove(link_prismaticFork);
        mysystem->Remove(link_actuatorFork);
        mysystem->Remove(truss);
        mysystem->Remove(wheelRF);
        mysystem->Remove(wheelLF);
        mysystem->Remove(wheelB);
        mysystem->Remove(spindleB);
        mysystem->Remove(arm);
        mysystem->Remove(fork);
    }
Esempio n. 15
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;
}
Esempio n. 16
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);
				

				}

		
			} 
Esempio n. 17
0
int main(int argc, char* argv[])
{

	// In CHRONO engine, The DLL_CreateGlobals() - DLL_DeleteGlobals(); pair is needed if
	// global functions are needed.
	DLL_CreateGlobals();

	// Create a ChronoENGINE physical system
	ChSystem mphysicalSystem;

	// Create the Irrlicht visualization (open the Irrlicht device, 
	// bind a simple user interface, etc. etc.)
	ChIrrAppInterface application(&mphysicalSystem, L"Benchmark application",core::dimension2d<u32>(800,600),false);

 
	// Easy shortcuts to add logo, camera, lights and sky in Irrlicht scene:
	ChIrrWizard::add_typical_Lights(application.GetDevice());
	ChIrrWizard::add_typical_Camera(application.GetDevice(), core::vector3df(0,14,-40));



 	// 
	// CREATE THE MECHANICAL SYSTEM OF CHRONO...
	// 

 
	application.GetVideoDriver()->beginScene(true, true, SColor(255,140,161,192));
	application.GetVideoDriver()->endScene(); 
	GetLog() << "  ** PLEASE WAIT FOR INITIALIZATION! \n  ** This may take seconds or minutes..\n\n";

    
	// Prepare the physical system for the simulation
 
	mphysicalSystem.SetIntegrationType(ChSystem::INT_ANITESCU); 
	//mphysicalSystem.SetIntegrationType(ChSystem::INT_TASORA); 

	//mphysicalSystem.SetLcpSolverType(ChSystem::LCP_ITERATIVE_SYMMSOR); // here would be the better choiche since the wall is build ground up.
	//mphysicalSystem.SetLcpSolverType(ChSystem::LCP_ITERATIVE_SOR);
	//mphysicalSystem.SetLcpSolverType(ChSystem::LCP_ITERATIVE_JACOBI); 
	//mphysicalSystem.SetLcpSolverType(ChSystem::LCP_ITERATIVE_SOR_MULTITHREAD); 
	//mphysicalSystem.SetParallelThreadNumber(4);

	mphysicalSystem.SetMaxPenetrationRecoverySpeed(1.6); // used by Anitescu stepper only
	mphysicalSystem.SetIterLCPmaxItersSpeed(20);
	mphysicalSystem.SetIterLCPmaxItersStab(10); // unuseful for Anitescu, only Tasora uses this
	//mphysicalSystem.SetIterLCPwarmStarting(true);


	// Test convergence for varying omega 
	//
	// (solver:SOR)
	//
	if (false)
	{
		ChStreamOutAsciiFile data_err_SOR_Niter("data_err_SOR_Niter.dat");
		ChStreamOutAsciiFile data_dgamma_SOR_Niter("data_dgamma_SOR_Niter.dat");
		int plotframe = 500;
		int ntestspheres = 220;

		mphysicalSystem.SetLcpSolverType(ChSystem::LCP_ITERATIVE_SOR);
		mphysicalSystem.SetIterLCPmaxItersSpeed(80);
		mphysicalSystem.SetMaxPenetrationRecoverySpeed(2.0); 

		ChLcpIterativeSolver* msolver = (ChLcpIterativeSolver*)mphysicalSystem.GetLcpSolverSpeed();
		msolver->SetRecordViolation(true);

		for (double momega = 0.2; (momega <= 1.401 && application.GetDevice()->run()); momega +=0.2)
		{
			ISceneNode* parent = application.GetSceneManager()->addEmptySceneNode();

			mphysicalSystem.SetIterLCPomega(0.8);
			mphysicalSystem.SetIterLCPsharpnessLambda(1.0);
			mphysicalSystem.SetMaxPenetrationRecoverySpeed(2.0);

				// create spheres and walls, and insert into that scene node
			ChSetRandomSeed(123);
			create_some_falling_items(mphysicalSystem, application.GetSceneManager(), application.GetVideoDriver(), parent, ntestspheres, 1.6, 10); 

			int totframes = 0;
										// ------- begin simulation loop -----
			while(application.GetDevice()->run())
			{
				totframes++;

				application.GetVideoDriver()->beginScene(true, true, SColor(255,140,161,192));
				application.DrawAll();

				if (totframes==plotframe)
				{
					mphysicalSystem.SetIterLCPomega(momega);
					mphysicalSystem.SetIterLCPsharpnessLambda(0.7);
					mphysicalSystem.SetMaxPenetrationRecoverySpeed(0.0);
				}

				// integrate
				mphysicalSystem.DoStepDynamics(0.01);

				application.GetVideoDriver()->endScene(); 

				//***PLOT***
				if (totframes==plotframe)
				{
					GetLog()<< "Saving data\n";
					ChLcpIterativeSolver* msolver = (ChLcpIterativeSolver*)mphysicalSystem.GetLcpSolverSpeed();
					for (int k=0; k< msolver->GetViolationHistory().size(); k++)
					{
						data_err_SOR_Niter <<  msolver->GetViolationHistory()[k] << " ";
					}
					for (int j=0; j< msolver->GetDeltalambdaHistory().size(); j++)
					{
						data_dgamma_SOR_Niter <<  msolver->GetDeltalambdaHistory()[j] << " ";
					}
				}


				

				if(totframes>plotframe) break;

			}							// ------- end of simulation loop -----

			GetLog()<< "  num contacts " << mphysicalSystem.GetNcontacts() << "\n";
			
			data_err_SOR_Niter << "\n";
			data_dgamma_SOR_Niter << "\n";

			// remove the root scene node (contains walls & spheres but no camera no lights)
			// to reset and prepare for new scene at next for() loop.
			parent->remove();

			// Now the system should already have no bodies, because of full removal from Irrlicht scene.
			// Then, the following clearing should be unuseful...(do it anyway..)
			mphysicalSystem.Clear(); 
		}

	} // end test



	// Test convergence for varying omega 
	//
	// (solver:JACOBI)
	//
	if (false)
	{
		ChStreamOutAsciiFile data_err_JACOBI_Niter("data_err_JACOBI_Niter_L10_at500_ok.dat");
		ChStreamOutAsciiFile data_dgamma_JACOBI_Niter("data_dgamma_JACOBI_Niter_L10_at500_ok.dat");
		int plotframe = 500;
		int ntestspheres = 220;

		mphysicalSystem.SetLcpSolverType(ChSystem::LCP_ITERATIVE_SOR);
		mphysicalSystem.SetIterLCPomega(0.8);
		mphysicalSystem.SetIterLCPmaxItersSpeed(80);
		mphysicalSystem.SetMaxPenetrationRecoverySpeed(2.0); 

		ChLcpIterativeSolver* msolver = (ChLcpIterativeSolver*)mphysicalSystem.GetLcpSolverSpeed();
		msolver->SetRecordViolation(true);

		for (double momega = 0.1; (momega <= 0.71 && application.GetDevice()->run()); momega +=0.1)
		{
			ISceneNode* parent = application.GetSceneManager()->addEmptySceneNode();

			mphysicalSystem.SetLcpSolverType(ChSystem::LCP_ITERATIVE_SOR);
			mphysicalSystem.SetIterLCPomega(0.8);
			mphysicalSystem.SetIterLCPmaxItersSpeed(80);
			mphysicalSystem.SetMaxPenetrationRecoverySpeed(2.0); 
			mphysicalSystem.SetIterLCPsharpnessLambda(1.0);

				// create spheres and walls, and insert into that scene node
			ChSetRandomSeed(123);
			create_some_falling_items(mphysicalSystem, application.GetSceneManager(), application.GetVideoDriver(), parent, ntestspheres, 1.6, 10); 

			int totframes = 0;
										// ------- begin simulation loop -----
			while(application.GetDevice()->run())
			{
				totframes++;

				application.GetVideoDriver()->beginScene(true, true, SColor(255,140,161,192));
				application.DrawAll();

				if (totframes==plotframe)
				{
					mphysicalSystem.SetLcpSolverType(ChSystem::LCP_ITERATIVE_JACOBI);
					ChLcpIterativeSolver* msolver = (ChLcpIterativeSolver*)mphysicalSystem.GetLcpSolverSpeed();
					msolver->SetRecordViolation(true);
					mphysicalSystem.SetIterLCPomega(momega);
					mphysicalSystem.SetIterLCPsharpnessLambda(1.0);
					mphysicalSystem.SetMaxPenetrationRecoverySpeed(0.0);
				}

				// integrate
				mphysicalSystem.DoStepDynamics(0.01);

				application.GetVideoDriver()->endScene(); 

				//***PLOT***
				if (totframes==plotframe)
				{
					GetLog()<< "Saving data\n";
					ChLcpIterativeSolver* msolver = (ChLcpIterativeSolver*)mphysicalSystem.GetLcpSolverSpeed();
					for (int k=0; k< msolver->GetViolationHistory().size(); k++)
					{
						data_err_JACOBI_Niter <<  msolver->GetViolationHistory()[k] << " ";
					}
					for (int j=0; j< msolver->GetDeltalambdaHistory().size(); j++)
					{
						data_dgamma_JACOBI_Niter <<  msolver->GetDeltalambdaHistory()[j] << " ";
					}
				}

				if(totframes>plotframe) break;

			}							// ------- end of simulation loop -----

			GetLog()<< "  num contacts " << mphysicalSystem.GetNcontacts() << "\n";
			
			data_err_JACOBI_Niter << "\n";
			data_dgamma_JACOBI_Niter << "\n";

			// remove the root scene node (contains walls & spheres but no camera no lights)
			// to reset and prepare for new scene at next for() loop.
			parent->remove();

			// Now the system should already have no bodies, because of full removal from Irrlicht scene.
			// Then, the following clearing should be unuseful...(do it anyway..)
			mphysicalSystem.Clear(); 
		}

	} // end test



	// Test lambda effect
	//
	// Velocity error  vs.  Num. velocity iterations  vs. Lambda
	// (solver:SOR)
	//
	if (false)
	{
		ChStreamOutAsciiFile data_err_SOR_Niter("data_err_SOR_Niter_om1.dat");
		ChStreamOutAsciiFile data_dgamma_SOR_Niter("data_dgamma_SOR_Niter_om1.dat");
		int plotframe = 500;
		int ntestspheres = 220;

		mphysicalSystem.SetLcpSolverType(ChSystem::LCP_ITERATIVE_SOR);
		mphysicalSystem.SetIterLCPmaxItersSpeed(80);
		mphysicalSystem.SetMaxPenetrationRecoverySpeed(2.0); 

		ChLcpIterativeSolver* msolver = (ChLcpIterativeSolver*)mphysicalSystem.GetLcpSolverSpeed();
		msolver->SetRecordViolation(true);

		for (double mlambda = 0.2; (mlambda <= 1.01 && application.GetDevice()->run()); mlambda +=0.2)
		{
			ISceneNode* parent = application.GetSceneManager()->addEmptySceneNode();

			mphysicalSystem.SetIterLCPomega(0.8);
			mphysicalSystem.SetIterLCPsharpnessLambda(1.0);
			mphysicalSystem.SetMaxPenetrationRecoverySpeed(2.0);

				// create spheres and walls, and insert into that scene node
			ChSetRandomSeed(123);
			create_some_falling_items(mphysicalSystem, application.GetSceneManager(), application.GetVideoDriver(), parent, ntestspheres, 1.6, 10); 

			int totframes = 0;
										// ------- begin simulation loop -----
			while(application.GetDevice()->run())
			{
				totframes++;

				application.GetVideoDriver()->beginScene(true, true, SColor(255,140,161,192));
				application.DrawAll();

				if (totframes==plotframe)
				{
					mphysicalSystem.SetIterLCPomega(1.0);
					mphysicalSystem.SetIterLCPsharpnessLambda(mlambda);
					mphysicalSystem.SetMaxPenetrationRecoverySpeed(0.0);
				}

				// integrate
				mphysicalSystem.DoStepDynamics(0.01);

				application.GetVideoDriver()->endScene(); 

				//***PLOT***
				if (totframes==plotframe)
				{
					GetLog()<< "Saving data\n";
					ChLcpIterativeSolver* msolver = (ChLcpIterativeSolver*)mphysicalSystem.GetLcpSolverSpeed();
					for (int k=0; k< msolver->GetViolationHistory().size(); k++)
					{
						data_err_SOR_Niter <<  msolver->GetViolationHistory()[k] << " ";
					}
					for (int j=0; j< msolver->GetDeltalambdaHistory().size(); j++)
					{
						data_dgamma_SOR_Niter <<  msolver->GetDeltalambdaHistory()[j] << " ";
					}
				}


				

				if(totframes>plotframe) break;

			}							// ------- end of simulation loop -----

			GetLog()<< "  num contacts " << mphysicalSystem.GetNcontacts() << "\n";
			
			data_err_SOR_Niter << "\n";
			data_dgamma_SOR_Niter << "\n";

			// remove the root scene node (contains walls & spheres but no camera no lights)
			// to reset and prepare for new scene at next for() loop.
			parent->remove();

			// Now the system should already have no bodies, because of full removal from Irrlicht scene.
			// Then, the following clearing should be unuseful...(do it anyway..)
			mphysicalSystem.Clear(); 
		}

	} // end test



	// Test stack aspect ratio
	//
	//
	if (false)
	{
		ChStreamOutAsciiFile data_err_SOR_Niter("data_err_aspectratio3.dat");
		int plotframe = 500;
		int ntestspheres = 220;

		mphysicalSystem.SetLcpSolverType(ChSystem::LCP_ITERATIVE_SOR);
		mphysicalSystem.SetIterLCPmaxItersSpeed(30);
		mphysicalSystem.SetMaxPenetrationRecoverySpeed(2.0); 

		ChLcpIterativeSolver* msolver = (ChLcpIterativeSolver*)mphysicalSystem.GetLcpSolverSpeed();
		msolver->SetRecordViolation(true);

		for (double mspheres=10; (mspheres <= 330 && application.GetDevice()->run()); mspheres +=40)
		{
			for (int nviters = 20; (nviters <= 101 && application.GetDevice()->run()); nviters +=20)
			{
				ISceneNode* parent = application.GetSceneManager()->addEmptySceneNode();

				mphysicalSystem.SetIterLCPomega(0.9);
				mphysicalSystem.SetIterLCPsharpnessLambda(1.0);
				mphysicalSystem.SetIterLCPmaxItersSpeed(30);
				mphysicalSystem.SetMaxPenetrationRecoverySpeed(2.0);
				
					// create spheres and walls, and insert into that scene node
				ChSetRandomSeed(13);
				create_some_falling_items(mphysicalSystem, application.GetSceneManager(), application.GetVideoDriver(), parent, mspheres, 1.6, 10,20.1); 

				int totframes = 0;
											// ------- begin simulation loop -----
				while(application.GetDevice()->run())
				{
					totframes++;

					application.GetVideoDriver()->beginScene(true, true, SColor(255,140,161,192));
					application.DrawAll();

					if (totframes==plotframe)
					{
						mphysicalSystem.SetIterLCPomega(0.9);
						mphysicalSystem.SetIterLCPmaxItersSpeed(nviters);
						mphysicalSystem.SetMaxPenetrationRecoverySpeed(0.0);
					}

					application.GetVideoDriver()->beginScene(true, true, SColor(255,140,161,192));
					application.DrawAll();

					// integrate
					mphysicalSystem.DoStepDynamics(0.01);

					application.GetVideoDriver()->endScene(); 

					//***PLOT***
					if (totframes==plotframe)
					{
						GetLog()<< "Saving data\n";
						ChLcpIterativeSolver* msolver = (ChLcpIterativeSolver*)mphysicalSystem.GetLcpSolverSpeed();
						data_err_SOR_Niter <<  msolver->GetViolationHistory()[msolver->GetViolationHistory().size()-1] << " ";
					}

					if(totframes>plotframe) break;

				}							// ------- end of simulation loop -----

				
				// remove the root scene node (contains walls & spheres but no camera no lights)
				// to reset and prepare for new scene at next for() loop.
				parent->remove();

				// Now the system should already have no bodies, because of full removal from Irrlicht scene.
				// Then, the following clearing should be unuseful...(do it anyway..)
				mphysicalSystem.Clear(); 
			}

			data_err_SOR_Niter << "\n";
		}

	} // end test




	// Test pos error
	//
	//
	if (false)
	{
		ChStreamOutAsciiFile data_err_pos("data_err_pos.dat");
		int plotframe = 500;
		int ntestspheres = 120;
		double mystep= 0;

		for (double mdt=0.01; (mdt>0.00015 && application.GetDevice()->run()); mdt*=0.5)
		{
			GetLog() << "\n\nDT = " << mdt << "\n";

			for (int nviters = 20; (nviters <= 81 && application.GetDevice()->run()); nviters +=20)
			{
				GetLog() << "  nviters = " << nviters << "\n";

				ISceneNode* parent = application.GetSceneManager()->addEmptySceneNode();

				mystep = 0.01;
				mphysicalSystem.SetChTime(0.0);
				mphysicalSystem.SetIterLCPsharpnessLambda(0.8);
				mphysicalSystem.SetIterLCPomega(0.8);
				mphysicalSystem.SetLcpSolverType(ChSystem::LCP_ITERATIVE_SOR);
				mphysicalSystem.SetIterLCPmaxItersSpeed(30);
				mphysicalSystem.SetMaxPenetrationRecoverySpeed(2.0); 
				
					// create spheres and walls, and insert into that scene node
				ChSetRandomSeed(13);
				create_some_falling_items(mphysicalSystem, application.GetSceneManager(), application.GetVideoDriver(), parent, ntestspheres, 1.6, 10); 

				int totframes = 0;
				int averagecnt = 0;
				double average = 0;
											// ------- begin simulation loop -----
				while(application.GetDevice()->run())
				{
					totframes++;

					application.GetVideoDriver()->beginScene(true, true, SColor(255,140,161,192));
					application.DrawAll();

					// start mode
					if (mphysicalSystem.GetChTime()>2.4)
					{	
						mphysicalSystem.SetIterLCPmaxItersSpeed(nviters);
						mystep=mdt;
					}

					//start average
					if (mphysicalSystem.GetChTime()>2.6)
					{	

						class _label_reporter_class : public chrono::ChReportContactCallback 
						{
						public:
							virtual bool ReportContactCallback (
											const chrono::ChVector<>& pA,				
											const chrono::ChVector<>& pB,				
											const chrono::ChMatrix33<>& plane_coord,	
											const double& distance,				
											const float& mfriction,			  	
											const chrono::ChVector<>& react_forces,		
											const chrono::ChVector<>& react_torques,	
											chrono::collision::ChCollisionModel* modA,	
											chrono::collision::ChCollisionModel* modB) 
							{
								if (distance<maxpen)
									maxpen = distance;
								return true; // to continue scanning contacts
							}
							// Data 
							double maxpen;
						};

						_label_reporter_class my_label_rep;

						my_label_rep.maxpen = 0;

						// scan all contacts
						mphysicalSystem.GetContactContainer()->ReportAllContacts(&my_label_rep);
						//GetLog() << "        p: " << my_label_rep.maxpen << "\n";
						averagecnt++;
						average += my_label_rep.maxpen;
					}

					// stop average & loop
					if(mphysicalSystem.GetChTime()>2.8)
					{
						average /= (double)averagecnt;
						GetLog() << "     avg.err: " << average << "\n";
						data_err_pos <<  average << " ";
						break;
					}

					// integrate
					mphysicalSystem.DoStepDynamics(mystep);

					application.GetVideoDriver()->endScene(); 

				}							// ------- end of simulation loop -----

				
				// remove the root scene node (contains walls & spheres but no camera no lights)
				// to reset and prepare for new scene at next for() loop.
				parent->remove();

				// Now the system should already have no bodies, because of full removal from Irrlicht scene.
				// Then, the following clearing should be unuseful...(do it anyway..)
				mphysicalSystem.Clear(); 
			}

			data_err_pos << "\n";
		}

	} // end test



	// Test pos error with Tasora stabilization
	//
	//
	if (true)
	{
		ChStreamOutAsciiFile data_err_pos("data_err_tasora.dat");
		int ntestspheres = 120;

		for (int npiters = 20; (npiters <= 81 && application.GetDevice()->run()); npiters +=20)
		{
			GetLog() << "  npiters = " << npiters << "\n";

			for (int nviters = 20; (nviters <= 81 && application.GetDevice()->run()); nviters +=20)
			{
				GetLog() << "  nviters = " << nviters << "\n";

				ISceneNode* parent = application.GetSceneManager()->addEmptySceneNode();

				mphysicalSystem.SetChTime(0.0);
				mphysicalSystem.SetIterLCPsharpnessLambda(0.8);
				mphysicalSystem.SetIterLCPomega(0.8);
				mphysicalSystem.SetLcpSolverType(ChSystem::LCP_ITERATIVE_SOR);
				mphysicalSystem.SetIntegrationType(ChSystem::INT_TASORA);
				mphysicalSystem.SetIterLCPmaxItersSpeed(30);
				mphysicalSystem.SetIterLCPmaxItersStab(30);
				mphysicalSystem.SetMaxPenetrationRecoverySpeed(0.0); 
				
					// create spheres and walls, and insert into that scene node
				ChSetRandomSeed(13);
				create_some_falling_items(mphysicalSystem, application.GetSceneManager(), application.GetVideoDriver(), parent, ntestspheres, 1.6, 10); 

				int totframes = 0;
				int averagecnt = 0;
				double average = 0;
											// ------- begin simulation loop -----
				while(application.GetDevice()->run())
				{
					totframes++;

					application.GetVideoDriver()->beginScene(true, true, SColor(255,140,161,192));
					application.DrawAll();

					// start mode
					if (mphysicalSystem.GetChTime()>3)
					{	
						mphysicalSystem.SetIterLCPmaxItersSpeed(nviters);
						mphysicalSystem.SetIterLCPmaxItersStab(npiters);
					}

					//start average
					if (mphysicalSystem.GetChTime()>4.2)
					{	

						class _label_reporter_class : public chrono::ChReportContactCallback 
						{
						public:
							virtual bool ReportContactCallback (
											const chrono::ChVector<>& pA,				
											const chrono::ChVector<>& pB,				
											const chrono::ChMatrix33<>& plane_coord,	
											const double& distance,				
											const float& mfriction,			  	
											const chrono::ChVector<>& react_forces,		
											const chrono::ChVector<>& react_torques,	
											chrono::collision::ChCollisionModel* modA,	
											chrono::collision::ChCollisionModel* modB) 
							{
								if (distance<maxpen)
									maxpen = distance;
								return true; // to continue scanning contacts
							}
							// Data 
							double maxpen;
						};

						_label_reporter_class my_label_rep;

						my_label_rep.maxpen = 0;

						// scan all contacts
						mphysicalSystem.GetContactContainer()->ReportAllContacts(&my_label_rep);
						averagecnt++;
						average += my_label_rep.maxpen;
					}

					// stop average & loop
					if(mphysicalSystem.GetChTime()>4.5)
					{
						average /= (double)averagecnt;
						GetLog() << "     avg.err: " << average << "\n";
						data_err_pos <<  average << " ";
						break;
					}

					// integrate
					mphysicalSystem.DoStepDynamics(0.01);

					application.GetVideoDriver()->endScene(); 

				}							// ------- end of simulation loop -----

				
				// remove the root scene node (contains walls & spheres but no camera no lights)
				// to reset and prepare for new scene at next for() loop.
				parent->remove();

				// Now the system should already have no bodies, because of full removal from Irrlicht scene.
				// Then, the following clearing should be unuseful...(do it anyway..)
				mphysicalSystem.Clear(); 
			}

			data_err_pos << "\n";
		}

	} // end test



	getchar();



	//
	// loop of tests:each time test more spheres!
	// 
	ChStreamOutAsciiFile data_spheres_times("data_spheres_times.dat");
	ChStreamOutAsciiFile data_contacts_times("data_contact_times.dat");
	ChStreamOutAsciiFile data_ncontacts("data_ncontacts.dat");
	ChStreamOutAsciiFile data_timexconstr("data_timexconstr.dat");

	for (int nspheres = 1; (nspheres <= 1 && application.GetDevice()->run()); nspheres +=1)
	{

		ChStreamOutAsciiFile data_timing("data_timing1k.dat");
		

		// 
		// Create all the  rigid bodies!!!! 
		//

			// the root scene node containing all dynamic objects
		ISceneNode* parent = application.GetSceneManager()->addEmptySceneNode();

			// create spheres and walls, and insert into that scene node
		create_some_falling_items(mphysicalSystem, application.GetSceneManager(), application.GetVideoDriver(), parent, SPHERE_NUM,SPHERE_RAD,SPHERE_MASS); 

		// 
		// THE SOFT-REAL-TIME CYCLE
		// 

		int mdelay=0;
		int lastFPS = -1;

		ChTimer<double>mtimer; 

		ChRealtimeStepTimer m_realtime_timer;

		//ChStreamOutAsciiFile data_deltares("data_pNviolation_i80.dat");


		int totframes = 0;
		while(application.GetDevice()->run())
		{
			totframes++;

			if (totframes == 400) mtimer.start();

			// Irrlicht must prepare frame to draw
			application.GetVideoDriver()->beginScene(true, true, SColor(255,140,161,192));
		
			// Irrlicht draws all 3D objects and all GUI items
			application.DrawAll();


			// HERE CHRONO INTEGRATION IS PERFORMED: THE  
			// TIME OF THE SIMULATION ADVANCES FOR A SINGLE
			// STEP:
			mphysicalSystem.DoStepDynamics(0.01);


			application.GetVideoDriver()->endScene(); 

			

			if (totframes > 600)
			data_timing << mphysicalSystem.GetChTime()-3.0 << " " \
						<< mphysicalSystem.GetTimerStep() << " " \
						<< mphysicalSystem.GetTimerLcp()+mphysicalSystem.GetTimerCollisionBroad() << " " \
						<< mphysicalSystem.GetTimerLcp() << "\n";


			/*
			//***PLOT*** plot max constr.normal violation
			if ((totframes<600)&&(totframes>300))
			{
				ChLcpIterativeSolver* msolver = (ChLcpIterativeSolver*)mphysicalSystem.GetLcpSolverStab();
				if (msolver->GetViolationHistory().size()>1)
					data_deltares <<  msolver->GetViolationHistory()[msolver->GetViolationHistory().size()-1] << "\n";
			}

			//***PLOT*** plot deltalambda corrections for varying omega
			if (totframes==999)
			{
				ChLcpIterativeSymmSOR* msolver = (ChLcpIterativeSymmSOR*)mphysicalSystem.GetLcpSolverSpeed();
				msolver->SetOmega(1.0);
			}
			if (totframes==1000)
			{
				GetLog()<< "Saving plot data\n";
				ChLcpIterativeSolver* msolver = (ChLcpIterativeSolver*)mphysicalSystem.GetLcpSolverSpeed();
				ChStreamOutAsciiFile data_deltalambda("data_deltalambda_om80.dat");
				for (int k=0; k< msolver->GetDeltalambdaHistory().size(); k++)
				{
					data_deltalambda <<  msolver->GetDeltalambdaHistory()[k] << "\n";
				}
			}
			*/

			if ((totframes>200)&&(totframes<=500))
			{
				//data_timexconstr << mphysicalSystem.GetTimerLcp()/(double)mphysicalSystem.GetNcontacts() << "\n";
				//GetLog()<< "  avg time/contacts " << mphysicalSystem.GetTimerLcp()/(double)mphysicalSystem.GetNcontacts() << "\n";
				//GetLog()<< "  ncontacts " << (double)mphysicalSystem.GetNcontacts() << "\n";
			}

			if(totframes>500) break;


		}  // ------- end of simulation loop -----



		mtimer.stop();
		GetLog()<< "Time used for simulating/viewing first 500 steps: " << mtimer() << "\n";
		GetLog()<< "  num contacts " << mphysicalSystem.GetNcontacts() << "\n";
		GetLog()<< "  avg time/contacts " << mtimer()/(double)mphysicalSystem.GetNcontacts() << "\n";
		data_spheres_times << nspheres << "  " << mtimer() << "\n";
		data_contacts_times << mphysicalSystem.GetNcontacts() << "  " << mtimer() << "\n";
		

		// remove the root scene node (contains walls & spheres but no camera no lights)
		// to reset and prepare for new scene at next for() loop.
		parent->remove();

		// Now the system should already have no bodies, because of full removal from Irrlicht scene.
		// Then, the following clearing should be unuseful...(do it anyway..)
		mphysicalSystem.Clear(); 
	}



	// Remember this at the end of the program, if you started
	// with DLL_CreateGlobals();
	DLL_DeleteGlobals();

	getchar();

	return 0;
}