driving_physics 0.0.2.1 → 0.0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 89628c4f71193088741435eb426419edf7c9ac78cad2169c4718f2a365db0881
4
- data.tar.gz: a229fa52ed29f6dcb8eab0513e845732e0735dd272e516e4f26603aeabe7f312
3
+ metadata.gz: 9b9159b499a0082d5af3ef926fceab925572552978b50d020b71bc51df7506fb
4
+ data.tar.gz: 183eaae3e07e24f38bb1417d96a6310eebfd288a1300d4e8bab96f008abbf3e5
5
5
  SHA512:
6
- metadata.gz: 42a6061d1ef6e2c989e5fb88141e8a84daaafc3c9a2f31e057d2fb7a384fbaa1c195d05deab18b2703fd5e79b539557543ec8eaf8632cd2a5f776359c7c3e340
7
- data.tar.gz: 2860d2b6c17c5d4e9d73868de36bdcf48341d74712666c109d422c97975899b0fde2248b58c060d02e02561ba3dff471d7b66c694a44e5d143108a20f828e477
6
+ metadata.gz: 9a19ba4646abe21f30ca12c88f43e9ddc7083028e96504260f0277b167af5374364967b1617ab83744f824d6d2aa513ef38627d23ad5e9ccc8ff7e017b8a2ac8
7
+ data.tar.gz: 5357970cd547b12727bfc20c408df27a07d3aaac5d5b9042cbb10fc98c85484eb7bf054e140158f7e8695ef6c30eb18961fdd6979b4d0e3ab6c343f7767fc296
data/README.md CHANGED
@@ -10,14 +10,28 @@ using `Vector` class from `matrix.rb` in stdlib.
10
10
 
11
11
  This is very much a **Work In Progress**. Implemented so far:
12
12
 
13
+ ### Library Features
14
+
15
+ * Spinning: rotational inertia and friction / hysteresis
16
+ * Tires: traction force via friction (static and kinetic) and the normal force
17
+ * Vectors: 2D Vector forces and 3D Vector torques
18
+ * Motor: torque curves, rotating mass with friction
19
+ * Gearbox: gear ratios, final drive, rotating mass with friction
20
+ * Powertrain: combines motor and gearbox
21
+ * Car: 4 tires, powertrain, extra mass presents a load to the powertrain
22
+ * Acceleration: via drive traction from "first principles"
23
+ * Variable clutch and throttle
24
+ * Engine braking
25
+ * Power and Energy
26
+
13
27
  ### mruby Support
14
28
 
15
- This is big. This library is primarily a Ruby library, intended for use with
16
- CRuby (MRI), JRuby, etc. **mruby** is the redheaded stepchild, with severe
29
+ This library is primarily a Ruby library, intended for use with CRuby (MRI),
30
+ JRuby, etc. **mruby** is the redheaded stepchild, with significant
17
31
  implications for a codebase that wants to support both sides. Supporting
18
32
  mruby here meant:
19
33
 
20
- 1. Editing the codebase (minimally) to remove *mruby-deadends*.
34
+ 1. Editing the codebase (minimally) to avoid and remove *mruby-deadends*.
21
35
  2. Creating `rake` tasks to process normal .rb files into *mruby-compatible*
22
36
  .rb files
23
37
  3. Assembling all needed library .rb files into a master .rb file
@@ -27,17 +41,6 @@ mruby here meant:
27
41
 
28
42
  See the main Rakefile near the top for mruby stuff.
29
43
 
30
- ### Library Features
31
-
32
- * Spinning: rotational inertia and friction / hysteresis
33
- * Tires: traction force via friction (static and kinetic) and the normal force
34
- * Vectors: 2D Vector forces and 3D Vector torques
35
- * Motor: torque curves, rotating mass with friction
36
- * Gearbox: gear ratios, final drive, rotating mass with friction
37
- * Powertrain: combines motor and gearbox
38
- * Car: 4 tires, powertrain, extra mass presents a load to the powertrain
39
- * Acceleration: via drive traction from "first principles"
40
-
41
44
  ## Rationale
42
45
 
43
46
  This is a toy project intended to scratch a personal itch: I want to create
data/Rakefile CHANGED
@@ -40,8 +40,8 @@ end
40
40
 
41
41
  file MRBLIB_FILE do
42
42
  line_count = write_mruby(File.join(%w[lib driving_physics.rb]), MRBLIB_FILE)
43
- %w[mruby environment imperial power
44
- disk tire motor gearbox powertrain car].each { |name|
43
+ %w[cli environment imperial power timer
44
+ disk tire motor gearbox powertrain car pid_controller].each { |name|
45
45
  file = File.join('lib', 'driving_physics', "#{name}.rb")
46
46
  line_count += write_mruby(file, MRBLIB_FILE, append: true)
47
47
  puts "wrote #{file} to #{MRBLIB_FILE}"
@@ -67,7 +67,7 @@ task mrblib: MRBLIB_FILE
67
67
  desc "Compile mruby/mrblib/driving_physics.rb to .mrb bytecode"
68
68
  task mrbc: MRBLIB_MRB
69
69
 
70
- %w[disk tire motor gearbox powertrain car].each { |name|
70
+ %w[disk tire motor gearbox powertrain car pid_controller].each { |name|
71
71
  demo_file = File.join(MRUBY_DEMO_DIR, "#{name}.rb")
72
72
  demo_mrb = File.join(MRUBY_DEMO_DIR, "#{name}.mrb")
73
73
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.2.1
1
+ 0.0.3.1
data/demo/car.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'driving_physics/car'
2
+ require 'driving_physics/cockpit'
2
3
  require 'driving_physics/imperial'
3
4
  require 'driving_physics/cli'
4
5
 
@@ -10,13 +11,16 @@ puts env
10
11
  tire = Tire.new(env)
11
12
  motor = Motor.new(env)
12
13
  gearbox = Gearbox.new(env)
13
- powertrain = Powertrain.new(motor, gearbox)
14
+ powertrain = Powertrain.new(motor: motor, gearbox: gearbox)
14
15
  car = Car.new(tire: tire, powertrain: powertrain) { |c|
15
16
  c.body_mass = 850.0
16
17
  c.frontal_area = 2.5
17
18
  c.cd = 0.5
18
19
  }
19
20
  puts car
21
+
22
+ cockpit = Cockpit.new(car)
23
+ puts cockpit
20
24
  CLI.pause
21
25
 
22
26
  duration = 120
@@ -31,18 +35,19 @@ tire_theta = 0.0
31
35
 
32
36
  crank_alpha = 0.0
33
37
  crank_omega = 0.0
34
- crank_theta = 0.0
35
38
 
36
39
  start = Timer.now
37
40
  paused = 0.0
38
41
  num_ticks = duration * env.hz + 1
39
42
 
40
- clutch = :ok
43
+ rev_match = :ok
41
44
  phase = :ignition
45
+ gearbox.clutch = 0.0 # clutch in to fire up motor
42
46
  flag = false
43
- rpm = 0
44
-
45
47
 
48
+ rpm, crank_torque = 0, 0
49
+ axle_torque, drive_force, net_force = 0, 0, 0
50
+ ar, rr, rf, ir = 0, 0, 0, 0
46
51
 
47
52
  puts <<EOF
48
53
 
@@ -54,24 +59,15 @@ EOF
54
59
 
55
60
  num_ticks.times { |i|
56
61
  if phase == :ignition
57
- # ignition phase
58
62
  crank_alpha = motor.alpha(motor.starter_torque, omega: crank_omega)
59
63
  crank_omega += crank_alpha * env.tick
60
- crank_theta += crank_omega * env.tick
61
64
 
62
65
  rpm = DrivingPhysics.rpm(crank_omega)
63
66
 
64
- if i % 100 == 0 or rpm > motor.idle_rpm
65
- puts Timer.display(ms: i)
66
- puts format("%d rad %d rad/s %d rad/s/s",
67
- crank_theta, crank_omega, crank_alpha)
68
- puts format("%d RPM %d Nm starter torque", rpm, motor.starter_torque)
69
- puts
70
- end
71
-
72
- if rpm > motor.idle_rpm
73
- car.gear = 1
74
- car.throttle = 1.0
67
+ if rpm > motor.idle
68
+ flag = true
69
+ cockpit.gear = 1
70
+ cockpit.throttle_pedal = 1.0
75
71
  phase = :running
76
72
 
77
73
  puts <<EOF
@@ -82,23 +78,19 @@ num_ticks.times { |i|
82
78
 
83
79
  EOF
84
80
  end
85
- elsif phase == :running
86
- # track crank_alpha/omega/theta
87
-
88
- # cut throttle after 60 s
89
- car.throttle = 0 if i > 60 * env.hz and car.throttle == 1.0
90
-
81
+ elsif phase == :running or phase == :off_throttle
91
82
  ar = car.air_force(speed)
92
83
  rr = car.tire_rolling_force(tire_omega)
93
84
  rf = car.tire_rotational_force(tire_omega)
94
85
 
95
86
  # note, this fails if we're in neutral
96
- force = car.drive_force(rpm) + ar + rr + rf
87
+ drive_force = car.drive_force(rpm, axle_omega: tire_omega)
88
+ net_force = drive_force + ar + rr + rf
97
89
 
98
- ir = car.tire_inertial_force(force)
99
- force += ir
90
+ ir = car.tire_inertial_force(net_force)
91
+ net_force += ir
100
92
 
101
- acc = DrivingPhysics.acc(force, car.total_mass)
93
+ acc = DrivingPhysics.acc(net_force, car.total_mass)
102
94
  speed += acc * env.tick
103
95
  dist += speed * env.tick
104
96
 
@@ -108,71 +100,89 @@ EOF
108
100
 
109
101
  crank_alpha = tire_alpha / car.powertrain.gearbox.ratio
110
102
  crank_omega += crank_alpha * env.tick
111
- crank_theta += crank_omega * env.tick
112
-
113
- axle_torque = car.powertrain.axle_torque(rpm)
114
- crank_torque = car.powertrain.motor.torque(rpm)
115
-
116
- if flag or (i < 5000 and i % 100 == 0) or (i % 1000 == 0)
117
- puts Timer.display(ms: i)
118
- puts format(" Tire: %.1f r/s/s %.2f r/s %.3f r",
119
- tire_alpha, tire_omega, tire_theta)
120
- puts format(" Car: %.1f m/s/s %.2f m/s %.3f m (%.1f MPH)",
121
- acc, speed, dist, Imperial.mph(speed))
122
- puts format(" Motor: %d RPM %.1f Nm", rpm, crank_torque)
123
- puts format(" Axle: %.1f Nm (%d N) Net Force: %.1f N",
124
- axle_torque, car.drive_force(rpm), force)
125
- puts "Resist: " + format(%w[Air Roll Spin Inertial].map { |s|
126
- "#{s}: %.1f N"
127
- }.join(' '), ar, rr, rf, ir)
128
- puts
129
- flag = false
130
- end
131
103
 
132
104
  # tire_omega determines new rpm
133
- new_rpm = car.powertrain.crank_rpm(tire_omega)
134
- new_clutch, proportion = car.powertrain.gearbox.match_rpms(rpm, new_rpm)
105
+ new_rpm = gearbox.crank_rpm(tire_omega, crank_rpm: rpm)
106
+ new_rev_match, clutch, proportion = Cockpit.rev_match(rpm, new_rpm)
135
107
 
136
- if new_clutch != clutch
108
+ if new_rev_match != rev_match
137
109
  flag = true
138
- puts format("Clutch: [%s] %d RPM is %.1f%% from %d RPM",
139
- new_clutch, new_rpm, proportion * 100, rpm)
140
- clutch = new_clutch
141
- paused += CLI.pause
110
+ puts format("Rev Match: [%s] %d RPM is %.1f%% from %d RPM",
111
+ new_rev_match, new_rpm, proportion * 100, rpm)
112
+ # puts format("Recommend clutch to %.1f%%", clutch * 100)
113
+ rev_match = new_rev_match
142
114
  end
143
115
 
144
- case new_clutch
145
- when :ok
146
- rpm = new_rpm
147
- when :mismatch
116
+ clutch_diff = clutch - gearbox.clutch
117
+ if clutch_diff.abs > 0.1
148
118
  flag = true
149
- puts '#'
150
- puts '# LURCH!'
151
- puts '#'
152
- puts
153
- rpm = new_rpm
119
+ puts format("Clutch: %.1f%% Recommended Clutch: %.1f%%",
120
+ gearbox.clutch * 100, clutch * 100)
154
121
  end
155
- next_gear = car.powertrain.gearbox.next_gear(rpm)
156
- if next_gear != gearbox.gear
122
+ # the clutch pedal will reflect this change
123
+ gearbox.clutch += clutch_diff * 0.5
124
+
125
+ # update the motor RPM based on new clutch
126
+ new_rpm = gearbox.crank_rpm(tire_omega, crank_rpm: rpm)
127
+ rpm = new_rpm if new_rpm > motor.idle
128
+
129
+ new_gear = cockpit.choose_gear(rpm)
130
+ if new_gear != cockpit.gear
131
+ flag = true
132
+ puts "Gear Change: #{new_gear}"
133
+ cockpit.gear = new_gear
134
+ end
135
+
136
+ # cut throttle after 60 s
137
+ if i > 60 * env.hz and car.throttle == 1.0
157
138
  flag = true
158
- puts "Gear Change: #{next_gear}"
159
- car.gear = next_gear
160
- paused += CLI.pause
139
+ phase = :off_throttle
140
+ cockpit.throttle_pedal = 0
161
141
  end
162
142
 
163
143
  # maintain idle when revs drop
164
- if car.throttle == 0 and rpm < motor.idle_rpm
144
+ if cockpit.throttle_pedal == 0 and rpm < motor.idle
165
145
  phase = :idling
166
146
  car.gear = 0
167
- paused += CLI.pause
168
147
  end
169
148
 
149
+ print "===\n\n" if flag
170
150
 
171
151
  elsif phase == :idling
172
- # fake
173
- rpm = motor.idle_rpm
152
+ # fake; exit
153
+ rpm = motor.idle
174
154
  break
175
155
  end
156
+
157
+ if flag or (i < 5000 and i % 100 == 0) or (i % 1000 == 0)
158
+ puts Timer.display(ms: i)
159
+ puts format(" Phase: %s", phase)
160
+ puts format(" Tire: %.3f r/s/s %.2f r/s %.1f r",
161
+ tire_alpha, tire_omega, tire_theta)
162
+ puts format(" Car: %.3f m/s/s %.2f m/s %.1f m (%.1f MPH)",
163
+ acc, speed, dist, Imperial.mph(speed))
164
+ if phase == :ignition
165
+ puts format(" Motor: %d RPM Starter: %d Nm Friction: %.1f Nm",
166
+ rpm, motor.starter_torque, motor.friction(crank_omega))
167
+ else
168
+ crank_torque = car.powertrain.motor.torque(rpm)
169
+ puts format(" Motor: %d RPM %.1f Nm Friction: %.1f Nm",
170
+ rpm, crank_torque, motor.friction(crank_omega))
171
+ end
172
+ puts format("Gearbox: %s", gearbox.inputs)
173
+ if phase != :ignition
174
+ axle_torque = car.powertrain.axle_torque(rpm, axle_omega: tire_omega)
175
+ puts format(" Axle: %.1f Nm (%d N) Net Force: %.1f N",
176
+ axle_torque, drive_force, net_force)
177
+ end
178
+ puts " Resist: " + format(%w[Air Roll Spin Inertial].map { |s|
179
+ "#{s}: %.1f N"
180
+ }.join(' '), ar, rr, rf, ir)
181
+ puts cockpit
182
+ puts
183
+ paused += CLI.pause if flag
184
+ flag = false
185
+ end
176
186
  }
177
187
 
178
188
  puts Timer.summary(start, num_ticks, paused)
data/demo/motor.rb CHANGED
@@ -48,7 +48,7 @@ motor.throttle = 1.0
48
48
  puts
49
49
  puts "Now, the simulation begins..."
50
50
  puts "---"
51
- puts "* Spin the motor up to #{motor.idle_rpm} RPM with the starter motor."
51
+ puts "* Spin the motor up to #{motor.idle} RPM with the starter motor."
52
52
  puts "* Rev it up with the throttle."
53
53
  puts "* Let it die."
54
54
  CLI.pause
@@ -89,7 +89,7 @@ num_ticks.times { |i|
89
89
  rpm = DrivingPhysics.rpm(omega)
90
90
  power = DrivingPhysics.power(net_torque, omega)
91
91
 
92
- if rpm > motor.idle_rpm and status == :ignition
92
+ if rpm > motor.idle and status == :ignition
93
93
  status = :running
94
94
  flag = true
95
95
  end
@@ -106,10 +106,13 @@ num_ticks.times { |i|
106
106
  flag = true
107
107
  end
108
108
 
109
+ # we don't need no PID control
109
110
  if status == :idling
110
- if rpm < 999
111
+ if rpm.round <= 999
111
112
  motor.throttle += (1.0 - motor.throttle) * 0.005
112
- elsif rpm > 1001
113
+ elsif rpm.round == 1000
114
+ motor.throttle += (rand - 0.5) * 0.0005
115
+ else
113
116
  motor.throttle -= motor.throttle * 0.005
114
117
  end
115
118
  end
data/demo/mruby/car.rb ADDED
@@ -0,0 +1,184 @@
1
+
2
+ include DrivingPhysics
3
+
4
+ env = Environment.new
5
+ puts env
6
+
7
+ tire = Tire.new(env)
8
+ motor = Motor.new(env)
9
+ gearbox = Gearbox.new(env)
10
+ powertrain = Powertrain.new(motor: motor, gearbox: gearbox)
11
+ car = Car.new(tire: tire, powertrain: powertrain) { |c|
12
+ c.body_mass = 850.0
13
+ c.frontal_area = 2.5
14
+ c.cd = 0.5
15
+ }
16
+ puts car
17
+
18
+ cockpit = Cockpit.new(car)
19
+ puts cockpit
20
+ CLI.pause
21
+
22
+ duration = 120
23
+
24
+ acc = 0.0
25
+ speed = 0.0
26
+ dist = 0.0
27
+
28
+ tire_alpha = 0.0
29
+ tire_omega = 0.0
30
+ tire_theta = 0.0
31
+
32
+ crank_alpha = 0.0
33
+ crank_omega = 0.0
34
+
35
+ start = Timer.now
36
+ paused = 0.0
37
+ num_ticks = duration * env.hz + 1
38
+
39
+ rev_match = :ok
40
+ phase = :ignition
41
+ gearbox.clutch = 0.0 # clutch in to fire up motor
42
+ flag = false
43
+
44
+ rpm, crank_torque = 0, 0
45
+ axle_torque, drive_force, net_force = 0, 0, 0
46
+ ar, rr, rf, ir = 0, 0, 0, 0
47
+
48
+ puts <<EOF
49
+
50
+ #
51
+ # IGNITION
52
+ #
53
+
54
+ EOF
55
+
56
+ num_ticks.times { |i|
57
+ if phase == :ignition
58
+ crank_alpha = motor.alpha(motor.starter_torque, omega: crank_omega)
59
+ crank_omega += crank_alpha * env.tick
60
+
61
+ rpm = DrivingPhysics.rpm(crank_omega)
62
+
63
+ if rpm > motor.idle
64
+ flag = true
65
+ cockpit.gear = 1
66
+ cockpit.throttle_pedal = 1.0
67
+ phase = :running
68
+
69
+ puts <<EOF
70
+
71
+ #
72
+ # RUNNING
73
+ #
74
+
75
+ EOF
76
+ end
77
+ elsif phase == :running or phase == :off_throttle
78
+ ar = car.air_force(speed)
79
+ rr = car.tire_rolling_force(tire_omega)
80
+ rf = car.tire_rotational_force(tire_omega)
81
+
82
+ # note, this fails if we're in neutral
83
+ drive_force = car.drive_force(rpm, axle_omega: tire_omega)
84
+ net_force = drive_force + ar + rr + rf
85
+
86
+ ir = car.tire_inertial_force(net_force)
87
+ net_force += ir
88
+
89
+ acc = DrivingPhysics.acc(net_force, car.total_mass)
90
+ speed += acc * env.tick
91
+ dist += speed * env.tick
92
+
93
+ tire_alpha = acc / car.tire.radius
94
+ tire_omega += tire_alpha * env.tick
95
+ tire_theta += tire_omega * env.tick
96
+
97
+ crank_alpha = tire_alpha / car.powertrain.gearbox.ratio
98
+ crank_omega += crank_alpha * env.tick
99
+
100
+ # tire_omega determines new rpm
101
+ new_rpm = gearbox.crank_rpm(tire_omega, crank_rpm: rpm)
102
+ new_rev_match, clutch, proportion = Cockpit.rev_match(rpm, new_rpm)
103
+
104
+ if new_rev_match != rev_match
105
+ flag = true
106
+ puts format("Rev Match: [%s] %d RPM is %.1f%% from %d RPM",
107
+ new_rev_match, new_rpm, proportion * 100, rpm)
108
+ # puts format("Recommend clutch to %.1f%%", clutch * 100)
109
+ rev_match = new_rev_match
110
+ end
111
+
112
+ clutch_diff = clutch - gearbox.clutch
113
+ if clutch_diff.abs > 0.1
114
+ flag = true
115
+ puts format("Clutch: %.1f%% Recommended Clutch: %.1f%%",
116
+ gearbox.clutch * 100, clutch * 100)
117
+ end
118
+ # the clutch pedal will reflect this change
119
+ gearbox.clutch += clutch_diff * 0.5
120
+
121
+ # update the motor RPM based on new clutch
122
+ new_rpm = gearbox.crank_rpm(tire_omega, crank_rpm: rpm)
123
+ rpm = new_rpm if new_rpm > motor.idle
124
+
125
+ new_gear = cockpit.choose_gear(rpm)
126
+ if new_gear != cockpit.gear
127
+ flag = true
128
+ puts "Gear Change: #{new_gear}"
129
+ cockpit.gear = new_gear
130
+ end
131
+
132
+ # cut throttle after 60 s
133
+ if i > 60 * env.hz and car.throttle == 1.0
134
+ flag = true
135
+ phase = :off_throttle
136
+ cockpit.throttle_pedal = 0
137
+ end
138
+
139
+ # maintain idle when revs drop
140
+ if cockpit.throttle_pedal == 0 and rpm < motor.idle
141
+ phase = :idling
142
+ car.gear = 0
143
+ end
144
+
145
+ print "===\n\n" if flag
146
+
147
+ elsif phase == :idling
148
+ # fake; exit
149
+ rpm = motor.idle
150
+ break
151
+ end
152
+
153
+ if flag or (i < 5000 and i % 100 == 0) or (i % 1000 == 0)
154
+ puts Timer.display(ms: i)
155
+ puts format(" Phase: %s", phase)
156
+ puts format(" Tire: %.3f r/s/s %.2f r/s %.1f r",
157
+ tire_alpha, tire_omega, tire_theta)
158
+ puts format(" Car: %.3f m/s/s %.2f m/s %.1f m (%.1f MPH)",
159
+ acc, speed, dist, Imperial.mph(speed))
160
+ if phase == :ignition
161
+ puts format(" Motor: %d RPM Starter: %d Nm Friction: %.1f Nm",
162
+ rpm, motor.starter_torque, motor.friction(crank_omega))
163
+ else
164
+ crank_torque = car.powertrain.motor.torque(rpm)
165
+ puts format(" Motor: %d RPM %.1f Nm Friction: %.1f Nm",
166
+ rpm, crank_torque, motor.friction(crank_omega))
167
+ end
168
+ puts format("Gearbox: %s", gearbox.inputs)
169
+ if phase != :ignition
170
+ axle_torque = car.powertrain.axle_torque(rpm, axle_omega: tire_omega)
171
+ puts format(" Axle: %.1f Nm (%d N) Net Force: %.1f N",
172
+ axle_torque, drive_force, net_force)
173
+ end
174
+ puts " Resist: " + format(%w[Air Roll Spin Inertial].map { |s|
175
+ "#{s}: %.1f N"
176
+ }.join(' '), ar, rr, rf, ir)
177
+ puts cockpit
178
+ puts
179
+ paused += CLI.pause if flag
180
+ flag = false
181
+ end
182
+ }
183
+
184
+ puts Timer.summary(start, num_ticks, paused)
data/demo/mruby/motor.rb CHANGED
@@ -45,7 +45,7 @@ motor.throttle = 1.0
45
45
  puts
46
46
  puts "Now, the simulation begins..."
47
47
  puts "---"
48
- puts "* Spin the motor up to #{motor.idle_rpm} RPM with the starter motor."
48
+ puts "* Spin the motor up to #{motor.idle} RPM with the starter motor."
49
49
  puts "* Rev it up with the throttle."
50
50
  puts "* Let it die."
51
51
  CLI.pause
@@ -86,7 +86,7 @@ num_ticks.times { |i|
86
86
  rpm = DrivingPhysics.rpm(omega)
87
87
  power = DrivingPhysics.power(net_torque, omega)
88
88
 
89
- if rpm > motor.idle_rpm and status == :ignition
89
+ if rpm > motor.idle and status == :ignition
90
90
  status = :running
91
91
  flag = true
92
92
  end
@@ -103,10 +103,13 @@ num_ticks.times { |i|
103
103
  flag = true
104
104
  end
105
105
 
106
+ # we don't need no PID control
106
107
  if status == :idling
107
- if rpm < 999
108
+ if rpm.round <= 999
108
109
  motor.throttle += (1.0 - motor.throttle) * 0.005
109
- elsif rpm > 1001
110
+ elsif rpm.round == 1000
111
+ motor.throttle += (rand - 0.5) * 0.0005
112
+ else
110
113
  motor.throttle -= motor.throttle * 0.005
111
114
  end
112
115
  end