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 // Base class for a track assembly which consists of one sprocket, one idler,
16 // a collection of road wheel assemblies (suspensions), a collection of rollers,
17 // and a collection of track shoes.
18 //
19 // The reference frame for a vehicle follows the ISO standard: Z-axis up, X-axis
20 // pointing forward, and Y-axis towards the left of the vehicle.
21 //
22 // =============================================================================
23
24 #include <cmath>
25
26 #include "chrono/core/ChLog.h"
27
28 #include "chrono_vehicle/tracked_vehicle/ChTrackAssembly.h"
29
30 namespace chrono {
31 namespace vehicle {
32
ChTrackAssembly(const std::string & name,VehicleSide side)33 ChTrackAssembly::ChTrackAssembly(const std::string& name, VehicleSide side)
34 : ChPart(name),
35 m_side(side),
36 m_idler_as_cylinder(true),
37 m_roller_as_cylinder(true),
38 m_roadwheel_as_cylinder(true) {}
39
40 // -----------------------------------------------------------------------------
41 // Get the complete state for the specified track shoe.
42 // -----------------------------------------------------------------------------
GetTrackShoeState(size_t id) const43 BodyState ChTrackAssembly::GetTrackShoeState(size_t id) const {
44 BodyState state;
45
46 state.pos = GetTrackShoePos(id);
47 state.rot = GetTrackShoeRot(id);
48 state.lin_vel = GetTrackShoeLinVel(id);
49 state.ang_vel = GetTrackShoeAngVel(id);
50
51 return state;
52 }
53
54 // -----------------------------------------------------------------------------
55 // Get the complete states for all track shoes.
56 // -----------------------------------------------------------------------------
GetTrackShoeStates(BodyStates & states) const57 void ChTrackAssembly::GetTrackShoeStates(BodyStates& states) const {
58 size_t num_shoes = GetNumTrackShoes();
59 assert(states.size() == num_shoes);
60
61 for (size_t i = 0; i < num_shoes; ++i)
62 states[i] = GetTrackShoeState(i);
63 }
64
65 // -----------------------------------------------------------------------------
66 // Initialize this track assembly subsystem.
67 // -----------------------------------------------------------------------------
Initialize(std::shared_ptr<ChChassis> chassis,const ChVector<> & location,bool create_shoes)68 void ChTrackAssembly::Initialize(std::shared_ptr<ChChassis> chassis,
69 const ChVector<>& location,
70 bool create_shoes) {
71 // Initialize the sprocket, idler, and brake
72 GetSprocket()->Initialize(chassis->GetBody(), location + GetSprocketLocation(), this);
73 m_idler->Initialize(chassis->GetBody(), location + GetIdlerLocation(), this);
74 m_brake->Initialize(chassis, GetSprocket());
75
76 // Initialize the suspension subsystems
77 for (size_t i = 0; i < m_suspensions.size(); ++i) {
78 m_suspensions[i]->Initialize(chassis, location + GetRoadWhelAssemblyLocation(static_cast<int>(i)), this);
79 }
80
81 // Initialize the roller subsystems
82 for (size_t i = 0; i < m_rollers.size(); ++i) {
83 m_rollers[i]->Initialize(chassis->GetBody(), location + GetRollerLocation(static_cast<int>(i)), this);
84 }
85
86 if (!create_shoes) {
87 RemoveTrackShoes();
88 return;
89 }
90
91 // Assemble the track. This positions all track shoes around the sprocket,
92 // road wheels, and idler. (Implemented by derived classes)
93 bool ccw = Assemble(chassis->GetBody());
94
95 // Loop over all track shoes and allow them to connect themselves to their
96 // neighbor.
97 size_t num_shoes = GetNumTrackShoes();
98 std::shared_ptr<ChTrackShoe> next;
99 for (size_t i = 0; i < num_shoes; ++i) {
100 next = (i == num_shoes - 1) ? GetTrackShoe(0) : GetTrackShoe(i + 1);
101 GetTrackShoe(i)->Connect(next, this, chassis.get(), ccw);
102 }
103 }
104
105 // -----------------------------------------------------------------------------
106 // -----------------------------------------------------------------------------
SetSprocketVisualizationType(VisualizationType vis)107 void ChTrackAssembly::SetSprocketVisualizationType(VisualizationType vis) {
108 GetSprocket()->SetVisualizationType(vis);
109 }
110
SetIdlerVisualizationType(VisualizationType vis)111 void ChTrackAssembly::SetIdlerVisualizationType(VisualizationType vis) {
112 GetIdler()->SetVisualizationType(vis);
113 }
114
SetRoadWheelAssemblyVisualizationType(VisualizationType vis)115 void ChTrackAssembly::SetRoadWheelAssemblyVisualizationType(VisualizationType vis) {
116 for (size_t i = 0; i < m_suspensions.size(); ++i) {
117 m_suspensions[i]->SetVisualizationType(vis);
118 }
119 }
120
SetRoadWheelVisualizationType(VisualizationType vis)121 void ChTrackAssembly::SetRoadWheelVisualizationType(VisualizationType vis) {
122 for (size_t i = 0; i < m_suspensions.size(); ++i) {
123 m_suspensions[i]->GetRoadWheel()->SetVisualizationType(vis);
124 }
125 }
126
SetRollerVisualizationType(VisualizationType vis)127 void ChTrackAssembly::SetRollerVisualizationType(VisualizationType vis) {
128 for (size_t i = 0; i < m_rollers.size(); ++i) {
129 m_rollers[i]->SetVisualizationType(vis);
130 }
131 }
132
SetTrackShoeVisualizationType(VisualizationType vis)133 void ChTrackAssembly::SetTrackShoeVisualizationType(VisualizationType vis) {
134 SetVisualizationType(vis);
135 for (size_t i = 0; i < GetNumTrackShoes(); ++i) {
136 GetTrackShoe(i)->SetVisualizationType(vis);
137 }
138 }
139
140 // -----------------------------------------------------------------------------
141
SetWheelCollisionType(bool roadwheel_as_cylinder,bool idler_as_cylinder,bool roller_as_cylinder)142 void ChTrackAssembly::SetWheelCollisionType(bool roadwheel_as_cylinder,
143 bool idler_as_cylinder,
144 bool roller_as_cylinder) {
145 m_roadwheel_as_cylinder = roadwheel_as_cylinder;
146 m_idler_as_cylinder = idler_as_cylinder;
147 m_roller_as_cylinder = roller_as_cylinder;
148 }
149
150 // -----------------------------------------------------------------------------
151 // Calculate and return the total mass of the track assembly
152 // -----------------------------------------------------------------------------
GetMass() const153 double ChTrackAssembly::GetMass() const {
154 double mass = GetSprocket()->GetMass() + m_idler->GetMass();
155 for (size_t i = 0; i < m_suspensions.size(); i++)
156 mass += m_suspensions[i]->GetMass();
157 for (size_t i = 0; i < m_rollers.size(); i++)
158 mass += m_rollers[i]->GetMass();
159 for (size_t i = 0; i < GetNumTrackShoes(); ++i)
160 mass += GetTrackShoe(i)->GetMass();
161
162 return mass;
163 }
164
165 // -----------------------------------------------------------------------------
166 // Update the state of this track assembly at the current time.
167 // -----------------------------------------------------------------------------
Synchronize(double time,double braking,const TerrainForces & shoe_forces)168 void ChTrackAssembly::Synchronize(double time, double braking, const TerrainForces& shoe_forces) {
169 // Zero out applied torque on sprocket axle
170 GetSprocket()->m_axle->SetAppliedTorque(0.0);
171
172 // Apply track shoe forces
173 for (size_t i = 0; i < GetNumTrackShoes(); ++i) {
174 GetTrackShoe(i)->m_shoe->Empty_forces_accumulators();
175 GetTrackShoe(i)->m_shoe->Accumulate_force(shoe_forces[i].force, shoe_forces[i].point, false);
176 GetTrackShoe(i)->m_shoe->Accumulate_torque(shoe_forces[i].moment, false);
177 }
178
179 // Apply braking input
180 m_brake->Synchronize(braking);
181 }
182
183 // -----------------------------------------------------------------------------
184 // -----------------------------------------------------------------------------
SetOutput(bool state)185 void ChTrackAssembly::SetOutput(bool state) {
186 m_output = state;
187 GetSprocket()->SetOutput(state);
188 m_brake->SetOutput(state);
189 m_idler->SetOutput(state);
190 for (auto suspension : m_suspensions)
191 suspension->SetOutput(state);
192 for (auto roller : m_rollers)
193 roller->SetOutput(state);
194 if (GetNumTrackShoes() > 0)
195 GetTrackShoe(0)->SetOutput(state);
196 }
197
198 // -----------------------------------------------------------------------------
199 // -----------------------------------------------------------------------------
ExportComponentList(rapidjson::Document & jsonDocument) const200 void ChTrackAssembly::ExportComponentList(rapidjson::Document& jsonDocument) const {
201 ChPart::ExportComponentList(jsonDocument);
202
203 jsonDocument.AddMember("number shoes", static_cast<int>(GetNumTrackShoes()), jsonDocument.GetAllocator());
204
205 {
206 rapidjson::Document jsonSubDocument(&jsonDocument.GetAllocator());
207 jsonSubDocument.SetObject();
208 GetSprocket()->ExportComponentList(jsonSubDocument);
209 jsonDocument.AddMember("sprocket", jsonSubDocument, jsonDocument.GetAllocator());
210 }
211
212 {
213 rapidjson::Document jsonSubDocument(&jsonDocument.GetAllocator());
214 jsonSubDocument.SetObject();
215 m_brake->ExportComponentList(jsonSubDocument);
216 jsonDocument.AddMember("brake", jsonSubDocument, jsonDocument.GetAllocator());
217 }
218
219 {
220 rapidjson::Document jsonSubDocument(&jsonDocument.GetAllocator());
221 jsonSubDocument.SetObject();
222 m_idler->ExportComponentList(jsonSubDocument);
223 jsonDocument.AddMember("idler", jsonSubDocument, jsonDocument.GetAllocator());
224 }
225
226 rapidjson::Value suspArray(rapidjson::kArrayType);
227 for (auto suspension : m_suspensions) {
228 rapidjson::Document jsonSubDocument(&jsonDocument.GetAllocator());
229 jsonSubDocument.SetObject();
230 suspension->ExportComponentList(jsonSubDocument);
231 suspArray.PushBack(jsonSubDocument, jsonDocument.GetAllocator());
232 }
233 jsonDocument.AddMember("suspensions", suspArray, jsonDocument.GetAllocator());
234
235 rapidjson::Value rollerArray(rapidjson::kArrayType);
236 for (auto roller : m_rollers) {
237 rapidjson::Document jsonSubDocument(&jsonDocument.GetAllocator());
238 jsonSubDocument.SetObject();
239 roller->ExportComponentList(jsonSubDocument);
240 rollerArray.PushBack(jsonSubDocument, jsonDocument.GetAllocator());
241 }
242 jsonDocument.AddMember("rollers", rollerArray, jsonDocument.GetAllocator());
243
244 if (GetNumTrackShoes() > 0) {
245 rapidjson::Document jsonSubDocument(&jsonDocument.GetAllocator());
246 jsonSubDocument.SetObject();
247 GetTrackShoe(0)->ExportComponentList(jsonSubDocument);
248 jsonDocument.AddMember("shoe 0", jsonSubDocument, jsonDocument.GetAllocator());
249 }
250 }
251
252 // -----------------------------------------------------------------------------
253 // -----------------------------------------------------------------------------
Output(ChVehicleOutput & database) const254 void ChTrackAssembly::Output(ChVehicleOutput& database) const {
255 if (!m_output)
256 return;
257
258 database.WriteSection(GetSprocket()->GetName());
259 GetSprocket()->Output(database);
260
261 database.WriteSection(m_brake->GetName());
262 m_brake->Output(database);
263
264 database.WriteSection(m_idler->GetName());
265 m_idler->Output(database);
266
267 for (auto suspension : m_suspensions) {
268 database.WriteSection(suspension->GetName());
269 suspension->Output(database);
270 database.WriteSection(suspension->GetRoadWheel()->GetName());
271 suspension->GetRoadWheel()->Output(database);
272 }
273
274 for (auto roller : m_rollers) {
275 database.WriteSection(roller->GetName());
276 roller->Output(database);
277 }
278
279 if (GetNumTrackShoes() > 0) {
280 database.WriteSection(GetTrackShoe(0)->GetName());
281 GetTrackShoe(0)->Output(database);
282 }
283 }
284
285 // -----------------------------------------------------------------------------
286 // Log constraint violations
287 // -----------------------------------------------------------------------------
LogConstraintViolations()288 void ChTrackAssembly::LogConstraintViolations() {
289 GetLog() << "SPROCKET constraint violations\n";
290 GetSprocket()->LogConstraintViolations();
291 GetLog() << "IDLER constraint violations\n";
292 m_idler->LogConstraintViolations();
293 for (size_t i = 0; i < m_suspensions.size(); i++) {
294 GetLog() << "SUSPENSION #" << i << " constraint violations\n";
295 m_suspensions[i]->LogConstraintViolations();
296 }
297 for (size_t i = 0; i < m_rollers.size(); i++) {
298 GetLog() << "ROLLER #" << i << " constraint violations\n";
299 m_rollers[i]->LogConstraintViolations();
300 }
301 }
302
303 } // end namespace vehicle
304 } // end namespace chrono
305