src/vamos/body/Engine.cc

Go to the documentation of this file.
00001 //  Engine.cc - an engine for the drivetrain.
00002 //
00003 //  Copyright (C) 2001--2002 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/Engine.h>
00022 #include <vamos/geometry/Conversions.h>
00023 #include <iostream>
00024 
00025 //* Class Engine
00026 
00027 //** Constructor
00028 Vamos_Body::
00029 Engine::Engine (double mass, const Vamos_Geometry::Three_Vector& position,
00030                                 double max_power,
00031                                 double peak_engine_rpm,
00032                                 double rpm_limit,
00033                                 double inertia,
00034                                 double idle_throttle,
00035                                 double start_speed,
00036                                 double stall_speed,
00037                                 double fuel_consumption) 
00038   : Particle (mass, position),
00039         m_max_power (max_power),
00040         m_peak_engine_speed (Vamos_Geometry::rpm_to_rad_s (peak_engine_rpm)),
00041         m_engine_speed_limit (Vamos_Geometry::rpm_to_rad_s (rpm_limit)),
00042         m_inertia (inertia),
00043         m_idle_throttle (idle_throttle),
00044         m_start_speed (Vamos_Geometry::rpm_to_rad_s (start_speed)),
00045         m_stall_speed (Vamos_Geometry::rpm_to_rad_s (stall_speed)),
00046         m_fuel_consumption (fuel_consumption),
00047         m_rotational_speed (0.0),
00048         m_gas (0.0),
00049         m_drag (0.0),
00050         m_transmission_speed (0.0),
00051         m_out_of_gas (false),
00052         m_drive_torque (0.0),
00053         m_drive_impulse (0.0),
00054         m_engaged (false),
00055     // See "Motor Vehicle Dynamics" Genta, Section 4.2.2
00056     m_friction (m_max_power / pow (m_peak_engine_speed, 3))
00057 {
00058 }
00059 
00060 void Vamos_Body::
00061 Engine::set_torque_curve (const std::vector <Vamos_Geometry::Two_Point>& torque_points)
00062 {
00063   m_torque_curve.clear ();
00064   m_torque_curve.load (torque_points);
00065   m_torque_curve.scale (Vamos_Geometry::rpm_to_rad_s (1.0));
00066         //cout << m_torque_curve.interpolate(8300*Vamos_Geometry::rpm_to_rad_s(1.0)) << endl;
00067 //      cout << "torque curve set" << endl;
00068 }
00069 
00070 // Handle the input parameters.  GAS is the throttle position.
00071 // TRANSMISSION_SPEED is the rotational speed of the transmission side
00072 // of the clutch.  DRAG is the torque due to friction when the clutch
00073 // is not fully engaged.  ENGAGED is true when the clutch is fully
00074 // engaged, false otherwise.
00075 void Vamos_Body::
00076 Engine::input (double gas, double drag, double transmission_speed, 
00077                            bool engaged)
00078 {
00079   m_gas = gas;
00080   m_drag = drag;
00081   m_transmission_speed = transmission_speed;
00082   m_engaged = engaged;
00083 }
00084 
00085 void Vamos_Body::
00086 Engine::find_forces ()
00087 {
00088   // Find the engine's torque with the current conditions.
00089   m_drive_torque = torque_map (m_gas, m_rotational_speed) - m_drag;
00090   m_torque = Vamos_Geometry::Three_Vector (-m_drive_torque, 0.0, 0.0);
00091 }
00092 
00093 void Vamos_Body::
00094 Engine::propagate (double time)
00095 {
00096   // The engine should change its own speed only when the clutch is 
00097   // disengaged.  Otherwise, the engine speed is matched to the transmission,
00098   // which changes speed due to the applied engine torque.
00099   m_last_rotational_speed = m_rotational_speed;
00100  
00101   // If the clutch is engaged, the engine speed is locked to the
00102   // transmission speed.
00103   if (m_engaged)
00104         {
00105           m_rotational_speed = m_transmission_speed;
00106         }
00107   else
00108         {
00109           m_rotational_speed += time * m_drive_torque / m_inertia;
00110         }
00111 
00112   // Keep engine speed from going negative when changing from forward to
00113   // reverse (or vice versa) without using the clutch.
00114   if (m_rotational_speed < m_stall_speed)
00115         {
00116           m_rotational_speed = 0.0;
00117         }
00118 }
00119 
00120 void Vamos_Body::
00121 Engine::rewind ()
00122 {
00123   m_rotational_speed = m_last_rotational_speed;
00124 }
00125 
00126 // Return the torque for a given throttle setting, GAS, and engine
00127 // speed ROTATIONAL_SPEED.
00128 double Vamos_Body::
00129 Engine::torque_map (double gas, double rot_speed)
00130 {
00131   double idle = m_idle_throttle;
00132   if ((m_out_of_gas) || (m_rotational_speed < m_stall_speed))
00133         {
00134           gas = 0.0;
00135           idle = 0.0;
00136         }
00137   else if (gas < idle) 
00138         {
00139           gas = idle;
00140         }
00141   m_gas = gas;
00142         
00143         if (m_torque_curve.size () == 0)
00144     {
00145       // See "Motor Vehicle Dynamics" Genta, Section 4.2.2
00146                 /*double torque = m_friction * rot_speed * rot_speed;
00147                 
00148                 assert (m_peak_engine_speed != 0.0);
00149                 
00150                 if (m_rotational_speed < m_engine_speed_limit)
00151                 {
00152                   torque += (m_max_power * m_gas * (1.0 + rot_speed / m_peak_engine_speed) 
00153                 / m_peak_engine_speed);
00154                 }
00155                 
00156                 return torque;*/
00157                 
00158                 double factor = 1.0 / m_peak_engine_speed; 
00159 
00160                 double torque = -m_max_power * factor * factor * factor 
00161                         * rot_speed * rot_speed;
00162                 
00163                 if (m_rotational_speed < m_engine_speed_limit)
00164                 {
00165                   torque += m_max_power * factor * gas * (1.0 + factor * rot_speed);
00166                 }
00167                 
00168                 return torque;
00169                 
00170       //return (m_max_power * m_gas * (1.0 + rot_speed / m_peak_engine_speed) 
00171           //      / m_peak_engine_speed)
00172         //- m_friction * rot_speed * rot_speed;
00173     }
00174   else
00175     {
00176       // Interpolate between the drag curve and the torque curve.
00177                 double torque = -m_friction * rot_speed * rot_speed * (1 - m_gas);
00178                 //double torque = -m_friction * rot_speed * rot_speed;
00179                 
00180                 //cout << m_gas * m_torque_curve.interpolate (rot_speed) << " - " << torque << ": ";
00181                 
00182                 if (m_rotational_speed < m_engine_speed_limit)
00183                 {
00184                   //torque += m_max_power * factor * gas * (1.0 + factor * rot_speed);
00185                         double addtorque = m_gas * m_torque_curve.interpolate (rot_speed);
00186                         if (addtorque > 0)
00187                                 torque += addtorque;
00188                         //cout << m_torque_curve.interpolate (rot_speed) << ": ";
00189                 }
00190                 //cout << rot_speed << "," << torque << "," << m_gas << endl;
00191                 //cout << m_torque_curve.interpolate(9400*0.104) << endl;
00192                 return torque;
00193                 
00194       //return m_gas * m_torque_curve.interpolate (rot_speed) 
00195       //  - m_friction * rot_speed * rot_speed * (1.0 - m_gas);
00196     }
00197         
00198 /*// This model is from section 4.2.2 of Getna's "Motor Vehicle Dynamics."
00199   double factor = 1.0 / m_peak_engine_speed; 
00200 
00201   double torque = -m_max_power * factor * factor * factor 
00202         * rot_speed * rot_speed;
00203 
00204   if (m_rotational_speed < m_engine_speed_limit)
00205         {
00206           torque += m_max_power * factor * gas * (1.0 + factor * rot_speed);
00207         }
00208 
00209   return torque;*/
00210 }
00211 
00212 // Set the engine speed to SPEED_IN and calculate the resulting
00213 // impulse.
00214 void Vamos_Body::
00215 Engine::speed (double speed_in)
00216 {
00217   if (speed_in > m_stall_speed)
00218         {
00219           m_rotational_speed = speed_in;
00220         }
00221   else
00222         {
00223           // The engine stalled.
00224           m_rotational_speed = 0.0;
00225         }
00226   // Record the change in angular momentum.
00227   m_drive_impulse = m_inertia * (m_rotational_speed - m_last_rotational_speed);
00228 }

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