1 // =============================================================================
2 // PROJECT CHRONO - http://projectchrono.org
3 //
4 // Copyright (c) 2019 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 // Authors: Radu Serban
13 // =============================================================================
14 //
15 // Tractor-trailer acceleration test.
16 //
17 // The vehicle reference frame has Z up, X towards the front of the vehicle, and
18 // Y pointing to the left.
19 //
20 // =============================================================================
21 
22 #include <cmath>
23 
24 #include "chrono/ChConfig.h"
25 #include "chrono/utils/ChFilters.h"
26 #include "chrono/utils/ChUtilsInputOutput.h"
27 #include "chrono/core/ChTimer.h"
28 
29 #include "chrono_vehicle/ChConfigVehicle.h"
30 #include "chrono_vehicle/ChVehicleModelData.h"
31 #include "chrono_vehicle/driver/ChPathFollowerDriver.h"
32 #include "chrono_vehicle/terrain/RigidTerrain.h"
33 #include "chrono_vehicle/utils/ChVehiclePath.h"
34 #include "chrono_vehicle/wheeled_vehicle/utils/ChWheeledVehicleIrrApp.h"
35 
36 #include "chrono_models/vehicle/kraz/Kraz.h"
37 
38 #ifdef CHRONO_POSTPROCESS
39 #include "chrono_postprocess/ChGnuPlot.h"
40 #endif
41 
42 using namespace chrono;
43 using namespace chrono::irrlicht;
44 using namespace chrono::vehicle;
45 using namespace chrono::vehicle::kraz;
46 
47 // =============================================================================
48 
49 // Visualization type for vehicle parts (PRIMITIVES, MESH, or NONE)
50 VisualizationType chassis_vis_type = VisualizationType::MESH;
51 VisualizationType suspension_vis_type = VisualizationType::PRIMITIVES;
52 VisualizationType steering_vis_type = VisualizationType::PRIMITIVES;
53 VisualizationType wheel_vis_type = VisualizationType::MESH;
54 VisualizationType tire_vis_type = VisualizationType::MESH;
55 
56 // Terrain length (X direction)
57 double terrainLength = 300.0;
58 
59 // Simulation step sizes
60 double step_size = 1e-3;
61 double tire_step_size = 1e-3;
62 
63 // Initial vehicle position
64 ChVector<> initLoc(0, 0, 0.6);
65 
66 // =============================================================================
67 
main(int argc,char * argv[])68 int main(int argc, char* argv[]) {
69     GetLog() << "Copyright (c) 2017 projectchrono.org\nChrono version: " << CHRONO_VERSION << "\n\n";
70 
71     // Create the semi-trailer truck
72     Kraz truck;
73     truck.SetContactMethod(ChContactMethod::NSC);
74     truck.SetChassisFixed(false);
75     truck.SetInitPosition(ChCoordsys<>(initLoc, QUNIT));
76     truck.SetTireStepSize(tire_step_size);
77     truck.SetInitFwdVel(0.0);
78 
79     truck.Initialize();
80 
81     truck.SetChassisVisualizationType(VisualizationType::MESH, VisualizationType::PRIMITIVES);
82     truck.SetSteeringVisualizationType(VisualizationType::PRIMITIVES);
83     truck.SetSuspensionVisualizationType(VisualizationType::PRIMITIVES, VisualizationType::PRIMITIVES);
84     truck.SetWheelVisualizationType(VisualizationType::MESH, VisualizationType::MESH);
85     truck.SetTireVisualizationType(VisualizationType::MESH, VisualizationType::MESH);
86 
87     // Create the terrain
88     RigidTerrain terrain(truck.GetSystem());
89     auto patch_mat = chrono_types::make_shared<ChMaterialSurfaceSMC>();
90     patch_mat->SetFriction(0.9f);
91     patch_mat->SetRestitution(0.01f);
92     patch_mat->SetYoungModulus(2e7f);
93     patch_mat->SetPoissonRatio(0.3f);
94     for (size_t i = 0; i < 3; i++) {
95         auto patch =
96             terrain.AddPatch(patch_mat, ChVector<>(terrainLength * i, 0, 0), ChVector<>(0, 0, 1), terrainLength, 5);
97         patch->SetColor(ChColor(0.8f, 0.8f, 0.5f));
98         patch->SetTexture(vehicle::GetDataFile("terrain/textures/tile4.jpg"), 200, 5);
99     }
100     terrain.Initialize();
101 
102     // Create the vehicle Irrlicht interface
103     ChWheeledVehicleIrrApp app(&truck.GetTractor(), L"Semi-trailer truck :: Follows Straight Line");
104     app.SetSkyBox();
105     app.AddTypicalLights(irr::core::vector3df(30.f, -30.f, 100.f), irr::core::vector3df(30.f, 50.f, 100.f), 250, 130);
106     app.SetChaseCamera(ChVector<>(0.0, 0.0, 1.75), 6.0, 0.5);
107     app.SetTimestep(step_size);
108 
109     // Create the straight path and the driver system
110     auto path = StraightLinePath(ChVector<>(-terrainLength / 2, 0, 0.5), ChVector<>(10 * terrainLength / 2, 0, 0.5), 1);
111     ChPathFollowerDriver driver(truck.GetTractor(), path, "my_path", 1000.0);
112     driver.GetSteeringController().SetLookAheadDistance(5.0);
113     driver.GetSteeringController().SetGains(0.5, 0, 0);
114     driver.GetSpeedController().SetGains(0.4, 0, 0);
115     driver.Initialize();
116 
117     // ---------------------------------------------
118     // Finalize construction of visualization assets
119     // ---------------------------------------------
120 
121     app.AssetBindAll();
122     app.AssetUpdateAll();
123 
124     // ---------------
125     // Simulation loop
126     // ---------------
127 
128     // Running average of vehicle speed
129     utils::ChRunningAverage speed_filter(500);
130     double last_speed = -1;
131 
132     // Record vehicle speed
133     ChFunction_Recorder speed_recorder;
134 
135     // Initialize simulation frame counter and simulation time
136     int step_number = 0;
137     double time = 0;
138     bool done = false;
139 
140     ChTimer<> timer;
141     timer.start();
142     while (app.GetDevice()->run()) {
143         time = truck.GetSystem()->GetChTime();
144 
145         double speed = speed_filter.Add(truck.GetTractor().GetVehicleSpeed());
146         if (!done) {
147             speed_recorder.AddPoint(time, speed);
148             if (time > 6 && std::abs((speed - last_speed) / step_size) < 2e-4) {
149                 done = true;
150                 timer.stop();
151                 std::cout << "Simulation time: " << timer() << std::endl;
152                 std::cout << "Maximum speed: " << speed << std::endl;
153 #ifdef CHRONO_POSTPROCESS
154                 postprocess::ChGnuPlot gplot;
155                 gplot.SetGrid();
156                 gplot.SetLabelX("time (s)");
157                 gplot.SetLabelY("speed (m/s)");
158                 gplot.Plot(speed_recorder, "", " with lines lt -1 lc rgb'#00AAEE' ");
159 #endif
160             }
161         }
162         last_speed = speed;
163 
164         // End simulation
165         if (time >= 100)
166             break;
167 
168         app.BeginScene(true, true, irr::video::SColor(255, 140, 161, 192));
169         app.DrawAll();
170 
171         // Driver inputs
172         ChDriver::Inputs driver_inputs = driver.GetInputs();
173 
174         if (done) {
175             driver_inputs.m_throttle = 0.1;
176             driver_inputs.m_braking = 0.8;
177         }
178 
179         // Update modules (process inputs from other modules)
180         driver.Synchronize(time);
181         terrain.Synchronize(time);
182         truck.Synchronize(time, driver_inputs, terrain);
183         app.Synchronize("Acceleration test", driver_inputs);
184 
185         // Advance simulation for one timestep for all modules
186         driver.Advance(step_size);
187         terrain.Advance(step_size);
188         truck.Advance(step_size);
189         app.Advance(step_size);
190 
191         // Increment frame number
192         step_number++;
193 
194         app.EndScene();
195     }
196 
197     return 0;
198 }
199