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 // Authors: Radu Serban
13 // =============================================================================
14 //
15 // Demonstration of rendering a vehicle specified through JSON files.
16 // Uses Chrono::OpenGL and a user-specified event receiver to trigger a rebuild
17 // of the vehicle when pressing 'U'.
18 //
19 // The vehicle reference frame has Z up, X towards the front of the vehicle, and
20 // Y pointing to the left.
21 //
22 // =============================================================================
23
24 #include "chrono/physics/ChSystemSMC.h"
25
26 #include "chrono_vehicle/ChVehicleModelData.h"
27 #include "chrono_vehicle/terrain/RigidTerrain.h"
28 #include "chrono_vehicle/utils/ChUtilsJSON.h"
29 #include "chrono_vehicle/wheeled_vehicle/vehicle/WheeledVehicle.h"
30 #include "chrono_vehicle/tracked_vehicle/vehicle/TrackedVehicle.h"
31
32 #include "chrono_opengl/ChOpenGLWindow.h"
33
34 #include "chrono_thirdparty/filesystem/path.h"
35
36 using namespace chrono;
37 using namespace chrono::vehicle;
38
39 // =============================================================================
40
41 bool chassis_fixed = false;
42 bool enable_gravity = true;
43
44 std::string vehicle_file = "hmmwv/vehicle/HMMWV_Vehicle.json";
45 std::string powertrain_file = "hmmwv/powertrain/HMMWV_ShaftsPowertrain.json";
46 std::string tire_file = "hmmwv/tire/HMMWV_TMeasyTire.json";
47
48 ////std::string vehicle_file("M113/vehicle/M113_Vehicle_SinglePin.json");
49 ////std::string powertrain_file("M113/powertrain/M113_SimpleCVTPowertrain.json");
50
51 // =============================================================================
52
CreateVehicle(ChSystem * sys,bool is_wheeled)53 ChVehicle* CreateVehicle(ChSystem* sys, bool is_wheeled) {
54 if (is_wheeled) {
55 // Create the wheeled vehicle system
56 auto vehicle = new WheeledVehicle(sys, vehicle::GetDataFile(vehicle_file));
57 vehicle->Initialize(ChCoordsys<>(ChVector<>(0, 0, 0.75), QUNIT));
58 vehicle->GetChassis()->SetFixed(chassis_fixed);
59 vehicle->SetChassisVisualizationType(VisualizationType::MESH);
60 vehicle->SetSuspensionVisualizationType(VisualizationType::PRIMITIVES);
61 vehicle->SetSteeringVisualizationType(VisualizationType::PRIMITIVES);
62 vehicle->SetWheelVisualizationType(VisualizationType::MESH);
63
64 // Create and initialize the powertrain system
65 auto powertrain = ReadPowertrainJSON(vehicle::GetDataFile(powertrain_file));
66 vehicle->InitializePowertrain(powertrain);
67
68 // Create and initialize the tires
69 for (auto& axle : vehicle->GetAxles()) {
70 for (auto& wheel : axle->GetWheels()) {
71 auto tire = ReadTireJSON(vehicle::GetDataFile(tire_file));
72 vehicle->InitializeTire(tire, wheel, VisualizationType::MESH);
73 }
74 }
75
76 return vehicle;
77 } else {
78 // Create the tracked vehicle system
79 auto vehicle = new TrackedVehicle(sys, vehicle::GetDataFile(vehicle_file));
80 vehicle->Initialize(ChCoordsys<>(ChVector<>(0, 0, 0.85), QUNIT));
81 vehicle->GetChassis()->SetFixed(chassis_fixed);
82 vehicle->SetChassisVisualizationType(VisualizationType::MESH);
83 vehicle->SetSprocketVisualizationType(VisualizationType::MESH);
84 vehicle->SetIdlerVisualizationType(VisualizationType::MESH);
85 vehicle->SetRoadWheelAssemblyVisualizationType(VisualizationType::MESH);
86 vehicle->SetRoadWheelVisualizationType(VisualizationType::MESH);
87 vehicle->SetTrackShoeVisualizationType(VisualizationType::MESH);
88
89 // Create and initialize the powertrain system
90 auto powertrain = ReadPowertrainJSON(vehicle::GetDataFile(powertrain_file));
91 vehicle->InitializePowertrain(powertrain);
92
93 return vehicle;
94 }
95 }
96
97 // =============================================================================
98
99 class EventCB : public opengl::ChOpenGLEventCB {
100 public:
EventCB(ChVehicle * & vehicle,bool is_wheeled)101 EventCB(ChVehicle*& vehicle, bool is_wheeled) : m_vehicle(vehicle), m_is_wheeled(is_wheeled), m_chassis_vis(true) {}
102
CallbackKeyboard(GLFWwindow * window,int key,int scancode,int action,int mode)103 virtual bool CallbackKeyboard(GLFWwindow* window, int key, int scancode, int action, int mode) override {
104 switch (key) {
105 case 'U': {
106 std::cout << "Update..." << std::endl;
107 auto sys = m_vehicle->GetSystem();
108 delete m_vehicle;
109 m_vehicle = nullptr;
110 m_vehicle = CreateVehicle(sys, m_is_wheeled);
111 return true;
112 }
113 case 'X':
114 m_chassis_vis = !m_chassis_vis;
115 m_vehicle->SetChassisVisualizationType(m_chassis_vis ? VisualizationType::MESH
116 : VisualizationType::NONE);
117 return true;
118 default:
119 return false;
120 }
121 }
122
CallbackMouseButton(GLFWwindow * window,int button,int action,int mods)123 virtual bool CallbackMouseButton(GLFWwindow* window, int button, int action, int mods) override { return false; }
CallbackMousePos(GLFWwindow * window,double x,double y)124 virtual bool CallbackMousePos(GLFWwindow* window, double x, double y) override { return false; }
125
126 ChVehicle*& m_vehicle;
127 bool m_is_wheeled;
128 bool m_chassis_vis;
129 };
130
131 // =============================================================================
132
main(int argc,char * argv[])133 int main(int argc, char* argv[]) {
134 GetLog() << "Copyright (c) 2017 projectchrono.org\nChrono version: " << CHRONO_VERSION << "\n\n";
135
136 // Peek in vehicle JSON file and infer type
137 rapidjson::Document d;
138 ReadFileJSON(vehicle::GetDataFile(vehicle_file), d);
139 assert(!d.IsNull());
140 assert(d.HasMember("Type"));
141 assert(d.HasMember("Template"));
142 std::string type = d["Type"].GetString();
143 assert(type.compare("Vehicle") == 0);
144 std::string subtype = d["Template"].GetString();
145 bool is_wheeled = (subtype.compare("WheeledVehicle") == 0);
146
147 // Create containing system and vehicle
148 ChSystemSMC sys;
149 sys.Set_G_acc(enable_gravity ? ChVector<>(0, 0, -9.81) : VNULL);
150 auto vehicle = CreateVehicle(&sys, is_wheeled);
151
152 // (Constant) driver inputs
153 ChDriver::Inputs driver_inputs;
154 driver_inputs.m_braking = 1;
155 driver_inputs.m_steering = 0;
156 driver_inputs.m_throttle = 0;
157
158 // Create the terrain
159 RigidTerrain terrain(&sys);
160 if (enable_gravity) {
161 MaterialInfo minfo;
162 minfo.mu = 0.9f;
163 minfo.cr = 0.01f;
164 minfo.Y = 2e7f;
165 auto patch_mat = minfo.CreateMaterial(sys.GetContactMethod());
166 auto patch = terrain.AddPatch(patch_mat, ChVector<>(0, 0, 0), ChVector<>(0, 0, 1), 10, 5);
167 terrain.Initialize();
168 }
169
170 // Initialize OpenGL
171 double factor = (is_wheeled ? 3.0 : 5.0);
172 opengl::ChOpenGLWindow& gl_window = opengl::ChOpenGLWindow::getInstance();
173 gl_window.Initialize(1280, 720, "JSON visualization", &sys);
174 gl_window.SetCamera(factor * ChVector<>(-1, -1, 0.75), ChVector<>(0, 0, 0.5), ChVector<>(0, 0, 1));
175 gl_window.SetRenderMode(opengl::SOLID);
176 gl_window.EnableHUD(false);
177
178 // Attache event receiver (use key 'U' to trigger a vehicle update)
179 EventCB my_receiver(vehicle, is_wheeled);
180 gl_window.SetUserEventReceiver(&my_receiver);
181
182 // Simulation loop
183 double step_size = 2e-3;
184
185 // Dummy (not needed)
186 TerrainForces shoe_forces_left;
187 TerrainForces shoe_forces_right;
188 if (!is_wheeled) {
189 shoe_forces_left.resize(static_cast<TrackedVehicle*>(vehicle)->GetNumTrackShoes(LEFT));
190 shoe_forces_right.resize(static_cast<TrackedVehicle*>(vehicle)->GetNumTrackShoes(RIGHT));
191 }
192
193 while (gl_window.Active()) {
194 gl_window.Render();
195
196 if (!vehicle)
197 continue;
198
199 // Update modules (process inputs from other modules)
200 double time = vehicle->GetSystem()->GetChTime();
201 terrain.Synchronize(time);
202 if (is_wheeled)
203 static_cast<WheeledVehicle*>(vehicle)->Synchronize(time, driver_inputs, terrain);
204 else
205 static_cast<TrackedVehicle*>(vehicle)->Synchronize(time, driver_inputs, shoe_forces_left,
206 shoe_forces_right);
207
208 // Advance simulation for one timestep for all modules
209 terrain.Advance(step_size);
210 vehicle->Advance(step_size);
211 sys.DoStepDynamics(step_size);
212 }
213
214 delete vehicle;
215 return 0;
216 }
217