src/vamos/body/Tire.cc

Go to the documentation of this file.
00001 //  Tire.cc - the tire 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/body/Tire.h>
00022 #include <vamos/geometry/Conversions.h>
00023 
00024 #include <algorithm>
00025 #include <cassert>
00026 #include <cmath>
00027 #include <iostream>
00028 
00029 using namespace Vamos_Geometry;
00030 
00031 #define MINSLIP 1.0e-4
00032 //#define MINSLIP 1.0e-2
00033 
00034 //* Class Tire_Friction
00035 
00036 //** Constructor
00037 Vamos_Body::
00038 Tire_Friction::Tire_Friction (const std::vector <double>& long_parameters,
00039                                                           const std::vector <double>& trans_parameters,
00040                                                           const std::vector <double>& align_parameters) :
00041   m_longitudital_parameters (long_parameters),
00042   m_transverse_parameters (trans_parameters),
00043   m_aligning_parameters (align_parameters),
00044   m_slide (0.0)
00045 {
00046   assert (m_longitudital_parameters.size () == 11);
00047   assert (m_transverse_parameters.size () == 15);
00048   assert (m_aligning_parameters.size () == 18);
00049 }
00050 
00051 double Vamos_Body::Tire_Friction::Pacejka_Fx(double sigma, double Fz, double friction_factor)
00052 {
00053         //double Fz_squared = Fz * Fz;
00054         
00055         // Evaluate the longitudinal parameters.
00056         const std::vector <double>& b = m_longitudital_parameters;
00057         /*double Cx = b [0];
00058         double Dx = friction_factor * (b [1] * Fz_squared + b [2] * Fz);
00059         double Bx = (b [3] * Fz_squared + b [4] * Fz) * exp (-b [5] * Fz) 
00060         / (Cx * Dx);
00061         double Ex = b [6] * Fz_squared + b [7] * Fz + b [8];
00062         double Shx = b [9] * Fz + b [10];*/
00063         
00064         double D = (b[1]*Fz + b[2])*Fz*friction_factor;
00065         double B = (b[3]*Fz+b[4])*exp(-b[5]*Fz)/(b[0]*(b[1]*Fz+b[2]));
00066         double E = (b[6]*Fz*Fz+b[7]*Fz+b[8]);
00067         double S = (100*sigma + b[9]*Fz+b[10]);
00068         double Fx = D*sin(b[0] * atan(S*B+E*(atan(S*B)-S*B)));
00069         return Fx;
00070 }
00071 
00072 double Vamos_Body::Tire_Friction::Pacejka_Fy(double alpha, double Fz, double gamma, double friction_factor)
00073 {
00074         //cout << alpha << "," << Fz << "," << gamma << endl;
00075         
00076         const std::vector <double>& a = m_transverse_parameters;
00077         
00078         /*double Cy = a [0];
00079   double Dy = (a [1] * Fz_squared + a [2] * Fz);
00080   double By = a [3] * sin (2.0 * atan (Fz / a [4])) 
00081         * (1.0 - a [5] * std::abs (gamma)) / (Cy * Dy);
00082   double Ey = a [6] * Fz + a [7];
00083   double Shy = a [8] * gamma + a [9] * Fz + a [10];
00084   double Svy = (a [11] * Fz + a [12]) * gamma * Fz 
00085         + a [13] * Fz + a [14];*/
00086         
00087         double D = (a[1]*Fz+a[2])*Fz*friction_factor;
00088         double B = a[3]*sin(2.0*atan(Fz/a[4]))*(1.0-a[5]*std::abs(gamma))/(a[0]*(a[1]*Fz+a[2])*Fz);
00089         double E = a[6]*Fz+a[7];
00090         double S = alpha + a[8]*gamma+a[9]*Fz+a[10];
00091 //      double Sv = ((a[11]*Fz+a[12])*gamma + a[13])*Fz+a[14];
00092         
00093         double Fy = D*sin(a[0]*atan(S*B+E*(atan(S*B)-S*B)));//+Sv;
00094         return Fy;
00095 }
00096 
00097 double Vamos_Body::Tire_Friction::Pacejka_Mz(double sigma, double alpha, double Fz, double gamma, double friction_factor)
00098 {
00099         const std::vector <double>& c = m_aligning_parameters;
00100         
00101         double D = (c[1]*Fz+c[2])*Fz*friction_factor;
00102         double B = (c[3]*Fz*Fz+c[4]*Fz)*(1.0-c[6]*std::abs(gamma))*exp(-c[5]*Fz)/(c[0]*D);
00103         double E = (c[7]*Fz*Fz+c[8]*Fz+c[9])*(1.0-c[10]*std::abs(gamma));
00104         double S = alpha + c[11]*gamma+c[12]*Fz+c[13];
00105 //      double Sv = (c[14]*Fz*Fz+c[15]*Fz)*gamma+c[16]*Fz + c[17];
00106         
00107         double Mz = D*sin(c[0]*atan(S*B+E*(atan(S*B)-S*B)));//+Sv;
00108         return Mz;
00109 }
00110 
00111 // Return the friction vector calculated from the magic formula.
00112 // HUB_VELOCITY is the velocity vector of the wheel's reference
00113 // frame.  PATCH_SPEED is the rearward speed of the contact pacth with
00114 // respect to the wheel's frame.
00115 Three_Vector Vamos_Body::
00116 Tire_Friction::friction_forces (double normal_force, double friction_factor,
00117                                                                 const Three_Vector& hub_velocity, 
00118                                                                 double patch_speed, double current_camber,
00119                                                                 double sigma_hat, double alpha_hat)
00120 {
00121         double Fz = normal_force / 1000.0;
00122         
00123         // Calculate the slip parameters sigma and tan_alpha.  We have to
00124         // play some games to keep them reasonable in extreme conditions.
00125         
00126         // Leave the slip parameters at zero if the difference between the
00127         // patch speed and the hub velocity is very small.
00128         double sigma = 0.0;
00129         double tan_alpha = 0.0;
00130         double alpha = 0.0;
00131         
00132         double V = hub_velocity[0];
00133         //if (std::abs(V) > MINSLIP)
00134         {
00135                 double denom = std::max (std::abs (hub_velocity [0]), 1.0);
00136                 
00137                 //sigma = (patch_speed/V - 1.0);
00138                 sigma = (patch_speed - V)/denom;
00139                 //sigma = patch_speed/V;
00140                 //sigma = -sigma;
00141                 
00142                 tan_alpha = hub_velocity [1] / denom;
00143                 //alpha = rad_to_deg(atan2(hub_velocity[1],hub_velocity[0]));
00144                 alpha = -rad_to_deg(atan2(hub_velocity[1],denom));
00145         }
00146         
00147         /*if (std::abs (hub_velocity [0] - patch_speed) > MINSLIP)
00148         {
00149           // Put a lower limit on the denominator to keep sigma and
00150           // tan_alpha from getting out of hand at low speeds.
00151                 double denom = std::max (std::abs (hub_velocity [0]), 3.0);
00152                 sigma = (patch_speed - hub_velocity [0]) / denom;
00153                 tan_alpha = hub_velocity [1] / denom;
00154                 alpha = atan(tan_alpha);
00155         }*/
00156         
00157         double gamma = rad_to_deg (current_camber);
00158         
00159         //double Fx = Pacejka_Fx(sigma, Fz);
00160         //double Fy = Pacejka_Fy(alpha, Fz, gamma);
00161         //double Mz = Pacejka_Mz(sigma, alpha, Fz, gamma);
00162         
00163         //combine the grip
00164         //double sigma_hat = 0.08;
00165         //double alpha_hat = 8.0;
00166         //double s = std::abs(sigma) / sigma_hat;
00167         //double a = std::abs(alpha) / alpha_hat;
00168         double s = sigma / sigma_hat;
00169         double a = alpha / alpha_hat;
00170         double rho = sqrt(s*s+a*a);
00171         
00172         double Fx = (s / rho)*Pacejka_Fx(rho*sigma_hat, Fz, friction_factor);
00173         double Fy = (a / rho)*Pacejka_Fy(rho*alpha_hat, Fz, gamma, friction_factor);
00174         double Mz = Pacejka_Mz(sigma, alpha, Fz, gamma, friction_factor);
00175         //Fx = (s / rho)*Pacejka_Fx(sigma, Fz);
00176         //Fy = (a / rho)*Pacejka_Fy(alpha, Fz, gamma);
00177         //cout << sigma << "," << sigma_hat << ": " << endl;
00178         //cout << s << "," << a << ": " << rho << endl;
00179         //Mz = (a / rho)*Pacejka_Mz(rho*sigma_hat, rho*alpha_hat, Fz, gamma);
00180         //cout << Fx << "," << Fy << "," << Mz << endl;
00181         
00182         //cout << V << "," << patch_speed << "," << sigma << ": " << Fx << endl;
00183         //cout << hub_velocity[0] << "," << hub_velocity[1] << "," << alpha << ": " << Fy << endl;
00184         //cout << "sigma=0: " << Pacejka_Fx(0, 2.5) << endl;
00185         //cout << "Fy,alpha=0: " << Pacejka_Fy(0, 2.5, 0) << endl;
00186         //cout << "alpha=0: " << Pacejka_Mz(0, 0, 2.5, 0) << endl;
00187         
00188         //double slip_x = sigma;
00189         double slip_x = -sigma / (1.0 + std::abs (sigma));
00190         //double slip_x = patch_speed/V;
00191         //double d_alpha = 
00192         //deg_to_rad (-Shy - Svy / (By * Cy * Dy * (1.0 + (180.0 / pi - 1.0) * Ey)));
00193         // Genta lists d_alpha as -Shy - Svy / (By * Cy * Dy).  This is what
00194         // you get from the magic formula for Fy(alpha) using the small
00195         // angle approximation.  However, the constants calculated above are
00196         // for alpha in degrees.  The small-angle formulas atan(x) =
00197         // 180*x/pi and sin(x) = pi*x/180 for x << 180/pi give the formula
00198         // d_alpha shown above.  Ey, in general, is not << 1.  After we get
00199         // d_alpha, we have to convert it to radians.
00200         double slip_y = tan_alpha / (1.0+std::abs (sigma-1.0));
00201         //double slip_y = hub_velocity[1];
00202         double total_slip = std::sqrt (slip_x * slip_x + slip_y * slip_y);
00203         /*if (total_slip > 1.0e-6)
00204         {
00205                 Fx *= slip_x / total_slip;
00206                 Fy *= slip_y / total_slip;
00207                 Mz *= slip_y / total_slip;
00208         }*/
00209         
00210         //cout << slip_x << "," << slip_y << "," << total_slip << endl;
00211         
00212         // Set the volume of the tire squeal sound. 
00213         //m_slide = 0.0;
00214         const std::vector <double>& b = m_longitudital_parameters;
00215         double maxforce = b[2] * 7.0; //(b[1]*(normal_force / 1000.0)+b[2])*4.0;
00216         double combforce = sqrt(Fx*Fx + Fy*Fy);
00217         //double overforce = maxforce - combforce;
00218         if (combforce > maxforce && combforce > 1.0e-3)
00219         {
00220                 //cout << "max: " << maxforce << ", " << combforce << " -- " << Fx << "," << Fy << " -- " << total_slip << endl;
00221                 Fx *= maxforce / combforce;
00222                 Fy *= maxforce / combforce;
00223         }
00224         /*if (!(std::abs(Fx) < maxforce))
00225         {
00226                 
00227                 Fx = maxforce;
00228         }
00229         if (!(std::abs(Fy) < maxforce))
00230         {
00231                 Fy = maxforce;
00232         }*/
00233         
00234         if (hub_velocity.abs () < 0.1)
00235         {
00236           m_slide = 0.0;
00237         }
00238   else
00239         {
00240           m_slide = total_slip;
00241           if (m_slide > 1.0)
00242                 m_slide = 1.0;
00243         }
00244         
00245         //cout << Fx << endl;
00246         
00247         // Construct the friction vector.  The z-component is the aligning
00248         // torque.
00249         return Three_Vector (Fx, Fy, Mz);
00250 }
00251 
00252 //double Vamos_Body::Tire_Friction::Pacejka_Fy(double slip_y, double Fz, double gamma);
00253 
00254 // Return the friction vector calculated from the magic formula.
00255 // HUB_VELOCITY is the velocity vector of the wheel's reference
00256 // frame.  PATCH_SPEED is the rearward speed of the contact pacth with
00257 // respect to the wheel's frame.
00258 /*Three_Vector Vamos_Body::
00259 Tire_Friction::friction_forces (double normal_force, double friction_factor,
00260                                                                 const Three_Vector& hub_velocity, 
00261                                                                 double patch_speed, double current_camber)
00262 {
00263   double Fz = normal_force / 1000.0;
00264   double Fz_squared = Fz * Fz;
00265         
00266   // Evaluate the longitudinal parameters.
00267   const std::vector <double>& b = m_longitudital_parameters;
00268   double Cx = b [0];
00269   double Dx = friction_factor * (b [1] * Fz_squared + b [2] * Fz);
00270   double Bx = (b [3] * Fz_squared + b [4] * Fz) * exp (-b [5] * Fz) 
00271         / (Cx * Dx);
00272   double Ex = b [6] * Fz_squared + b [7] * Fz + b [8];
00273   double Shx = b [9] * Fz + b [10];
00274 
00275   // Evaluate the transverse parameters.
00276   const std::vector <double>& a = m_transverse_parameters;
00277   double gamma = rad_to_deg (current_camber);
00278 
00279   double Cy = a [0];
00280   double Dy = friction_factor * (a [1] * Fz_squared + a [2] * Fz);
00281   double By = a [3] * sin (2.0 * atan (Fz / a [4])) 
00282         * (1.0 - a [5] * std::abs (gamma)) / (Cy * Dy);
00283   double Ey = a [6] * Fz + a [7];
00284   double Shy = a [8] * gamma + a [9] * Fz + a [10];
00285   double Svy = (a [11] * Fz + a [12]) * gamma * Fz 
00286         + a [13] * Fz + a [14];
00287 
00288   // Evaluate the formula for aligning torque.
00289   const std::vector <double>& c = m_aligning_parameters;
00290   double Cz = c [0];
00291   double Dz = friction_factor * (c [1] * Fz_squared + c [2] * Fz);
00292   double Bz = (c [3] * Fz_squared + c [4] * Fz) 
00293         * (1.0 - c [6] * std::abs (gamma))
00294         * exp (-c [5] * Fz) / (Cz * Dz);
00295   double Ez = (c [7] * Fz_squared + c [8] * Fz + c [9]) 
00296         * (1.0 - c [10] * std::abs (gamma));
00297   double Shz = c [11] * gamma + c [12] * Fz + c [13];
00298   double Svz = (c [14] * Fz_squared + c [15] * Fz) * gamma + c [16] * Fz 
00299         + c [17];
00300 
00301   // Calculate the slip parameters sigma and tan_alpha.  We have to
00302   // play some games to keep them reasonable in extreme conditions.
00303 
00304   // Leave the slip parameters at zero if the difference between the
00305   // patch speed and the hub velocity is very small.
00306   double sigma = 0.0;
00307   double tan_alpha = 0.0;
00308   if (std::abs (hub_velocity [0] - patch_speed) > MINSLIP)
00309         {
00310           // Put a lower limit on the denominator to keep sigma and
00311           // tan_alpha from getting out of hand at low speeds.
00312           double denom = std::max (std::abs (hub_velocity [0]), 3.0);
00313           sigma = (patch_speed - hub_velocity [0]) / denom;
00314           tan_alpha = hub_velocity [1] / denom;
00315         }
00316 
00317   double d_sigma = -Shx;
00318   double slip_x = -sigma / (1.0 + std::abs (sigma)) - d_sigma;
00319 
00320   double d_alpha = 
00321         deg_to_rad (-Shy - Svy / (By * Cy * Dy * (1.0 + (180.0 / pi - 1.0) * Ey)));
00322   // Genta lists d_alpha as -Shy - Svy / (By * Cy * Dy).  This is what
00323   // you get from the magic formula for Fy(alpha) using the small
00324   // angle approximation.  However, the constants calculated above are
00325   // for alpha in degrees.  The small-angle formulas atan(x) =
00326   // 180*x/pi and sin(x) = pi*x/180 for x << 180/pi give the formula
00327   // d_alpha shown above.  Ey, in general, is not << 1.  After we get
00328   // d_alpha, we have to convert it to radians.
00329 
00330   double slip_y = tan_alpha / (1.0 + std::abs (sigma)) + d_alpha;
00331 
00332   double total_slip = std::sqrt (slip_x * slip_x + slip_y * slip_y);
00333   double slip_percent = total_slip * 100.0;
00334 
00335   // Find the longitudinal force.
00336   double Fx = -Dx * sin (Cx * atan (Bx * (1.0 - Ex) * (slip_percent + Shx)
00337                                                                         + Ex * atan (Bx * (slip_percent + Shx))));
00338 
00339   // Find the transverse force.
00340   double Fy = 
00341         -Dy * sin (Cy * atan (By * (1.0 - Ey) * (slip_percent + Shy)
00342                                                   + Ey * atan (By * (slip_percent + Shy)))) + Svy;
00343 
00344   // Genta describes a more complicated method of combining Fx and Fy,
00345   // however I can't make sense of it.  No matter what I do I can't
00346   // get the Fx vs. Fy curves to look like anything reasonable.
00347 
00348   // Find the aligning torque.
00349   double Mz = 
00350         -Dz * sin (Cz * atan (Bz * (1.0 - Ez) * (slip_percent + Shz)
00351                                                   + Ez * atan (Bz * (slip_percent + Shz)))) + Svz;
00352 
00353   if (total_slip > 1.0e-6)
00354         {
00355           Fx *= slip_x / total_slip;
00356           Fy *= slip_y / total_slip;
00357           Mz *= slip_y / total_slip;
00358         }
00359         
00360         //- Fy is the resulting combined slip lateral force
00361         //- Fy0 is the lateral force as calculated using the normal Fy formula
00362         //- Fx is the longitudinal force as calculated using the normal Fx formula
00363         //- Fx0 is the MAXIMUM longitudinal force possible (calculated as D+Sv in the Pacejka Fx formula).
00364         //double D = (b [1] * Fz_squared + b [2] * Fz);
00365         //double maxforce = Fy*sqrt(1.0-(Fx/D)*(Fx/D));
00366         double maxforce = b[2] * 4.0; //(b[1]*(normal_force / 1000.0)+b[2])*4.0;
00367         double combforce = sqrt(Fx*Fx + Fy*Fy);
00368         //double overforce = maxforce - combforce;
00369         if (combforce > maxforce && combforce > 1.0e-3)
00370         {
00371                 //cout << "max: " << maxforce << ", " << combforce << " -- " << Fx << "," << Fy << " -- " << total_slip << endl;
00372                 Fx *= maxforce / combforce;
00373                 Fy *= maxforce / combforce;
00374         }
00375         
00376         //cout << slip_x << "," << total_slip << endl;
00377 
00378   // Set the volume of the tire squeal sound. 
00379   if (hub_velocity.abs () < 0.1)
00380         {
00381           m_slide = 0.0;
00382         }
00383   else
00384         {
00385           m_slide = total_slip;
00386           if (m_slide > 1.0)
00387                 m_slide = 1.0;
00388         }
00389 
00390         //cout << Fx << endl;
00391         
00392   // Construct the friction vector.  The z-component is the aligning
00393   // torque.
00394   return Three_Vector (Fx, Fy, Mz);
00395 }*/
00396 
00397 //* Class Tire
00398 
00399 //** Constructor
00400 Vamos_Body::
00401 Tire::Tire (double radius, double rolling_resistance_1,
00402                         double rolling_resistance_2, const Tire_Friction& friction, 
00403                         double inertia, double tread) :
00404   m_radius (radius),
00405   m_rolling_resistance_1 (rolling_resistance_1),
00406   m_rolling_resistance_2 (rolling_resistance_2),
00407   m_tire_friction (friction),
00408   m_inertia (inertia),
00409   m_rotational_speed (0.0),
00410   m_last_rotational_speed (0.0),
00411   m_slide (0.0),
00412   m_velocity (0.0, 0.0, 0.0),
00413   m_normal_ang_velocity (0.0),
00414   m_normal_force (0.0),
00415   m_camber (0.0),
00416   m_applied_torque (0.0),
00417   m_is_locked (false),
00418   m_material (0),
00419   m_feedback (0),
00420   m_tread (tread),
00421   m_friction1 (1.0),
00422   m_friction2 (1.0)
00423 {
00424 }
00425 
00426 // Called by the wheel to update the tire.
00427 void Vamos_Body::
00428 Tire::input (const Three_Vector& velocity, 
00429                          double normal_ang_velocity,
00430                          const Three_Vector& normal_force,
00431                          double camber,
00432                          double torque,
00433                          bool is_locked,
00434                          Material_Handle material)
00435 {
00436   orient_frame_with_unit_vector (normal_force.unit ());
00437 
00438   m_velocity = rotate_in (velocity);
00439   m_normal_ang_velocity = normal_ang_velocity;
00440   m_normal_force = normal_force.abs ();
00441   m_camber = camber;
00442   m_applied_torque = torque;
00443   m_is_locked = is_locked;
00444   m_material = material;
00445 }
00446 
00447 // Orient the tire's z-axis with the normal force.
00448 void Vamos_Body::
00449 Tire::orient_frame_with_unit_vector (const Three_Vector& normal_unit_vector)
00450 {
00451   Three_Vector rotation_axis = 
00452         Three_Vector (-normal_unit_vector [1], normal_unit_vector [0], 0.0);
00453 
00454   double length = sqrt (normal_unit_vector [0] * normal_unit_vector [0]
00455                                                 + normal_unit_vector [1] * normal_unit_vector [1]);
00456   double rotation_angle = asin (length);
00457 
00458   orient (Three_Matrix (1.0));
00459   rotate (rotation_axis.unit () * rotation_angle);
00460 }
00461 
00462 void Vamos_Body::
00463 Tire::find_forces ()
00464 {
00465   // m_force is the force of the road on the tire.  The force of the
00466   // tire on the body must be calculated.  The transverse component
00467   // won't change, but the longitudial component will be affected by
00468   // the tire's ability to move in that direction, and by applied
00469   // foces (acceleration and braking).
00470 
00471   // Skip this step if we don't have a surface yet.
00472   if (m_material.null ())
00473         return;
00474 
00475   m_slide = 0.0;
00476 
00477   if (m_normal_force <= 0.0)
00478         {
00479           m_force.zero ();
00480           m_torque.zero ();
00481           return;
00482         }
00483 
00484         double sh, ah, nf;
00485         nf = (m_normal_force / 1000.0);
00486         if (nf < HAT_LOAD)
00487         {
00488                 sh = sigma_hat[0];
00489                 ah = alpha_hat[0];
00490         }
00491         else if (nf > HAT_LOAD*HAT_ITERATIONS)
00492         {
00493                 sh = sigma_hat[HAT_ITERATIONS-1];
00494                 ah = alpha_hat[HAT_ITERATIONS-1];
00495         }
00496         else
00497         {
00498                 int lbound;
00499                 double blend;
00500                 lbound = (int)(nf/HAT_LOAD);
00501                 lbound--;
00502                 if (lbound < 0)
00503                         lbound = 0;
00504                 blend = (nf-HAT_LOAD*(lbound+1))/HAT_LOAD;
00505                 sh = sigma_hat[lbound]*(1.0-blend)+sigma_hat[lbound+1]*blend;
00506                 ah = alpha_hat[lbound]*(1.0-blend)+alpha_hat[lbound+1]*blend;
00507         }
00508         
00509         
00510   // Get the friction force (components 0 and 1) and the aligning
00511   // torque (component 2).
00512         double surface_friction_factor = (1.0-m_tread)*m_friction1 + m_tread*m_friction2;
00513         //cout << m_tread << ": " << m_friction1 << "," << m_friction2 << endl;
00514         //if (surface_friction_factor < 1.0) cout << surface_friction_factor << endl;
00515   Three_Vector friction_force = m_tire_friction.
00516         //friction_forces (m_normal_force, m_material->friction_factor (), m_velocity, speed(), m_camber, sh, ah);
00517         friction_forces (m_normal_force, surface_friction_factor, m_velocity, speed(), m_camber, sh, ah);
00518         
00519         //cout << m_normal_force << endl;
00520         
00521         //if (!firstprint)
00522         if (0)
00523         {
00524                 ofstream of("/home/joe/temp/y.txt");
00525                 double x;
00526                 double load = 2.500;
00527                 of << "Fx = c(";
00528                 for (x = -2; x < 2; x += 0.01)
00529                 {
00530                         /*float load = 2500;
00531                         float fspeed = 1.0;
00532                         Three_Vector fakevel(fspeed/(x+1),0,0);
00533                         cout << m_tire_friction.
00534                 friction_forces (load, m_material->friction_factor (),
00535                                                  fakevel, fspeed, m_camber)[0] << ", ";*/
00536                         //cout << m_tire_friction.Pacejka_Fx(x, load) << ",";
00537                         //of << m_tire_friction.Pacejka_Mz(0, x, load, 0) << ",";
00538                         of << m_tire_friction.Pacejka_Fx(x, load, 1.0) << ",";
00539                 }
00540                 of << "0)" << endl;
00541                 //of.close();
00542                 
00543                 //ofstream of("/home/joe/temp/y3.txt");
00544                 //double x;
00545                 of << "Fy = c(";
00546                 for (x = -20; x < 20; x += 0.1)
00547                 {
00548                         /*float load = 2500;
00549                         float fspeed = 1.0;
00550                         Three_Vector fakevel(fspeed/(x+1),0,0);
00551                         cout << m_tire_friction.
00552                 friction_forces (load, m_material->friction_factor (),
00553                                                  fakevel, fspeed, m_camber)[0] << ", ";*/
00554 
00555                         //cout << m_tire_friction.Pacejka_Fx(x, load) << ",";
00556                         //of << m_tire_friction.Pacejka_Mz(0, x, load, 0) << ",";
00557                         of << m_tire_friction.Pacejka_Fy(x, load, 0, 1.0) << ",";
00558                 }
00559                 of << "0)" << endl;
00560                 //of.close();
00561                 
00562                 //ofstream of("/home/joe/temp/y4.txt");
00563                 //double x;
00564                 of << "Mz = c(";
00565                 for (x = -20; x < 20; x += 0.1)
00566                 {
00567                         /*float load = 2500;
00568                         float fspeed = 1.0;
00569                         Three_Vector fakevel(fspeed/(x+1),0,0);
00570                         cout << m_tire_friction.
00571                 friction_forces (load, m_material->friction_factor (),
00572                                                  fakevel, fspeed, m_camber)[0] << ", ";*/
00573                         
00574                         
00575                         //cout << m_tire_friction.Pacejka_Fx(x, load) << ",";
00576                         //of << m_tire_friction.Pacejka_Mz(0, x, load, 0) << ",";
00577                         of << m_tire_friction.Pacejka_Mz(0, x, load, 0, 1.0) << ",";
00578                 }
00579                 of << "0)" << endl;
00580                 
00581                 of.close();
00582                 
00583 //              firstprint = true;
00584         }
00585 
00586   // the frictional force opposing the motion of the contact patch.
00587   m_force = Three_Vector (friction_force [0], friction_force [1], 0.0);
00588 
00589   // Apply the reaction torque from acceleration or braking.  In
00590   // normal conditions this torque comes from friction.  However, the
00591   // frictional force can sometimes be large when no acceleration or
00592   // braking is applied.  For instance, when you run into a gravel
00593   // trap.  In any case, the reaction torque should never be larger
00594   // than the applied accelerating or braking torque. 
00595   double reaction = m_force [0] * m_radius;
00596   if (((m_applied_torque > 0.0) && (reaction > m_applied_torque))
00597           || ((m_applied_torque < 0.0) && (reaction < m_applied_torque)))
00598         {
00599           reaction = m_applied_torque;
00600         }
00601         
00602         //cout << m_force[0] << endl;
00603         
00604         //cout << friction_force [2] << endl;
00605 
00606   m_torque = Three_Vector (0.0, reaction, friction_force [2]);
00607         
00608   double feedbackcoeff = 0.05;
00609   m_feedback = m_feedback*(1.0-feedbackcoeff) + friction_force[2]*feedbackcoeff;
00610 
00611   if (!m_is_locked)
00612         {
00613           double rolling_1 = m_rolling_resistance_1;
00614           if (speed () < 0.0)
00615                 rolling_1 *= -1.0;
00616           // Include constant and quadratic rolling resistance.
00617           double rolling = m_rolling_resistance_factor  
00618                 * (rolling_1 + m_rolling_resistance_2 * speed () * speed ());
00619           m_applied_torque -= (m_force [0] + rolling) * m_radius;
00620         }
00621 
00622   // Add the suface drag.
00623   m_force [0] -= m_rolling_drag * m_velocity [0];
00624   m_force [1] -= m_rolling_drag * m_velocity [1];
00625 
00626   m_slide = m_tire_friction.slide ();
00627         
00628         bool nan = false;
00629         if (!(m_force[0] < 0 || m_force[0] >= 0))
00630         {
00631                 m_force[0] = 0;
00632                 nan = true;
00633         }
00634         if (!(m_force[1] < 0 || m_force[1] >= 0))
00635         {
00636                 m_force[1] = 0;
00637                 nan = true;
00638         }
00639         if (!(m_force[2] < 0 || m_force[2] >= 0))
00640         {
00641                 m_force[2] = 0;
00642                 nan = true;
00643         }
00644         
00645         if (nan)        
00646                 m_force.zero();
00647         
00648         nan = false;
00649         
00650         if (!(m_torque[0] < 0 || m_torque[0] >= 0))
00651         {
00652                 m_torque[0] = 0;
00653                 nan = true;
00654         }
00655         if (!(m_torque[1] < 0 || m_torque[1] >= 0))
00656         {
00657                 m_torque[1] = 0;
00658                 nan = true;
00659         }
00660         if (!(m_torque[2] < 0 || m_torque[2] >= 0))
00661         {
00662                 m_torque[2] = 0;
00663                 nan = true;
00664         }
00665         
00666         if (nan)
00667                 m_torque.zero();
00668 }
00669 
00670 // Advance this suspension component forward in time by TIME.
00671 void Vamos_Body::
00672 Tire::propagate (double time) 
00673 {
00674   m_last_rotational_speed = m_rotational_speed;
00675   if (m_is_locked)
00676         {
00677           // This causes speed() to return 0.0.
00678           m_rotational_speed = 0.0;
00679         }
00680   else
00681         {
00682           m_rotational_speed += m_applied_torque * time / m_inertia;
00683         }
00684 }
00685 
00686 void Vamos_Body::
00687 Tire::rewind ()
00688 {
00689   m_rotational_speed = m_last_rotational_speed;
00690 }
00691 
00692 // Return the position of the contact patch in the wheel's coordinate
00693 // system.
00694 Three_Vector Vamos_Body::
00695 Tire::contact_position () const
00696 {
00697   return Three_Vector (0.0, 0.0, -m_radius);
00698 }
00699 
00700 // Set the tire to its initial conditions.
00701 void Vamos_Body::
00702 Tire::reset ()
00703 {
00704         //firstprint = false;
00705   m_rotational_speed = 0.0;
00706   m_force.zero ();
00707   m_torque.zero ();
00708         
00709         int i;
00710         for (i = 0; i < HAT_ITERATIONS; i++)
00711         {
00712                 FindSigmaHatAlphaHat((double)(i+1)*HAT_LOAD, sigma_hat[i], alpha_hat[i]);
00713                 //cout << i << ": " << sigma_hat[i] << "," << alpha_hat[i] << endl;
00714         }
00715 }
00716 
00717 void Vamos_Body::
00718 Tire::FindSigmaHatAlphaHat(double load, double & sh, double & ah)
00719 {
00720         double x, y, ymax;
00721         ymax = 0;
00722         for (x = -2; x < 2; x += 0.01)
00723         {
00724                 y = m_tire_friction.Pacejka_Fx(x, load, 1.0);
00725                 if (y > ymax)
00726                 {
00727                         sh = x;
00728                         ymax = y;
00729                 }
00730         }
00731         
00732         ymax = 0;
00733         for (x = -20; x < 20; x += 0.1)
00734         {
00735                 y = m_tire_friction.Pacejka_Fy(x, load, 0, 1.0);
00736                 if (y > ymax)
00737                 {
00738                         ah = x;
00739                         ymax = y;
00740                 }
00741         }
00742 }

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