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 // Track assembly (double-pin) model constructed from a JSON specification file
16 //
17 // =============================================================================
18 
19 #include "chrono_vehicle/tracked_vehicle/track_assembly/TrackAssemblyDoublePin.h"
20 
21 #include "chrono_vehicle/tracked_vehicle/sprocket/SprocketDoublePin.h"
22 #include "chrono_vehicle/tracked_vehicle/track_shoe/TrackShoeDoublePin.h"
23 
24 #include "chrono_vehicle/tracked_vehicle/brake/TrackBrakeSimple.h"
25 
26 #include "chrono_vehicle/tracked_vehicle/idler/SingleIdler.h"
27 #include "chrono_vehicle/tracked_vehicle/idler/DoubleIdler.h"
28 
29 #include "chrono_vehicle/tracked_vehicle/suspension/LinearDamperRWAssembly.h"
30 
31 #include "chrono_vehicle/tracked_vehicle/roller/DoubleRoller.h"
32 
33 #include "chrono_vehicle/ChVehicleModelData.h"
34 #include "chrono_vehicle/utils/ChUtilsJSON.h"
35 
36 using namespace rapidjson;
37 
38 namespace chrono {
39 namespace vehicle {
40 
41 // -----------------------------------------------------------------------------
42 // -----------------------------------------------------------------------------
ReadSprocket(const std::string & filename,int output)43 void TrackAssemblyDoublePin::ReadSprocket(const std::string& filename, int output) {
44     Document d; ReadFileJSON(filename, d);
45     if (d.IsNull())
46         return;
47 
48     // Check that the given file is a sprocket specification file.
49     assert(d.HasMember("Type"));
50     std::string type = d["Type"].GetString();
51     assert(type.compare("Sprocket") == 0);
52 
53     // Check sprocket type.
54     assert(d.HasMember("Template"));
55     std::string subtype = d["Template"].GetString();
56     assert(subtype.compare("SprocketDoublePin") == 0);
57 
58     // Create the sprocket using the appropriate template.
59     m_sprocket = chrono_types::make_shared<SprocketDoublePin>(d);
60 
61     // A non-zero value of 'output' indicates overwriting the subsystem's flag
62     if (output != 0) {
63         m_sprocket->SetOutput(output == +1);
64     }
65 
66     GetLog() << "  Loaded JSON: " << filename.c_str() << "\n";
67 }
68 
69 // -----------------------------------------------------------------------------
70 // -----------------------------------------------------------------------------
ReadTrackShoes(const std::string & filename,int num_shoes,int output)71 void TrackAssemblyDoublePin::ReadTrackShoes(const std::string& filename, int num_shoes, int output) {
72     Document d; ReadFileJSON(filename, d);
73     if (d.IsNull())
74         return;
75 
76     // Check that the given file is a track shoe specification file.
77     assert(d.HasMember("Type"));
78     std::string type = d["Type"].GetString();
79     assert(type.compare("TrackShoe") == 0);
80 
81     // Check track shoe type.
82     assert(d.HasMember("Template"));
83     std::string subtype = d["Template"].GetString();
84     assert(subtype.compare("TrackShoeDoublePin") == 0);
85 
86     // Create the track shoes using the appropriate template.
87     for (size_t it = 0; it < num_shoes; it++) {
88         m_shoes.push_back(chrono_types::make_shared<TrackShoeDoublePin>(d));
89     }
90 
91     // A non-zero value of 'output' indicates overwriting the subsystem's flag
92     if (output != 0) {
93         m_shoes[0]->SetOutput(output == +1);
94     }
95 
96     GetLog() << "  Loaded JSON: " << filename.c_str() << "\n";
97 }
98 
99 // -----------------------------------------------------------------------------
100 // -----------------------------------------------------------------------------
TrackAssemblyDoublePin(const std::string & filename)101 TrackAssemblyDoublePin::TrackAssemblyDoublePin(const std::string& filename) : ChTrackAssemblyDoublePin("", LEFT) {
102     Document d; ReadFileJSON(filename, d);
103     if (d.IsNull())
104         return;
105 
106     Create(d);
107 
108     GetLog() << "Loaded JSON: " << filename.c_str() << "\n";
109 }
110 
TrackAssemblyDoublePin(const rapidjson::Document & d)111 TrackAssemblyDoublePin::TrackAssemblyDoublePin(const rapidjson::Document& d) : ChTrackAssemblyDoublePin("", LEFT) {
112     Create(d);
113 }
114 
Create(const rapidjson::Document & d)115 void TrackAssemblyDoublePin::Create(const rapidjson::Document& d) {
116     // Invoke base class method.
117     ChPart::Create(d);
118 
119     // Create the sprocket
120     {
121         assert(d.HasMember("Sprocket"));
122         std::string file_name = d["Sprocket"]["Input File"].GetString();
123         int output = 0;
124         if (d["Sprocket"].HasMember("Output")) {
125             output = d["Sprocket"]["Output"].GetBool() ? +1 : -1;
126         }
127         ReadSprocket(vehicle::GetDataFile(file_name), output);
128         m_sprocket_loc = ReadVectorJSON(d["Sprocket"]["Location"]);
129     }
130 
131     // Create the brake
132     {
133         assert(d.HasMember("Brake"));
134         std::string file_name = d["Brake"]["Input File"].GetString();
135         m_brake = ReadTrackBrakeJSON(vehicle::GetDataFile(file_name));
136         if (d["Brake"].HasMember("Output")) {
137             m_brake->SetOutput(d["Brake"]["Output"].GetBool());
138         }
139     }
140 
141     // Create the idler
142     {
143         assert(d.HasMember("Idler"));
144         std::string file_name = d["Idler"]["Input File"].GetString();
145         m_idler = ReadIdlerJSON(vehicle::GetDataFile(file_name));
146         if (d["Idler"].HasMember("Output")) {
147             m_idler->SetOutput(d["Idler"]["Output"].GetBool());
148         }
149         m_idler_loc = ReadVectorJSON(d["Idler"]["Location"]);
150     }
151 
152     // Create the suspensions
153     assert(d.HasMember("Suspension Subsystems"));
154     assert(d["Suspension Subsystems"].IsArray());
155     m_num_susp = d["Suspension Subsystems"].Size();
156     m_suspensions.resize(m_num_susp);
157     m_susp_locs.resize(m_num_susp);
158     for (int i = 0; i < m_num_susp; i++) {
159         std::string file_name = d["Suspension Subsystems"][i]["Input File"].GetString();
160         bool has_shock = d["Suspension Subsystems"][i]["Has Shock"].GetBool();
161         m_suspensions[i] = ReadRoadWheelAssemblyJSON(vehicle::GetDataFile(file_name), has_shock);
162         if (d["Suspension Subsystems"][i].HasMember("Output")) {
163             m_suspensions[i]->SetOutput(d["Suspension Subsystems"][i]["Output"].GetBool());
164         }
165         m_susp_locs[i] = ReadVectorJSON(d["Suspension Subsystems"][i]["Location"]);
166     }
167 
168     // Create the rollers
169     m_num_rollers = 0;
170     if (d.HasMember("Rollers")) {
171         assert(d["Rollers"].IsArray());
172         m_num_rollers = d["Rollers"].Size();
173         m_rollers.resize(m_num_rollers);
174         m_roller_locs.resize(m_num_rollers);
175         for (int i = 0; i < m_num_rollers; i++) {
176             std::string file_name = d["Rollers"][i]["Input File"].GetString();
177             m_rollers[i] = ReadRollerJSON(vehicle::GetDataFile(file_name));
178             if (d["Rollers"][i].HasMember("Output")) {
179                 m_rollers[i]->SetOutput(d["Rollers"][i]["Output"].GetBool());
180             }
181             m_roller_locs[i] = ReadVectorJSON(d["Rollers"][i]["Location"]);
182         }
183     }
184 
185     // Create the track shoes
186     {
187         assert(d.HasMember("Track Shoes"));
188         std::string file_name = d["Track Shoes"]["Input File"].GetString();
189         int output = 0;
190         if (d["Track Shoes"].HasMember("Output")) {
191             output = d["Track Shoes"]["Output"].GetBool() ? +1 : -1;
192         }
193         m_num_track_shoes = d["Track Shoes"]["Number Shoes"].GetInt();
194         ReadTrackShoes(vehicle::GetDataFile(file_name), m_num_track_shoes, output);
195 
196         if (d["Track Shoes"].HasMember("RSDA Data")) {
197             double k = d["Track Shoes"]["RSDA Data"]["Stiffness Rotational"].GetDouble();
198             double c = d["Track Shoes"]["RSDA Data"]["Damping Rotational"].GetDouble();
199             m_torque_funct = chrono_types::make_shared<ChTrackAssemblySegmented::TrackBendingFunctor>(k, c);
200         }
201 
202         if (d["Track Shoes"].HasMember("Bushing Data")) {
203             m_bushing_data = ReadBushingDataJSON(d["Track Shoes"]["Bushing Data"]);
204         }
205     }
206 }
207 
208 }  // end namespace vehicle
209 }  // end namespace chrono
210