00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <vamos/geometry/Conversions.h>
00022 #include <vamos/body/Suspension.h>
00023
00024 #include <cmath>
00025 #include <cassert>
00026
00027 using namespace Vamos_Geometry;
00028
00029
00030
00031
00032 const Three_Vector Vamos_Body::Suspension::
00033 STEER_AXIS = Three_Vector (0.0, 0.0, 1.0);
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 Vamos_Body::
00044 Hinge::Hinge (const Three_Vector& position) :
00045 Particle (0.0, position)
00046 {
00047 }
00048
00049 void Vamos_Body::
00050 Hinge::input (const Three_Vector& torque, const Three_Vector& radius)
00051 {
00052 double t_magnitude = sqrt(torque[0]*torque[0]+torque[1]*torque[1]+torque[2]*torque[2]);
00053 double r_magnitude = sqrt(radius[0]*radius[0]+radius[1]*radius[1]+radius[2]*radius[2]);
00054 m_force = t_magnitude
00055 / r_magnitude * (torque.cross (radius).unit ());
00056 }
00057
00058
00059 struct Vamos_Body::Suspension_Model
00060 {
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 };
00074
00075
00076
00077
00078 Vamos_Body::
00079 Suspension::Suspension (const Three_Vector& position,
00080 const Three_Vector& center_of_translation,
00081 Side side_of_car, double spring_constant,
00082 double bounce, double rebound, double travel,
00083 double max_compression_velocity) :
00084 Particle (0.0, position),
00085 mp_hinge (new Hinge (center_of_translation)),
00086 m_initial_z (position[2]),
00087 m_spring_constant (spring_constant),
00088 m_bounce (bounce),
00089 m_rebound (rebound),
00090 m_travel (travel),
00091 m_displacement (0.0),
00092 m_time_step (0.0),
00093 m_compression_velocity (0.0),
00094 m_max_compression_velocity (max_compression_velocity),
00095 m_bottomed_out (false),
00096 m_anti_roll_k (0.0),
00097 m_anti_roll_suspension (0),
00098 m_steer_angle (0.0),
00099 m_camber (0.0),
00100 m_caster (0.0),
00101 m_toe (0.0),
00102 m_side (side_of_car),
00103 m_normal (Three_Vector (0.0, 0.0, 1.0))
00104 {
00105 m_static_orientation.identity ();
00106
00107
00108 m_radius = center_of_translation - m_position;
00109
00110
00111
00112 m_radius_magnitude = m_radius.magnitude ();
00113 }
00114
00115
00116 Vamos_Body::
00117 Suspension::~Suspension ()
00118 {
00119
00120
00121
00122
00123
00124
00125 }
00126
00127
00128
00129
00130 void Vamos_Body::
00131 Suspension::anti_roll (Suspension* other, double spring_constant)
00132 {
00133 m_anti_roll_suspension = other;
00134 m_anti_roll_k = spring_constant;
00135
00136 m_anti_roll_suspension->m_anti_roll_suspension = this;
00137 m_anti_roll_suspension->m_anti_roll_k = m_anti_roll_k;
00138 }
00139
00140
00141
00142 void Vamos_Body::Suspension::
00143 displace (double distance)
00144 {
00145 double last_displacement = m_displacement;
00146 m_displacement = distance;
00147 if (m_displacement > m_travel)
00148 {
00149 m_bottomed_out = true;
00150
00151
00152 }
00153 else
00154 {
00155 m_bottomed_out = false;
00156 }
00157
00158
00159
00160 const Three_Vector& hinge_pos = mp_hinge->position ();
00161 double z = hinge_pos[2] - m_initial_z - m_displacement;
00162 assert (z <= m_radius_magnitude);
00163 m_angle = asin (z / m_radius_magnitude);
00164
00165 if (hinge_pos[0] > m_position[0])
00166 {
00167 m_angle = pi - m_angle;
00168 }
00169
00170
00171
00172 Three_Vector new_position = hinge_pos
00173 + m_radius_magnitude * Three_Vector (cos (m_angle), 0.0, -sin (m_angle));
00174 m_position[0] = new_position[0];
00175 m_position[2] = new_position[2];
00176
00177
00178 m_radius = hinge_pos - m_position;
00179
00180
00181
00182 m_tangent = Three_Vector (-m_radius[2], 0.0, m_radius[0]).unit ();
00183
00184 m_compression_velocity = (m_displacement - last_displacement) / m_time_step;
00185 }
00186
00187 void Vamos_Body::
00188 Suspension::input (const Three_Vector& wheel_force,
00189 const Three_Vector& normal)
00190 {
00191 m_wheel_force = wheel_force;
00192 m_normal = rotate_out (normal);
00193 }
00194
00195 void Vamos_Body::
00196 Suspension::torque (double wheel_torque)
00197 {
00198 mp_hinge->input (Three_Vector (0.0, -wheel_torque, 0.0), m_radius);
00199 }
00200
00201
00202 void Vamos_Body::
00203 Suspension::find_forces ()
00204 {
00205 double anti_roll_force = 0.0;
00206 if (m_anti_roll_suspension)
00207 {
00208 anti_roll_force = m_anti_roll_k *
00209 (m_displacement - m_anti_roll_suspension->m_displacement);
00210 }
00211
00212
00213 double damp = m_bounce;
00214 if (m_compression_velocity < 0.0)
00215 {
00216 damp = m_rebound;
00217 }
00218
00219 if (m_displacement <= 0.0)
00220 {
00221
00222 m_force.zero ();
00223 }
00224 else
00225 {
00226
00227
00228
00229 if (std::abs (m_compression_velocity) > m_max_compression_velocity)
00230 {
00231 m_bottomed_out = true;
00232 }
00233
00234 double spring_force = m_spring_constant * m_displacement;
00235 double damp_force = damp * m_compression_velocity;
00236 m_force =
00237 rotate_in (m_normal * (spring_force + damp_force + anti_roll_force));
00238 }
00239
00240
00241 if (m_bottomed_out)
00242 {
00243 double spring_force = 1000000.0 * (m_displacement-m_travel);
00244 double damp_force = damp * m_compression_velocity;
00245 m_force =
00246 rotate_in (m_normal * (spring_force + damp_force + anti_roll_force));
00247 }
00248 }
00249
00250
00251 void Vamos_Body::
00252 Suspension::propagate (double time)
00253 {
00254 m_time_step = time;
00255
00256
00257 orient (m_static_orientation);
00258 rotate (m_steer_angle * STEER_AXIS);
00259 }
00260
00261
00262 void Vamos_Body::
00263 Suspension::rewind ()
00264 {
00265 }
00266
00267
00268 void Vamos_Body::
00269 Suspension::steer (double degree_angle)
00270 {
00271 m_steer_angle = deg_to_rad (degree_angle);
00272 }
00273
00274
00275 void Vamos_Body::
00276 Suspension::camber (double degree_angle)
00277 {
00278 if (m_side == LEFT)
00279 degree_angle *= -1.0;
00280
00281
00282 m_static_orientation.rotate (Three_Vector (-m_camber, 0.0, 0.0));
00283 m_camber = deg_to_rad (degree_angle);
00284 m_static_orientation.rotate (Three_Vector (m_camber, 0.0, 0.0));
00285 }
00286
00287
00288 void Vamos_Body::
00289 Suspension::caster (double degree_angle)
00290 {
00291
00292
00293
00294 m_static_orientation.rotate (Three_Vector (0.0, -m_caster, 0.0));
00295 m_caster = -deg_to_rad (degree_angle);
00296 m_static_orientation.rotate (Three_Vector (0.0, m_caster, 0.0));
00297 }
00298
00299
00300 void Vamos_Body::
00301 Suspension::toe (double degree_angle)
00302 {
00303 if (m_side == LEFT)
00304 degree_angle *= -1.0;
00305
00306
00307 m_static_orientation.rotate (-m_toe * STEER_AXIS);
00308 m_toe = deg_to_rad (degree_angle);
00309 m_static_orientation.rotate (m_toe * STEER_AXIS);
00310 }
00311
00312
00313
00314 double Vamos_Body::Suspension::
00315 camber_function (double displacement) const
00316 {
00317 return 0.0;
00318 }
00319
00320 double Vamos_Body::
00321 Suspension::current_camber (double normal_y) const
00322 {
00323 return Vamos_Geometry::clip (normal_y, -0.5, 0.5);;
00324 }
00325
00326
00327 void Vamos_Body::
00328 Suspension::reset ()
00329 {
00330 m_force.zero ();
00331 m_displacement = 0.0;
00332 }
00333
00334
00335 void Vamos_Body::
00336 Suspension::set_model (std::string file_name,
00337 double scale,
00338 const Three_Vector& translation,
00339 const Three_Vector& rotation)
00340 {
00341 Three_Vector position = translation;
00342 Three_Vector orientation = rotation;
00343 if (m_side == LEFT)
00344 {
00345
00346 position[1] *= -1.0;
00347 orientation[0] *= -1.0;
00348 orientation[1] *= -1.0;
00349 }
00350
00351
00352
00353
00354
00355 }
00356
00357 void Vamos_Body::
00358 Suspension::draw ()
00359 {
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376 }