Class: DrivingPhysics::Motor

Inherits:
Object
  • Object
show all
Defined in:
lib/driving_physics/motor.rb

Overview

represent all rotating mass as one big flywheel

Defined Under Namespace

Classes: OverRev, Stall

Constant Summary collapse

CLOSED_THROTTLE =

threshold for engine braking

0.01

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(env, torque_curve = nil) {|_self| ... } ⇒ Motor

Originally, torque_curve was a kwarg; but mruby currently has a bug where block_given? returns true in the presence of an unset default kwarg, or something like that. github.com/mruby/mruby/issues/5741

Yields:

  • (_self)

Yield Parameters:



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/driving_physics/motor.rb', line 106

def initialize(env, torque_curve = nil)
  @env          = env
  @torque_curve = torque_curve.nil? ? TorqueCurve.new : torque_curve
  @throttle     = 0.0  # 0.0 - 1.0 (0% - 100%)

  @fixed_mass = 125
  @flywheel = Disk.new(@env) { |fly|
    fly.mass = 12
    fly.radius = 0.20
    fly.base_friction = 1.0 / 1_000
    fly.omega_friction = 5.0 / 10_000
  }
  @crankshaft = Disk.new(@env) { |crank|
    crank.mass = 25
    crank.radius = 0.04
    crank.base_friction = 1.0 / 1_000
    crank.omega_friction = 5.0 / 10_000
  }

  @starter_torque = 500  # Nm

  yield self if block_given?
end

Instance Attribute Details

#envObject (readonly)

Returns the value of attribute env.



98
99
100
# File 'lib/driving_physics/motor.rb', line 98

def env
  @env
end

#fixed_massObject

Returns the value of attribute fixed_mass.



99
100
101
# File 'lib/driving_physics/motor.rb', line 99

def fixed_mass
  @fixed_mass
end

#spinnerObject

Returns the value of attribute spinner.



99
100
101
# File 'lib/driving_physics/motor.rb', line 99

def spinner
  @spinner
end

#starter_torqueObject

Returns the value of attribute starter_torque.



99
100
101
# File 'lib/driving_physics/motor.rb', line 99

def starter_torque
  @starter_torque
end

#throttleObject

Returns the value of attribute throttle.



98
99
100
# File 'lib/driving_physics/motor.rb', line 98

def throttle
  @throttle
end

#torque_curveObject (readonly)

Returns the value of attribute torque_curve.



98
99
100
# File 'lib/driving_physics/motor.rb', line 98

def torque_curve
  @torque_curve
end

Class Method Details

.engine_braking(rpm) ⇒ Object

What percentage of the nominal torque at a given RPM would slow the motor when off throttle? 0% at 0 RPM; 50% at 7000 RPM



94
95
96
# File 'lib/driving_physics/motor.rb', line 94

def self.engine_braking(rpm)
  (rpm / 14_000.0).clamp(0, 0.5)
end

Instance Method Details

#alpha(torque, omega: 0) ⇒ Object

given torque, determine crank alpha considering inertia and friction



179
180
181
# File 'lib/driving_physics/motor.rb', line 179

def alpha(torque, omega: 0)
  (torque + self.friction(omega)) / self.inertia
end

#energy(omega) ⇒ Object



153
154
155
# File 'lib/driving_physics/motor.rb', line 153

def energy(omega)
  @crankshaft.energy(omega) + @flywheel.energy(omega)
end

#friction(omega) ⇒ Object



157
158
159
160
# File 'lib/driving_physics/motor.rb', line 157

def friction(omega)
  @crankshaft.rotating_friction(omega) +
    @flywheel.rotating_friction(omega)
end

#idleObject



134
135
136
# File 'lib/driving_physics/motor.rb', line 134

def idle
  @torque_curve.idle
end

#implied_torque(alpha) ⇒ Object



183
184
185
# File 'lib/driving_physics/motor.rb', line 183

def implied_torque(alpha)
  alpha * self.inertia
end

#inertiaObject



149
150
151
# File 'lib/driving_physics/motor.rb', line 149

def inertia
  @crankshaft.rotational_inertia + @flywheel.rotational_inertia
end

#massObject



162
163
164
# File 'lib/driving_physics/motor.rb', line 162

def mass
  @fixed_mass + self.rotating_mass
end

#output_torque(rpm) ⇒ Object



187
188
189
# File 'lib/driving_physics/motor.rb', line 187

def output_torque(rpm)
  self.torque(rpm) + self.friction(DrivingPhysics.omega(rpm))
end

#redlineObject



130
131
132
# File 'lib/driving_physics/motor.rb', line 130

def redline
  @torque_curve.redline
end

#rotating_massObject



166
167
168
# File 'lib/driving_physics/motor.rb', line 166

def rotating_mass
  @crankshaft.mass + @flywheel.mass
end

#throttle_pct(places = 1) ⇒ Object



174
175
176
# File 'lib/driving_physics/motor.rb', line 174

def throttle_pct(places = 1)
  format("%.#{places}f%%", @throttle * 100)
end

#to_sObject



138
139
140
141
142
143
144
145
146
147
# File 'lib/driving_physics/motor.rb', line 138

def to_s
  peak_rpm, peak_tq = *@torque_curve.peak
  [format("Peak Torque: %d Nm @ %d RPM  Redline: %d",
          peak_tq, peak_rpm, @torque_curve.redline),
   format("   Throttle: %s  Mass: %.1f kg  (%d kg fixed)",
          self.throttle_pct, self.mass, @fixed_mass),
   format(" Crankshaft: %s", @crankshaft),
   format("   Flywheel: %s", @flywheel),
  ].join("\n")
end

#torque(rpm) ⇒ Object

this is our “input torque” and it depends on @throttle here is where engine braking is implemented

Raises:



193
194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/driving_physics/motor.rb', line 193

def torque(rpm)
  raise(Stall, "RPM #{rpm}") if rpm < @torque_curve.min
  raise(OverRev, "RPM #{rpm}") if rpm > @torque_curve.max

  # interpolate based on torque curve points
  torque = @torque_curve.torque(rpm)

  if (@throttle <= CLOSED_THROTTLE)
    -1 * torque * self.class.engine_braking(rpm)
  else
    torque * @throttle
  end
end