sae/
lib.rs

1mod constants;
2mod utils;
3
4const V_CAR: f64 = 26.8;
5const W_E: f64 = 3600.0 * 2.0 * std::f64::consts::PI / 60.0;
6const RHO_AIR: f64 = 1.225;
7const R_TRACK: f64 = 9.0;
8const P_BRAKE: f64 = 10_000_000.0;
9const C_DC: f64 = 0.04;
10const GRAVITY: f64 = 9.81;
11const Y_SUSPENSION: f64 = 0.05;
12const DYDT_SUSPENSION: f64 = 0.025;
13
14// Weights
15const EVEN_WEIGHTS: [f64; 11] = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0];
16const WEIGHTS1: [i32; 11] = [14, 1, 20, 30, 10, 1, 1, 10, 10, 2, 1]; // TODO: Make f64
17const WEIGHTS2: [i32; 11] = [25, 1, 15, 20, 15, 1, 1, 15, 5, 1, 1]; // TODO: Make f64
18const WEIGHTS3: [i32; 11] = [14, 1, 20, 15, 25, 1, 1, 10, 10, 2, 1]; // TODO: Make f64
19
20#[derive(Default)]
21pub struct Car {
22    rear_wing_height: f64,
23    rear_wing_length: f64,
24    rear_wing_angle_of_attack: f64,
25    front_wing_height: f64,
26    front_wing_length: f64,
27    front_wing_width: f64,
28    front_wing_angle_of_attack: f64,
29    side_wings_height: f64,
30    side_wings_length: f64,
31    side_wings_width: f64,
32    side_wings_angle_of_attack: f64,
33    rear_tire_pressure: f64,
34    front_tire_pressure: f64,
35    cabin_height: f64,
36    cabin_length: f64,
37    cabin_width: f64,
38    cabin_thickness: f64,
39    impact_attenuator_height: f64,
40    impact_attenuator_width: f64,
41    rear_wing_density: f64,
42    front_wing_density: f64,
43    side_wing_density: f64,
44    cabin_density: f64,
45    impact_attenuator_density: f64,
46    impact_attenuator_modulus: f64,
47    rear_tire_radius: f64,
48    rear_tire_mass: f64,
49    front_tire_radius: f64,
50    front_tire_mass: f64,
51    engine_power: f64,
52    engine_length: f64,
53    engine_height: f64,
54    engine_torque: f64,
55    engine_mass: f64,
56    brake_radius: f64,
57    brake_density: f64,
58    brake_length: f64,
59    brake_height: f64,
60    brake_width: f64,
61    brake_thickness: f64,
62    rear_suspension_spring_constant: f64,
63    rear_suspension_damping_coefficient: f64,
64    rear_suspension_mass: f64,
65    front_suspension_spring_constant: f64,
66    front_suspension_damping_coefficient: f64,
67    front_suspension_mass: f64,
68    rear_wing_width: f64,
69    rear_wing_y_position: f64,
70    front_wing_y_position: f64,
71    side_wing_y_position: f64,
72    engine_y_position: f64,
73    cabin_y_position: f64,
74    impact_attenuator_length: f64,
75    impact_attenuator_y_position: f64,
76    rear_suspension_y_position: f64,
77    front_suspension_y_position: f64,
78}
79
80impl Car {
81    pub fn new() -> Self {
82        // Get libraries
83        let tires = constants::get_tires();
84        let brakes = constants::get_brakes();
85        let motors = constants::get_motors();
86        let materials = constants::get_materials();
87        let suspensions = constants::get_suspensions();
88
89        // Define indicates
90        let rear_tire_index = utils::multinomial_draw(vec![1.0; tires.len()]);
91        let front_tire_index = utils::multinomial_draw(vec![1.0; tires.len()]);
92        let brake_index = utils::multinomial_draw(vec![1.0; brakes.len()]);
93        let motor_index = utils::multinomial_draw(vec![1.0; motors.len()]);
94        let suspension_index = utils::multinomial_draw(vec![1.0; suspensions.len()]);
95        let rear_wing_material_index = utils::multinomial_draw(vec![1.0; materials.len()]);
96        let front_wing_material_index = utils::multinomial_draw(vec![1.0; materials.len()]);
97        let side_wing_material_index = utils::multinomial_draw(vec![1.0; materials.len()]);
98        let cabin_material_index = utils::multinomial_draw(vec![1.0; materials.len()]);
99        let impact_attenuator_material_index = utils::multinomial_draw(vec![1.0; materials.len()]);
100
101        // Variables used in multiple places
102        let impact_attenuator_height = utils::random_uniform(
103            constants::CONST_BOUNDS[17][0],
104            constants::CONST_BOUNDS[17][1],
105        );
106        let front_wing_length =
107            utils::random_uniform(constants::CONST_BOUNDS[4][0], constants::CONST_BOUNDS[4][1]);
108        let cabin_height = utils::random_uniform(
109            constants::CONST_BOUNDS[13][0],
110            constants::CONST_BOUNDS[13][1],
111        );
112        let rear_wing_height =
113            utils::random_uniform(constants::CONST_BOUNDS[0][0], constants::CONST_BOUNDS[0][1]);
114        let front_wing_height =
115            utils::random_uniform(constants::CONST_BOUNDS[3][0], constants::CONST_BOUNDS[3][1]);
116        let side_wings_height =
117            utils::random_uniform(constants::CONST_BOUNDS[7][0], constants::CONST_BOUNDS[7][1]);
118
119        Car {
120            // Parameters with uniform bounds
121            rear_wing_height,
122            rear_wing_length: utils::random_uniform(
123                constants::CONST_BOUNDS[1][0],
124                constants::CONST_BOUNDS[1][1],
125            ),
126            rear_wing_angle_of_attack: utils::random_uniform(
127                constants::CONST_BOUNDS[2][0],
128                constants::CONST_BOUNDS[2][1],
129            ),
130            front_wing_height,
131            front_wing_length,
132            front_wing_width: utils::random_uniform(
133                constants::CONST_BOUNDS[5][0],
134                constants::CONST_BOUNDS[5][1],
135            ),
136            front_wing_angle_of_attack: utils::random_uniform(
137                constants::CONST_BOUNDS[6][0],
138                constants::CONST_BOUNDS[6][1],
139            ),
140            side_wings_height,
141            side_wings_length: utils::random_uniform(
142                constants::CONST_BOUNDS[8][0],
143                constants::CONST_BOUNDS[8][1],
144            ),
145            side_wings_width: utils::random_uniform(
146                constants::CONST_BOUNDS[9][0],
147                constants::CONST_BOUNDS[9][1],
148            ),
149            side_wings_angle_of_attack: utils::random_uniform(
150                constants::CONST_BOUNDS[10][0],
151                constants::CONST_BOUNDS[10][1],
152            ),
153            rear_tire_pressure: utils::random_uniform(
154                constants::CONST_BOUNDS[11][0],
155                constants::CONST_BOUNDS[11][1],
156            ),
157            front_tire_pressure: utils::random_uniform(
158                constants::CONST_BOUNDS[12][0],
159                constants::CONST_BOUNDS[12][1],
160            ),
161            cabin_height,
162            cabin_length: utils::random_uniform(
163                constants::CONST_BOUNDS[14][0],
164                constants::CONST_BOUNDS[14][1],
165            ),
166            cabin_width: utils::random_uniform(
167                constants::CONST_BOUNDS[15][0],
168                constants::CONST_BOUNDS[15][1],
169            ),
170            cabin_thickness: utils::random_uniform(
171                constants::CONST_BOUNDS[16][0],
172                constants::CONST_BOUNDS[16][1],
173            ),
174            impact_attenuator_height,
175            impact_attenuator_width: utils::random_uniform(
176                constants::CONST_BOUNDS[18][0],
177                constants::CONST_BOUNDS[18][1],
178            ),
179
180            // Parameters based on lookup from indices
181            rear_wing_density: materials[&rear_wing_material_index]["density"],
182            front_wing_density: materials[&front_wing_material_index]["density"],
183            side_wing_density: materials[&side_wing_material_index]["density"],
184            cabin_density: materials[&cabin_material_index]["density"],
185            impact_attenuator_density: materials[&impact_attenuator_material_index]["density"],
186            impact_attenuator_modulus: materials[&impact_attenuator_material_index]["modulus"],
187            rear_tire_radius: tires[&rear_tire_index]["radius"],
188            rear_tire_mass: tires[&rear_tire_index]["mass"],
189            front_tire_radius: tires[&front_tire_index]["radius"],
190            front_tire_mass: tires[&front_tire_index]["mass"],
191            engine_power: motors[&motor_index]["power"],
192            engine_length: motors[&motor_index]["length"],
193            engine_height: motors[&motor_index]["height"],
194            engine_torque: motors[&motor_index]["torque"],
195            engine_mass: motors[&motor_index]["mass"],
196            brake_radius: brakes[&brake_index]["radius"],
197            brake_density: brakes[&brake_index]["density"],
198            brake_length: brakes[&brake_index]["length"],
199            brake_height: brakes[&brake_index]["height"],
200            brake_width: brakes[&brake_index]["width"],
201            brake_thickness: brakes[&brake_index]["thickness"],
202            rear_suspension_spring_constant: suspensions[&suspension_index]["spring_constant"],
203            rear_suspension_damping_coefficient: suspensions[&suspension_index]
204                ["damping_coefficient"],
205            rear_suspension_mass: suspensions[&suspension_index]["mass"],
206            front_suspension_spring_constant: suspensions[&suspension_index]["spring_constant"],
207            front_suspension_damping_coefficient: suspensions[&suspension_index]
208                ["damping_coefficient"],
209            front_suspension_mass: suspensions[&suspension_index]["mass"],
210
211            // Parameters with variables bounds
212            rear_wing_width: utils::random_uniform(
213                0.3,
214                9.0 - 2.0 * tires[&rear_tire_index]["radius"],
215            ),
216            rear_wing_y_position: utils::random_uniform(
217                0.5 + rear_wing_height / 2.0,
218                1.2 - rear_wing_height / 2.0,
219            ),
220            front_wing_y_position: utils::random_uniform(
221                0.03 + front_wing_height,
222                0.25 - rear_wing_height / 2.0,
223            ),
224            side_wing_y_position: utils::random_uniform(
225                0.03 + side_wings_height / 2.0,
226                0.25 - side_wings_height / 2.0,
227            ),
228            engine_y_position: utils::random_uniform(
229                0.03 + motors[&motor_index]["height"] / 2.0,
230                0.5 - motors[&motor_index]["height"] / 2.0,
231            ),
232            cabin_y_position: utils::random_uniform(
233                0.03 + cabin_height / 2.0,
234                1.2 - cabin_height / 2.0,
235            ),
236            impact_attenuator_length: utils::random_uniform(0.2, 0.7 - front_wing_length),
237            impact_attenuator_y_position: utils::random_uniform(
238                0.03 + impact_attenuator_height / 2.0,
239                1.2 - impact_attenuator_height / 2.0,
240            ),
241            rear_suspension_y_position: utils::random_uniform(
242                tires[&rear_tire_index]["radius"],
243                2.0 * tires[&rear_tire_index]["radius"],
244            ),
245            front_suspension_y_position: utils::random_uniform(
246                tires[&front_tire_index]["radius"],
247                2.0 * tires[&front_tire_index]["radius"],
248            ),
249        }
250    }
251
252    pub fn new_from_parameters(p: &Vec<f64>) -> Self {
253        // Get libraries
254        let tires = constants::get_tires();
255        let brakes = constants::get_brakes();
256        let motors = constants::get_motors();
257        let materials = constants::get_materials();
258        let suspensions = constants::get_suspensions();
259
260        // Pull out indices
261        let rear_wing_material_index = p[19] as usize;
262        let front_wing_material_index = p[20] as usize;
263        let side_wing_material_index = p[21] as usize;
264        let cabin_material_index = p[22] as usize;
265        let impact_attenuator_material_index = p[23] as usize;
266        let rear_tire_index = p[24] as usize;
267        let front_tire_index = p[25] as usize;
268        let brake_index = p[26] as usize;
269        let motor_index = p[27] as usize;
270        let suspension_index = p[28] as usize;
271
272        Car {
273            rear_wing_height: p[0],
274            rear_wing_length: p[1],
275            rear_wing_angle_of_attack: p[2],
276            front_wing_height: p[3],
277            front_wing_length: p[4],
278            front_wing_width: p[5],
279            front_wing_angle_of_attack: p[6],
280            side_wings_height: p[7],
281            side_wings_length: p[8],
282            side_wings_width: p[9],
283            side_wings_angle_of_attack: p[10],
284            rear_tire_pressure: p[11],
285            front_tire_pressure: p[12],
286            cabin_height: p[13],
287            cabin_length: p[14],
288            cabin_width: p[15],
289            cabin_thickness: p[16],
290            impact_attenuator_height: p[17],
291            impact_attenuator_width: p[18],
292            rear_wing_density: materials[&rear_wing_material_index]["density"],
293            front_wing_density: materials[&front_wing_material_index]["density"],
294            side_wing_density: materials[&side_wing_material_index]["density"],
295            cabin_density: materials[&cabin_material_index]["density"],
296            impact_attenuator_density: materials[&impact_attenuator_material_index]["density"],
297            impact_attenuator_modulus: materials[&impact_attenuator_material_index]["modulus"],
298            rear_tire_radius: tires[&rear_tire_index]["radius"],
299            rear_tire_mass: tires[&rear_tire_index]["mass"],
300            front_tire_radius: tires[&front_tire_index]["radius"],
301            front_tire_mass: tires[&front_tire_index]["mass"],
302            engine_power: motors[&motor_index]["power"],
303            engine_length: motors[&motor_index]["length"],
304            engine_height: motors[&motor_index]["height"],
305            engine_torque: motors[&motor_index]["torque"],
306            engine_mass: motors[&motor_index]["mass"],
307            brake_radius: brakes[&brake_index]["radius"],
308            brake_density: brakes[&brake_index]["density"],
309            brake_length: brakes[&brake_index]["length"],
310            brake_height: brakes[&brake_index]["height"],
311            brake_width: brakes[&brake_index]["width"],
312            brake_thickness: brakes[&brake_index]["thickness"],
313            rear_suspension_spring_constant: suspensions[&suspension_index]["spring_constant"],
314            rear_suspension_damping_coefficient: suspensions[&suspension_index]
315                ["damping_coefficient"],
316            rear_suspension_mass: suspensions[&suspension_index]["mass"],
317            front_suspension_spring_constant: suspensions[&suspension_index]["spring_constant"],
318            front_suspension_damping_coefficient: suspensions[&suspension_index]
319                ["damping_coefficient"],
320            front_suspension_mass: suspensions[&suspension_index]["mass"],
321            rear_wing_width: p[29],
322            rear_wing_y_position: p[30],
323            front_wing_y_position: p[31],
324            side_wing_y_position: p[32],
325            engine_y_position: p[33],
326            cabin_y_position: p[34],
327            impact_attenuator_length: p[35],
328            impact_attenuator_y_position: p[36],
329            rear_suspension_y_position: p[37],
330            front_suspension_y_position: p[38],
331        }
332    }
333
334    pub fn objective(&self, weights: [f64; 11]) -> f64 {
335        weights[0] * self.mass()
336            + weights[1] * self.center_of_gravity()
337            + weights[2] * self.drag_force()
338            + weights[3] * self.downward_force()
339            + weights[4] * self.acceleration()
340            + weights[5] * self.crash_force()
341            + weights[6] * self.impact_attenuator_volume()
342            + weights[7] * self.corner_velocity()
343            + weights[8] * self.brakeing_distance()
344            + weights[9] * self.suspension_acceleration()
345            + weights[10] * self.pitch_moment()
346    }
347
348    pub fn objectives(&self) -> [f64; 11] {
349        [
350            self.mass(),
351            self.center_of_gravity(),
352            self.drag_force(),
353            self.downward_force(),
354            self.acceleration(),
355            self.crash_force(),
356            self.impact_attenuator_volume(),
357            self.corner_velocity(),
358            self.brakeing_distance(),
359            self.suspension_acceleration(),
360            self.pitch_moment(),
361        ]
362    }
363
364    pub fn check_bounds(&self) -> Vec<f64> {
365        todo!()
366    }
367
368    pub fn check_nonlinear_constraints(&self) -> Vec<f64> {
369        todo!()
370    }
371
372    pub fn check_linear_constraints(&self) -> Vec<f64> {
373        todo!()
374    }
375
376    pub fn center_of_gravity(&self) -> f64 {
377        let total_mass = self.mass();
378        let t1 = (self.mass_rear_wing() * self.rear_wing_y_position
379            + self.mass_front_wing() * self.front_wing_y_position
380            + self.engine_mass * self.engine_y_position
381            + self.mass_cabin() * self.cabin_y_position
382            + self.mass_impact_attenuator() * self.impact_attenuator_y_position)
383            / total_mass;
384        let t2 = 2.0
385            * (self.mass_side_wings() * self.side_wing_y_position
386                + self.rear_tire_mass * self.rear_tire_radius
387                + self.front_tire_mass * self.front_tire_radius
388                + self.mass_brake() * self.front_tire_radius
389                + self.rear_suspension_mass * self.rear_suspension_y_position
390                + self.front_suspension_mass * self.front_suspension_y_position)
391            / total_mass;
392        return t1 + t2;
393    }
394
395    pub fn drag_force(&self) -> f64 {
396        todo!()
397    }
398
399    pub fn downward_force(&self) -> f64 {
400        todo!()
401    }
402
403    pub fn acceleration(&self) -> f64 {
404        todo!()
405    }
406    pub fn crash_force(&self) -> f64 {
407        todo!()
408    }
409    pub fn impact_attenuator_volume(&self) -> f64 {
410        todo!()
411    }
412    pub fn corner_velocity(&self) -> f64 {
413        todo!()
414    }
415    pub fn brakeing_distance(&self) -> f64 {
416        todo!()
417    }
418    pub fn suspension_acceleration(&self) -> f64 {
419        todo!()
420    }
421    pub fn pitch_moment(&self) -> f64 {
422        todo!()
423    }
424
425    pub fn mass(&self) -> f64 {
426        self.mass_rear_wing()
427            + self.mass_front_wing()
428            + 2.0 * self.mass_side_wings()
429            + 2.0 * self.rear_tire_mass
430            + 2.0 * self.front_tire_mass
431            + self.engine_mass
432            + self.mass_cabin()
433            + self.mass_impact_attenuator()
434            + 4.0 * self.mass_brake()
435            + 2.0 * self.rear_suspension_mass
436            + 2.0 * self.front_suspension_mass
437    }
438
439    fn mass_rear_wing(&self) -> f64 {
440        self.rear_wing_length
441            * self.rear_wing_width
442            * self.rear_wing_height
443            * self.rear_wing_density
444    }
445
446    fn mass_front_wing(&self) -> f64 {
447        self.front_wing_length
448            * self.front_wing_width
449            * self.front_wing_height
450            * self.front_wing_density
451    }
452
453    fn mass_side_wings(&self) -> f64 {
454        self.side_wings_length
455            * self.side_wings_width
456            * self.side_wings_height
457            * self.side_wing_density
458    }
459    fn mass_impact_attenuator(&self) -> f64 {
460        self.impact_attenuator_length
461            * self.impact_attenuator_width
462            * self.impact_attenuator_height
463            * self.impact_attenuator_density
464    }
465    fn mass_cabin(&self) -> f64 {
466        2.0 * (self.cabin_height * self.cabin_length * self.cabin_thickness
467            + self.cabin_height * self.cabin_width * self.cabin_thickness
468            + self.cabin_length * self.cabin_height * self.cabin_thickness)
469            * self.cabin_density
470    }
471    fn mass_brake(&self) -> f64 {
472        self.brake_length * self.brake_width * self.brake_height * self.brake_density
473    }
474}
475
476impl argmin::prelude::ArgminOp for Car {
477    type Param = Vec<f64>;
478    type Output = f64;
479    type Hessian = ();
480    type Jacobian = ();
481    type Float = f64;
482
483    fn apply(&self, param: &Self::Param) -> Result<Self::Output, argmin::prelude::Error> {
484        Ok(Car::new_from_parameters(param).objective(EVEN_WEIGHTS))
485    }
486}
487
488impl std::fmt::Display for Car {
489    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
490        todo!()
491    }
492}
493
494#[cfg(test)]
495mod tests {
496    use super::*;
497
498    #[test]
499    fn internal() {
500        let cost = Car::new();
501        println!("{:?}", cost.objective(EVEN_WEIGHTS));
502        // let init_param: Vec<f64> = vec![0.0; 39];
503        // let line_search = argmin::solver::linesearch::MoreThuenteLineSearch::new();
504        // let solver = argmin::solver::gradientdescent::SteepestDescent::new(line_search);
505        // let res = argmin::prelude::Executor::new(cost, solver, init_param)
506        //     .add_observer(
507        //         argmin::prelude::ArgminSlogLogger::term(),
508        //         argmin::prelude::ObserverMode::Always,
509        //     )
510        //     .max_iters(10)
511        //     .run()?;
512    }
513}