// Copyright (C) 2001-2019 Sam Varner
//
// This file is part of Vamos Automotive Simulator.
//
// Vamos is free software: you can redistribute it and/or modify it under the terms of
// the GNU General Public License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// Vamos is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with Vamos.
// If not, see <http://www.gnu.org/licenses/>.
#ifndef VAMOS_BODY_ENGINE_HPP_INCLUDED
#define VAMOS_BODY_ENGINE_HPP_INCLUDED
#include "../geometry/Constants.hpp"
#include "../geometry/Spline.hpp"
#include "../geometry/Two_Vector.hpp"
#include "Particle.hpp"
namespace Vamos_Body
{
/// An engine for the drivetrain. An engine indirectly produces force through the
/// drivetrain. It also directly produces a torque in reaction to the torque that is
/// transmitted to the clutch.
class Engine : public Particle
{
public:
/// @param mass The mass of the engine.
/// @param position The location of the engine.
/// @param max_power Maximum engine power in derived units consistent with the length,
/// mass, and time units used throughout the simulation (watts in MKS).
/// @param peak_engine_rpm The engine speed, in rotations per minute, at which maximum
/// power is produced.
/// @param rpm_limit The throttle is cut while engine speed is above this value.
/// @param inertia The rotational inertia of moving components.
/// @param idle_throttle The minimum throttle fraction.
/// @param stall_rpm The engine stops if its speed goes below this value.
/// @param fuel_consumption This factor times engine speed in rad/s and the throttle
/// fraction gives the volume of fuel consumed per second. Volume units must
/// match the fuel tank's units.
/// @param The parent frame -- likely an instance of Rigid_Body.
Engine(double mass, const Vamos_Geometry::Three_Vector& position, double max_power,
double peak_engine_rpm, double rpm_limit, double inertia, double idle_throttle,
double start_rpm, double stall_rpm, double fuel_consumption);
void propagate(double time);
void set_torque_curve(const std::vector<Vamos_Geometry::Two_Vector>& torque_points);
void set_friction(double friction) { m_friction = friction; }
/// Handle the input parameters.
/// @param gas The throttle position.
/// @param transmission_speed The rotational speed of the transmission side of the
/// clutch.
/// @param drag The torque due to friction when the clutch is not fully engaged.
/// @param engaged True when the clutch is fully engaged, false otherwise.
void input(double gas, double drag, double transmission_speed, bool engaged);
/// @return The current rotational speed in radians per second.
double rotational_speed() const { return m_rotational_speed; }
/// @return The engine speed where the rev limiter kicks in.
double max_rotational_speed() const { return m_engine_speed_limit; }
double peak_engine_speed() const { return m_peak_engine_speed; }
double stall_speed() const { return m_stall_speed; }
/// @return The current torque.
double drive_torque() const { return m_drive_torque; }
double drive_impulse() const { return m_drive_impulse; }
/// @return The torque for a given throttle setting, \p gas, and engine speed
/// \p rotational_speed.
double torque_map(double gas, double rotational_speed);
double power(double gas, double rotational_speed);
double throttle() const { return m_gas; }
/// @return The current rate of fuel consumption.
double fuel_rate() const;
/// Tell the engine if we're out of gas.
void out_of_gas(bool out) { m_out_of_gas = out; }
bool is_out_of_gas() const { return m_out_of_gas; }
/// Start the engine.
void start();
private:
/// Set the engine speed to \p speed_in and calculate the resulting impulse.
void speed(double speed_in);
/// Used to calculate torque in torque_map().
double m_max_power;
/// Used to calculate torque in torque_map().
double m_peak_engine_speed;
/// The highest allowed engine speed (rev limit).
double m_engine_speed_limit;
/// The rotational inertia of the engine.
double m_inertia;
/// The fraction of throttle used when idling.
double m_idle_throttle;
/// The rotational speed that the engine is set to when starting.
double m_start_speed;
/// The engine shuts off if the rotational speed goes below this value.
double m_stall_speed;
/// The rate of fuel consumption.
double m_fuel_consumption;
/// The rotational speed of the engine.
double m_rotational_speed = 0.0;
/// The throttle position.
double m_gas = 0.0;
/// The load on the engine from the clutch.
double m_drag = 0.0;
double m_transmission_speed = 0.0;
/// true if the gas tank is empty, false otherwise.
bool m_out_of_gas = false;
/// The current torque produced by the engine.
double m_drive_torque = 0.0;
/// The impulse calculated in the last call to torque ().
double m_drive_impulse = 0.0;
/// true if the clutch is fully engaged, false otherwise.
bool m_engaged = false;
Vamos_Geometry::Spline m_torque_curve;
double m_friction;
};
} // namespace Vamos_Body
#endif // VAMOS_BODY_ENGINE_HPP_INCLUDED