1 // =============================================================================
2 // PROJECT CHRONO - http://projectchrono.org
3 //
4 // Copyright (c) 2014 projectchrono.org
5 // All rights reserved.
6 //
7 // Use of this source code is governed by a BSD-style license that can be found
8 // in the LICENSE file at the top level of the distribution and at
9 // http://projectchrono.org/license-chrono.txt.
10 //
11 // =============================================================================
12 //   Demo code (advanced), about
13 //
14 //     - using the SCM semi-empirical model for deformable soil
15 //     - using a deformable tire
16 // =============================================================================
17 
18 #include "chrono/geometry/ChTriangleMeshConnected.h"
19 #include "chrono/physics/ChLinkMotorRotationAngle.h"
20 #include "chrono/physics/ChLoadContainer.h"
21 #include "chrono/physics/ChSystemSMC.h"
22 
23 #include "chrono_irrlicht/ChIrrApp.h"
24 #include "chrono_pardisomkl/ChSolverPardisoMKL.h"
25 
26 #include "chrono_vehicle/ChVehicleModelData.h"
27 #include "chrono_vehicle/terrain/SCMDeformableTerrain.h"
28 #include "chrono_vehicle/wheeled_vehicle/wheel/Wheel.h"
29 #include "chrono_vehicle/wheeled_vehicle/tire/ReissnerTire.h"
30 
31 using namespace chrono;
32 using namespace chrono::irrlicht;
33 using namespace chrono::vehicle;
34 
35 using namespace irr;
36 
main(int argc,char * argv[])37 int main(int argc, char* argv[]) {
38     GetLog() << "Copyright (c) 2017 projectchrono.org\nChrono version: " << CHRONO_VERSION << "\n\n";
39 
40     // Global parameter for tire:
41     double tire_rad = 0.5;
42     ChVector<> tire_center(0, tire_rad, 0);
43 
44     // Create a Chrono physical system
45     ChSystemSMC my_system;
46 
47     // Create the Irrlicht visualization (open the Irrlicht device,
48     // bind a simple user interface, etc. etc.)
49     ChIrrApp application(&my_system, L"Deformable soil and deformable tire", core::dimension2d<u32>(1280, 720),
50                          VerticalDir::Y, false, true);
51 
52     // Easy shortcuts to add camera, lights, logo and sky in Irrlicht scene:
53     application.AddTypicalLogo();
54     application.AddTypicalSky();
55     application.AddTypicalLights();
56     application.AddTypicalCamera(core::vector3df(1.0f, 1.4f, -1.2f), core::vector3df(0, (f32)tire_rad, 0));
57     application.AddLightWithShadow(core::vector3df(1.5f, 5.5f, -2.5f), core::vector3df(0, 0, 0), 3, 2.2, 7.2, 40, 512,
58                                    video::SColorf(0.8f, 0.8f, 1.0f));
59 
60     std::shared_ptr<ChBody> mtruss (new ChBody);
61     mtruss->SetBodyFixed(true);
62     my_system.Add(mtruss);
63 
64 
65     //
66     // CREATE A DEFORMABLE TIRE
67     //
68 
69     // The rim body:
70     auto mrim = chrono_types::make_shared<ChBody>();
71     my_system.Add(mrim);
72     mrim->SetMass(80);
73     mrim->SetInertiaXX(ChVector<>(1,1,1));
74     mrim->SetPos(tire_center + ChVector<>(0,0.2,0));
75     mrim->SetRot(Q_from_AngAxis(CH_C_PI_2, VECT_Z));
76 
77     // The wheel object:
78     auto wheel = chrono_types::make_shared<Wheel>(vehicle::GetDataFile("hmmwv/wheel/HMMWV_Wheel.json"));
79     wheel->Initialize(mrim, LEFT);
80 
81     // The tire:
82     auto tire_reissner = chrono_types::make_shared<ReissnerTire>(vehicle::GetDataFile("hmmwv/tire/HMMWV_ReissnerTire.json"));
83     tire_reissner->EnablePressure(false);
84     tire_reissner->EnableContact(true);
85     tire_reissner->SetContactSurfaceType(ChDeformableTire::ContactSurfaceType::TRIANGLE_MESH);
86     tire_reissner->EnableRimConnection(true);
87     std::static_pointer_cast<ChTire>(tire_reissner)->Initialize(wheel);
88     tire_reissner->SetVisualizationType(VisualizationType::MESH);
89 
90     // Attach tire to wheel
91     wheel->GetTire() = tire_reissner;
92 
93     // The motor that rotates the rim:
94     auto motor = chrono_types::make_shared<ChLinkMotorRotationAngle>();
95     motor->SetSpindleConstraint(ChLinkMotorRotation::SpindleConstraint::OLDHAM);
96     motor->SetAngleFunction(chrono_types::make_shared<ChFunction_Ramp>(0, CH_C_PI / 4.0));
97     motor->Initialize(mrim, mtruss, ChFrame<>(tire_center, Q_from_AngAxis(CH_C_PI_2, VECT_Y)));
98     my_system.Add(motor);
99 
100 
101     //
102     // THE DEFORMABLE TERRAIN
103     //
104 
105     // Create the 'deformable terrain' object
106     vehicle::SCMDeformableTerrain mterrain(&my_system);
107 
108     // Displace/rotate the terrain reference plane.
109     // Note that SCMDeformableTerrain uses a default ISO reference frame (Z up). Since the mechanism is modeled here in
110     // a Y-up global frame, we rotate the terrain plane by -90 degrees about the X axis.
111     mterrain.SetPlane(ChCoordsys<>(ChVector<>(0, 0.2, 0.3), Q_from_AngX(-CH_C_PI_2)));
112 
113     // Initialize the geometry of the soil: use either a regular grid:
114     mterrain.Initialize(1.5, 6, 0.075);
115 
116     // Set the soil terramechanical parameters:
117      mterrain.SetSoilParameters(1.2e6,  // Bekker Kphi
118                                 0,      // Bekker Kc
119                                 1.1,    // Bekker n exponent
120                                 0,      // Mohr cohesive limit (Pa)
121                                 30,     // Mohr friction limit (degrees)
122                                 0.01,   // Janosi shear coefficient (m)
123                                5e7,    // Elastic stiffness (Pa/m), before plastic yield, must be > Kphi
124                                2e4     // Damping (Pa s/m), proportional to negative vertical speed (optional)
125     );
126     mterrain.EnableBulldozing(true);  // inflate soil at the border of the rut
127     mterrain.SetBulldozingParameters(
128         55,   // angle of friction for erosion of displaced material at the border of the rut
129         0.8,  // displaced material vs downward pressed material.
130         5,    // number of erosion refinements per timestep
131         10);  // number of concentric vertex selections subject to erosion
132 
133     // Set some visualization parameters: either with a texture, or with falsecolor plot, etc.
134     //mterrain.SetTexture(vehicle::GetDataFile("terrain/textures/grass.jpg"), 16, 16);
135     //mterrain.SetPlotType(vehicle::SCMDeformableTerrain::PLOT_PRESSURE, 0, 30000.2);
136     mterrain.SetPlotType(vehicle::SCMDeformableTerrain::PLOT_PRESSURE_YELD, 0, 30000.2);
137     //mterrain.SetPlotType(vehicle::SCMDeformableTerrain::PLOT_SINKAGE, 0, 0.15);
138     //mterrain.SetPlotType(vehicle::SCMDeformableTerrain::PLOT_SINKAGE_PLASTIC, 0, 0.15);
139     //mterrain.SetPlotType(vehicle::SCMDeformableTerrain::PLOT_SINKAGE_ELASTIC, 0, 0.05);
140     //mterrain.SetPlotType(vehicle::SCMDeformableTerrain::PLOT_STEP_PLASTIC_FLOW, 0, 0.0001);
141     //mterrain.SetPlotType(vehicle::SCMDeformableTerrain::PLOT_ISLAND_ID, 0, 8);
142     //mterrain.SetPlotType(vehicle::SCMDeformableTerrain::PLOT_IS_TOUCHED, 0, 8);
143     mterrain.GetMesh()->SetWireframe(true);
144 
145 
146 
147     // ==IMPORTANT!== Use this function for adding a ChIrrNodeAsset to all items
148     application.AssetBindAll();
149 
150     // ==IMPORTANT!== Use this function for 'converting' into Irrlicht meshes the assets
151     application.AssetUpdateAll();
152 
153     // Use shadows in realtime view
154     application.AddShadowAll();
155 
156 
157     //
158     // THE SOFT-REAL-TIME CYCLE
159     //
160 
161     // change the solver to PardisoMKL:
162     GetLog() << "Using PardisoMKL solver\n";
163     auto mkl_solver = chrono_types::make_shared<ChSolverPardisoMKL>();
164     mkl_solver->LockSparsityPattern(true);
165     my_system.SetSolver(mkl_solver);
166 
167 
168     // Change the timestepper to HHT:
169     my_system.SetTimestepperType(ChTimestepper::Type::HHT);
170     auto integrator = std::static_pointer_cast<ChTimestepperHHT>(my_system.GetTimestepper());
171     integrator->SetAlpha(-0.2);
172     integrator->SetMaxiters(8);
173     integrator->SetAbsTolerances(5e-05, 1.8e00);
174     integrator->SetMode(ChTimestepperHHT::POSITION);
175     integrator->SetModifiedNewton(false);
176     integrator->SetScaling(true);
177     integrator->SetVerbose(true);
178 
179 
180 
181 
182     application.SetTimestep(0.002);
183 
184     while (application.GetDevice()->run()) {
185         application.BeginScene();
186 
187         application.DrawAll();
188 
189         application.DoStep();
190 
191         tools::drawColorbar(0,30000, "Pressure yield [Pa]", application.GetDevice(),  1180);
192 
193         application.EndScene();
194     }
195 
196     return 0;
197 }
198