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 // Author: Radu Serban
13 // =============================================================================
14 //
15 // Chrono::Vehicle + Chrono::Multicore demo program for simulating a HMMWV vehicle
16 // over rigid or granular material.
17 //
18 // Contact uses the SMC (penalty) formulation.
19 //
20 // The global reference frame has Z up.
21 // All units SI.
22 // =============================================================================
23
24 #include <cstdio>
25 #include <cmath>
26 #include <vector>
27
28 #include "chrono/utils/ChUtilsInputOutput.h"
29
30 #include "chrono_vehicle/ChVehicleModelData.h"
31 #include "chrono_vehicle/ChDriver.h"
32 #include "chrono_vehicle/terrain/SCMDeformableTerrain.h"
33 #include "chrono_vehicle/terrain/RigidTerrain.h"
34 #include "chrono_vehicle/wheeled_vehicle/utils/ChWheeledVehicleIrrApp.h"
35
36 #include "chrono_models/vehicle/hmmwv/HMMWV.h"
37
38 #include "chrono_thirdparty/filesystem/path.h"
39
40 using namespace chrono;
41 using namespace chrono::collision;
42 using namespace chrono::irrlicht;
43 using namespace chrono::vehicle;
44 using namespace chrono::vehicle::hmmwv;
45
46 using std::cout;
47 using std::endl;
48
49 // =============================================================================
50 // USER SETTINGS
51 // =============================================================================
52
53 // -----------------------------------------------------------------------------
54 // Terrain parameters
55 // -----------------------------------------------------------------------------
56
57 double terrainLength = 16.0; // size in X direction
58 double terrainWidth = 8.0; // size in Y direction
59 double delta = 0.05; // SCM grid spacing
60
61 // -----------------------------------------------------------------------------
62 // Vehicle parameters
63 // -----------------------------------------------------------------------------
64
65 // Type of tire (controls both contact and visualization)
66 enum class TireType { CYLINDRICAL, LUGGED };
67 TireType tire_type = TireType::LUGGED;
68
69 // Tire contact material properties
70 float Y_t = 1.0e6f;
71 float cr_t = 0.1f;
72 float mu_t = 0.8f;
73
74 // Initial vehicle position and orientation
75 ChVector<> initLoc(-5, -2, 0.6);
76 ChQuaternion<> initRot(1, 0, 0, 0);
77
78 // -----------------------------------------------------------------------------
79 // Simulation parameters
80 // -----------------------------------------------------------------------------
81
82 // Simulation step size
83 double step_size = 3e-3;
84
85 // Time interval between two render frames (1/FPS)
86 double render_step_size = 1.0 / 100;
87
88 // Point on chassis tracked by the camera
89 ChVector<> trackPoint(0.0, 0.0, 1.75);
90
91 // Output directories
92 const std::string out_dir = GetChronoOutputPath() + "HMMWV_DEF_SOIL";
93 const std::string img_dir = out_dir + "/IMG";
94
95 // Visualization output
96 bool img_output = false;
97
98 // =============================================================================
99
100 class MyDriver : public ChDriver {
101 public:
MyDriver(ChVehicle & vehicle,double delay)102 MyDriver(ChVehicle& vehicle, double delay) : ChDriver(vehicle), m_delay(delay) {}
~MyDriver()103 ~MyDriver() {}
104
Synchronize(double time)105 virtual void Synchronize(double time) override {
106 m_throttle = 0;
107 m_steering = 0;
108 m_braking = 0;
109
110 double eff_time = time - m_delay;
111
112 // Do not generate any driver inputs for a duration equal to m_delay.
113 if (eff_time < 0)
114 return;
115
116 if (eff_time > 0.2)
117 m_throttle = 0.7;
118 else
119 m_throttle = 3.5 * eff_time;
120
121 if (eff_time < 2)
122 m_steering = 0;
123 else
124 m_steering = 0.6 * std::sin(CH_C_2PI * (eff_time - 2) / 6);
125 }
126
127 private:
128 double m_delay;
129 };
130
131 // =============================================================================
132
CreateLuggedGeometry(std::shared_ptr<ChBody> wheel_body,std::shared_ptr<ChMaterialSurfaceSMC> wheel_material)133 void CreateLuggedGeometry(std::shared_ptr<ChBody> wheel_body, std::shared_ptr<ChMaterialSurfaceSMC> wheel_material) {
134 std::string lugged_file("hmmwv/lugged_wheel_section.obj");
135 geometry::ChTriangleMeshConnected lugged_mesh;
136 ChConvexDecompositionHACDv2 lugged_convex;
137 utils::LoadConvexMesh(vehicle::GetDataFile(lugged_file), lugged_mesh, lugged_convex);
138 int num_hulls = lugged_convex.GetHullCount();
139
140 auto coll_model = wheel_body->GetCollisionModel();
141 coll_model->ClearModel();
142
143 // Assemble the tire contact from 15 segments, properly offset.
144 // Each segment is further decomposed in convex hulls.
145 for (int iseg = 0; iseg < 15; iseg++) {
146 ChQuaternion<> rot = Q_from_AngAxis(iseg * 24 * CH_C_DEG_TO_RAD, VECT_Y);
147 for (int ihull = 0; ihull < num_hulls; ihull++) {
148 std::vector<ChVector<> > convexhull;
149 lugged_convex.GetConvexHullResult(ihull, convexhull);
150 coll_model->AddConvexHull(wheel_material, convexhull, VNULL, rot);
151 }
152 }
153
154 // Add a cylinder to represent the wheel hub.
155 coll_model->AddCylinder(wheel_material, 0.223, 0.223, 0.126);
156 coll_model->BuildModel();
157
158 // Visualization
159 auto trimesh = chrono_types::make_shared<geometry::ChTriangleMeshConnected>();
160 trimesh->LoadWavefrontMesh(vehicle::GetDataFile("hmmwv/lugged_wheel.obj"), false, false);
161
162 auto trimesh_shape = chrono_types::make_shared<ChTriangleMeshShape>();
163 trimesh_shape->SetMesh(trimesh);
164 trimesh_shape->SetName("lugged_wheel");
165 wheel_body->AddAsset(trimesh_shape);
166
167 auto mcolor = chrono_types::make_shared<ChColorAsset>(0.3f, 0.3f, 0.3f);
168 wheel_body->AddAsset(mcolor);
169 }
170
171 // =============================================================================
172
main(int argc,char * argv[])173 int main(int argc, char* argv[]) {
174 GetLog() << "Copyright (c) 2017 projectchrono.org\nChrono version: " << CHRONO_VERSION << "\n\n";
175
176 // --------------------
177 // Create HMMWV vehicle
178 // --------------------
179 HMMWV_Full my_hmmwv;
180 my_hmmwv.SetContactMethod(ChContactMethod::SMC);
181 my_hmmwv.SetChassisFixed(false);
182 my_hmmwv.SetInitPosition(ChCoordsys<>(initLoc, initRot));
183 my_hmmwv.SetPowertrainType(PowertrainModelType::SHAFTS);
184 my_hmmwv.SetDriveType(DrivelineTypeWV::AWD);
185 switch (tire_type) {
186 case TireType::CYLINDRICAL:
187 my_hmmwv.SetTireType(TireModelType::RIGID_MESH);
188 break;
189 case TireType::LUGGED:
190 my_hmmwv.SetTireType(TireModelType::RIGID);
191 break;
192 }
193 my_hmmwv.Initialize();
194
195 my_hmmwv.SetChassisVisualizationType(VisualizationType::NONE);
196
197 // -----------------------------------------------------------
198 // Set tire contact material, contact model, and visualization
199 // -----------------------------------------------------------
200 auto wheel_material = chrono_types::make_shared<ChMaterialSurfaceSMC>();
201 wheel_material->SetFriction(mu_t);
202 wheel_material->SetYoungModulus(Y_t);
203 wheel_material->SetRestitution(cr_t);
204
205 switch (tire_type) {
206 case TireType::CYLINDRICAL:
207 my_hmmwv.SetTireVisualizationType(VisualizationType::MESH);
208 break;
209 case TireType::LUGGED:
210 my_hmmwv.SetTireVisualizationType(VisualizationType::NONE);
211 for (auto& axle : my_hmmwv.GetVehicle().GetAxles()) {
212 CreateLuggedGeometry(axle->m_wheels[0]->GetSpindle(), wheel_material);
213 CreateLuggedGeometry(axle->m_wheels[1]->GetSpindle(), wheel_material);
214 }
215 }
216
217 // --------------------
218 // Create driver system
219 // --------------------
220 MyDriver driver(my_hmmwv.GetVehicle(), 0.5);
221 driver.Initialize();
222
223 // ------------------
224 // Create the terrain
225 // ------------------
226 ChSystem* system = my_hmmwv.GetSystem();
227 system->SetNumThreads(std::min(8, ChOMP::GetNumProcs()));
228
229 SCMDeformableTerrain terrain(system);
230 terrain.SetSoilParameters(2e6, // Bekker Kphi
231 0, // Bekker Kc
232 1.1, // Bekker n exponent
233 0, // Mohr cohesive limit (Pa)
234 30, // Mohr friction limit (degrees)
235 0.01, // Janosi shear coefficient (m)
236 2e8, // Elastic stiffness (Pa/m), before plastic yield
237 3e4 // Damping (Pa s/m), proportional to negative vertical speed (optional)
238 );
239
240 ////terrain.EnableBulldozing(true); // inflate soil at the border of the rut
241 ////terrain.SetBulldozingParameters(55, // angle of friction for erosion of displaced material at rut border
242 //// 0.8, // displaced material vs downward pressed material.
243 //// 5, // number of erosion refinements per timestep
244 //// 10); // number of concentric vertex selections subject to erosion
245
246 // Optionally, enable moving patch feature (single patch around vehicle chassis)
247 terrain.AddMovingPatch(my_hmmwv.GetChassisBody(), ChVector<>(0, 0, 0), ChVector<>(5, 3, 1));
248
249 // Optionally, enable moving patch feature (multiple patches around each wheel)
250 ////for (auto& axle : my_hmmwv.GetVehicle().GetAxles()) {
251 //// terrain.AddMovingPatch(axle->m_wheels[0]->GetSpindle(), ChVector<>(0, 0, 0), ChVector<>(1, 0.5, 1));
252 //// terrain.AddMovingPatch(axle->m_wheels[1]->GetSpindle(), ChVector<>(0, 0, 0), ChVector<>(1, 0.5, 1));
253 ////}
254
255 ////terrain.SetTexture(vehicle::GetDataFile("terrain/textures/grass.jpg"), 80, 16);
256 ////terrain.SetPlotType(vehicle::SCMDeformableTerrain::PLOT_PRESSURE_YELD, 0, 30000.2);
257 terrain.SetPlotType(vehicle::SCMDeformableTerrain::PLOT_SINKAGE, 0, 0.1);
258
259 terrain.Initialize(terrainLength, terrainWidth, delta);
260
261 // ---------------------------------------
262 // Create the vehicle Irrlicht application
263 // ---------------------------------------
264 ChWheeledVehicleIrrApp app(&my_hmmwv.GetVehicle(), L"HMMWV Deformable Soil Demo");
265 app.SetSkyBox();
266 app.AddTypicalLights(irr::core::vector3df(30.f, -30.f, 100.f), irr::core::vector3df(30.f, 50.f, 100.f), 250, 130);
267 app.SetChaseCamera(trackPoint, 6.0, 0.5);
268 app.SetTimestep(step_size);
269 app.AssetBindAll();
270 app.AssetUpdateAll();
271
272 // -----------------
273 // Initialize output
274 // -----------------
275 if (!filesystem::create_directory(filesystem::path(out_dir))) {
276 std::cout << "Error creating directory " << out_dir << std::endl;
277 return 1;
278 }
279 if (img_output) {
280 if (!filesystem::create_directory(filesystem::path(img_dir))) {
281 std::cout << "Error creating directory " << img_dir << std::endl;
282 return 1;
283 }
284 }
285
286 // ---------------
287 // Simulation loop
288 // ---------------
289 std::cout << "Total vehicle mass: " << my_hmmwv.GetTotalMass() << std::endl;
290
291 // Solver settings.
292 system->SetSolverMaxIterations(50);
293
294 // Number of simulation steps between two 3D view render frames
295 int render_steps = (int)std::ceil(render_step_size / step_size);
296
297 // Initialize simulation frame counter
298 int step_number = 0;
299 int render_frame = 0;
300
301 ChTimer<> timer;
302
303 while (app.GetDevice()->run()) {
304 double time = system->GetChTime();
305
306 if (step_number == 800) {
307 std::cout << "\nstart timer at t = " << time << std::endl;
308 timer.start();
309 }
310 if (step_number == 1400) {
311 timer.stop();
312 std::cout << "stop timer at t = " << time << std::endl;
313 std::cout << "elapsed: " << timer() << std::endl;
314 std::cout << "\nSCM stats for last step:" << std::endl;
315 terrain.PrintStepStatistics(std::cout);
316 }
317
318 // Render scene
319 app.BeginScene(true, true, irr::video::SColor(255, 140, 161, 192));
320 app.DrawAll();
321 tools::drawColorbar(0, 0.1, "Sinkage", app.GetDevice(), 30);
322 app.EndScene();
323
324 if (img_output && step_number % render_steps == 0) {
325 char filename[100];
326 sprintf(filename, "%s/img_%03d.jpg", img_dir.c_str(), render_frame + 1);
327 app.WriteImageToFile(filename);
328 render_frame++;
329 }
330
331 // Driver inputs
332 ChDriver::Inputs driver_inputs = driver.GetInputs();
333
334 // Update modules
335 driver.Synchronize(time);
336 terrain.Synchronize(time);
337 my_hmmwv.Synchronize(time, driver_inputs, terrain);
338 app.Synchronize("", driver_inputs);
339
340 // Advance dynamics
341 system->DoStepDynamics(step_size);
342 app.Advance(step_size);
343
344 // Increment frame number
345 step_number++;
346 }
347
348 return 0;
349 }
350