src/vamos/body/Suspension.cc

Go to the documentation of this file.
00001 //  Suspension.cc - the suspension component for a wheel.
00002 //
00003 //  Copyright (C) 2001--2004 Sam Varner
00004 //
00005 //  This file is part of Vamos Automotive Simulator.
00006 //
00007 //  This program is free software; you can redistribute it and/or modify
00008 //  it under the terms of the GNU General Public License as published by
00009 //  the Free Software Foundation; either version 2 of the License, or
00010 //  (at your option) any later version.
00011 //
00012 //  This program is distributed in the hope that it will be useful,
00013 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 //  GNU General Public License for more details.
00016 //
00017 //  You should have received a copy of the GNU General Public License
00018 //  along with this program; if not, write to the Free Software
00019 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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 //* Static Member
00030 
00031 // The axis of rotation for steering and toe adjustments.
00032 const Three_Vector Vamos_Body::Suspension::
00033 STEER_AXIS = Three_Vector (0.0, 0.0, 1.0);
00034 
00035 // Note that all angles are stored as right-hand rotations.  As a
00036 // result, m_caster for a wheel on the right side of the car follows
00037 // the common convention that positive camber means that the wheel
00038 // leans away from the centerline.  For the wheel on the left,
00039 // m_caster is contrary to convention.
00040 
00041 
00042 //* Class Hinge
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 //* Struct Suspension_Model
00059 struct Vamos_Body::Suspension_Model
00060 {
00061 /*  GLuint display_list;
00062   double x;
00063   double y;
00064   double z;
00065 
00066   Suspension_Model (GLuint list_id, const Three_Vector& position)
00067         : display_list (list_id),
00068           x (position[0]),
00069           y (position[1]),
00070           z (position[2])
00071   {
00072   };*/
00073 };
00074 
00075 //* Class Suspension
00076 
00077 //** Constructor
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   // m_radius points from m_position to the hinge.
00108   m_radius = center_of_translation - m_position;
00109 
00110   // m_radius_magnitude is the length of m_radius.  It will not
00111   // change.
00112   m_radius_magnitude = m_radius.magnitude ();
00113 }
00114 
00115 
00116 Vamos_Body::
00117 Suspension::~Suspension ()
00118 {
00119   /*for (std::vector <Suspension_Model*>::iterator it = m_models.begin ();
00120            it != m_models.end ();
00121            it++)
00122         {
00123           delete *it;
00124         }*/
00125 }
00126 
00127 // Specify the suspension component that is attached to this one with
00128 // an anti-roll bar.  The anti-roll bar will have a spring constant of
00129 // SPRING_CONSTANT.
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 // Displace this suspension component by DISTANCE.  A positive
00141 // DISTANCE means compression.
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                 //VENZON: suspension bumper
00151           //m_displacement = m_travel;
00152         }
00153   else
00154         {
00155           m_bottomed_out = false;
00156         }
00157 
00158   // Update m_angle.  m_angle is a right-hand rotation about the
00159   // y-axis from the x-axis to m_radius.
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   // Get the right quadrant.
00165   if (hinge_pos[0] > m_position[0])
00166         {
00167           m_angle = pi - m_angle;
00168         }
00169 
00170   // Update m_position preserving the magnitude of m_radius.  We don't
00171   // change the y position yet.
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   // m_radius points from m_position to the hinge.
00178   m_radius = hinge_pos - m_position;
00179 
00180   // m_tangent is a unit vector that is perpendicular to m_radius such
00181   // that m_tangent x m_radius points in the y direction.
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 // Calculate the force exerted by the suspension in its current state.
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   // Use `m_bounce' for compression, `m_rebound' for decompression.
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           // Don't exert a force if this suspension is not compressed.
00222           m_force.zero ();
00223         }
00224   else
00225         {
00226           // If the suspension is moving at a speed > m_max_compression_velocity,
00227           // the damper 'locks up' due to turbulence in the fluid.  The effect
00228           // is the same as bottoming out.
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         //VENZON:  suspension bumper (special case for bottomed out springs)
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 // Advance this suspension component forward in time by TIME.
00251 void Vamos_Body::
00252 Suspension::propagate (double time)
00253 {
00254   m_time_step = time;
00255 
00256   // Start with the static orientation.
00257   orient (m_static_orientation);
00258   rotate (m_steer_angle * STEER_AXIS);
00259 }
00260 
00261 // Undo the last propagation.
00262 void Vamos_Body::
00263 Suspension::rewind ()
00264 {
00265 }
00266 
00267 // Set the steering angle.
00268 void Vamos_Body::
00269 Suspension::steer (double degree_angle)
00270 {
00271   m_steer_angle = deg_to_rad (degree_angle);
00272 }
00273 
00274 // Set the camber angle.
00275 void Vamos_Body::
00276 Suspension::camber (double degree_angle)
00277 {
00278   if (m_side == LEFT)
00279         degree_angle *= -1.0;
00280 
00281   // Undo the current camber setting before applying the new one.
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 // Set the caster angle.
00288 void Vamos_Body::
00289 Suspension::caster (double degree_angle)
00290 {
00291   // The caster rotation is in the same direction for both sides.
00292 
00293   // Undo the current caster setting before applying the new one.
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 // Set the toe angle.
00300 void Vamos_Body::
00301 Suspension::toe (double degree_angle)
00302 {
00303   if (m_side == LEFT)
00304         degree_angle *= -1.0;
00305 
00306   // Undo the current toe setting before applying the new one.
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 // Return the camber angle in radians for a suspension displacement of
00313 // DISPLACEMENT.
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 // Return this suspension component to equilibrium.
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           // Make the right and left sides symmetric.
00346           position[1] *= -1.0;
00347           orientation[0] *= -1.0;
00348           orientation[1] *= -1.0;
00349         }
00350 
00351   /*Vamos_Media::Ac3d* model = 
00352     new Vamos_Media::Ac3d (file_name, scale, Three_Vector (), orientation);
00353   m_models.push_back (new Suspension_Model (model->build (), position));
00354   delete model;*/
00355 }
00356 
00357 void Vamos_Body::
00358 Suspension::draw ()
00359 {
00360 /*  for (std::vector <Suspension_Model*>::iterator it = m_models.begin ();
00361            it != m_models.end ();
00362            it++)
00363         {
00364           glPushMatrix ();
00365 
00366           glTranslatef (m_position[0] + (*it)->x, 
00367                                         m_position[1] + (*it)->y,
00368                                         m_position[2] + (*it)->z - m_displacement);
00369 
00370           double angle = rad_to_deg (std::atan2 (-m_displacement, (*it)->y));
00371           glRotatef (angle, 1.0, 0.0, 0.0);
00372 
00373           glCallList ((*it)->display_list);
00374           glPopMatrix ();
00375         }*/
00376 }

Generated on Thu Oct 19 04:05:55 2006 by  doxygen 1.4.6