Class: DrivingPhysics::Motor

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

Defined Under Namespace

Classes: OverRev, SanityCheck, Stall

Constant Summary collapse

TORQUES =
[  0,   70,  130,  200,  250,  320,  330,  320,  260,    0]
RPMS =
[500, 1000, 1500, 2000, 2500, 3500, 5000, 6000, 7000, 7100]
ENGINE_BRAKING =

20% of the torque at a given RPM

0.2

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(env) ⇒ Motor

Returns a new instance of Motor.



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/driving_physics/motor.rb', line 17

def initialize(env)
  @env = env

  @torques = TORQUES
  @rpms = RPMS
  @fixed_mass = 125

  # represent all rotating mass as one big flywheel
  @spinner = Disk.new(@env) { |fly|
    fly.radius =  0.25 # m
    fly.mass   = 75    # kg
    fly.base_friction  = 5/1000r
    fly.omega_friction = 2/10_000r
  }
  @starter_torque = 500  # Nm
  @idle_rpm       = 1000 # RPM
  @throttle       = 0.0  # 0.0 - 1.0 (0% - 100%)
end

Instance Attribute Details

#envObject (readonly)

Returns the value of attribute env.



13
14
15
# File 'lib/driving_physics/motor.rb', line 13

def env
  @env
end

#fixed_massObject

Returns the value of attribute fixed_mass.



14
15
16
# File 'lib/driving_physics/motor.rb', line 14

def fixed_mass
  @fixed_mass
end

#idle_rpmObject

Returns the value of attribute idle_rpm.



14
15
16
# File 'lib/driving_physics/motor.rb', line 14

def idle_rpm
  @idle_rpm
end

#rpmsObject

Returns the value of attribute rpms.



14
15
16
# File 'lib/driving_physics/motor.rb', line 14

def rpms
  @rpms
end

#spinnerObject

Returns the value of attribute spinner.



14
15
16
# File 'lib/driving_physics/motor.rb', line 14

def spinner
  @spinner
end

#starter_torqueObject

Returns the value of attribute starter_torque.



14
15
16
# File 'lib/driving_physics/motor.rb', line 14

def starter_torque
  @starter_torque
end

#throttleObject

Returns the value of attribute throttle.



13
14
15
# File 'lib/driving_physics/motor.rb', line 13

def throttle
  @throttle
end

#torquesObject

Returns the value of attribute torques.



14
15
16
# File 'lib/driving_physics/motor.rb', line 14

def torques
  @torques
end

Instance Method Details

#alpha(torque, omega: 0) ⇒ Object

given torque, determine crank alpha after inertia and friction



65
66
67
# File 'lib/driving_physics/motor.rb', line 65

def alpha(torque, omega: 0)
  @spinner.alpha(torque + @spinner.rotating_friction(omega))
end

#implied_torque(alpha) ⇒ Object



69
70
71
# File 'lib/driving_physics/motor.rb', line 69

def implied_torque(alpha)
  @spinner.implied_torque(alpha)
end

#massObject



53
54
55
# File 'lib/driving_physics/motor.rb', line 53

def mass
  @spinner.mass + @fixed_mass
end

#rotational_inertiaObject



49
50
51
# File 'lib/driving_physics/motor.rb', line 49

def rotational_inertia
  @spinner.rotational_inertia
end

#to_sObject



36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/driving_physics/motor.rb', line 36

def to_s
  ary = [format("Throttle: %.1f%%", @throttle * 100)]
  ary << "Torque:"
  @rpms.each_with_index { |r, i|
    ary << format("%s Nm %s RPM",
                  @torques[i].round(1).to_s.rjust(4, ' '),
                  r.to_s.rjust(5, ' '))
  }
  ary << format("Mass: %.1f kg  Fixed: %d kg", self.mass, @fixed_mass)
  ary << format("Rotating: %s", @spinner)
  ary.join("\n")
end

#torque(rpm) ⇒ Object

interpolate based on torque curve points

Raises:



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/driving_physics/motor.rb', line 74

def torque(rpm)
  raise(Stall, "RPM #{rpm}") if rpm < @rpms.first
  raise(OverRev, "RPM #{rpm}") if rpm > @rpms.last

  last_rpm = 99999
  last_tq = -1
  torque = nil

  # ew; there must be a better way
  @rpms.each_with_index { |r, i|
    tq = @torques[i]
    if last_rpm <= rpm and rpm <= r
      proportion = Rational(rpm - last_rpm) / (r - last_rpm)
      torque = last_tq + (tq - last_tq) * proportion
      break
    end
    last_rpm = r
    last_tq = tq
  }
  raise(SanityCheck, "RPM #{rpm}") if torque.nil?

  if (@throttle <= 0.05) and (rpm > @idle_rpm * 1.5)
    # engine braking: 20% of torque
    -1 * torque * ENGINE_BRAKING
  else
    torque * @throttle
  end
end