driving_physics 0.0.1.2 → 0.0.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,34 @@
1
+ module DrivingPhysics
2
+ module Timer
3
+ # don't use `defined?` with mruby
4
+ if (Process::CLOCK_MONOTONIC rescue false)
5
+ def self.now
6
+ Process.clock_gettime Process::CLOCK_MONOTONIC
7
+ end
8
+ else
9
+ def self.now
10
+ Time.now
11
+ end
12
+ end
13
+
14
+ def self.since(t)
15
+ self.now - t
16
+ end
17
+
18
+ def self.elapsed(&work)
19
+ t = self.now
20
+ return yield, self.since(t)
21
+ end
22
+
23
+ # HH:MM:SS.mmm
24
+ def self.display(seconds: 0, ms: 0)
25
+ ms += (seconds * 1000).round if seconds > 0
26
+ DrivingPhysics.elapsed_display(ms)
27
+ end
28
+
29
+ def self.summary(start, num_ticks, paused = 0)
30
+ elapsed = self.since(start) - paused
31
+ format("%.3f s (%d ticks/s)", elapsed, num_ticks.to_f / elapsed)
32
+ end
33
+ end
34
+ end
@@ -26,14 +26,14 @@ module DrivingPhysics
26
26
 
27
27
  def initialize(env)
28
28
  @env = env
29
- @radius = 350/1000r # m
30
- @width = 200/1000r # m
29
+ @radius = 0.35
30
+ @width = 0.2
31
31
  @density = DENSITY
32
32
  @temp = @env.air_temp
33
- @mu_s = 11/10r # static friction
34
- @mu_k = 7/10r # kinetic friction
35
- @base_friction = 5/10_000r
36
- @omega_friction = 5/100_000r # scales with speed
33
+ @mu_s = 1.1 # static friction
34
+ @mu_k = 0.7 # kinetic friction
35
+ @base_friction = 5.0/10_000
36
+ @omega_friction = 5.0/100_000
37
37
  @roll_cof = DrivingPhysics::ROLL_COF
38
38
 
39
39
  yield self if block_given?
@@ -64,6 +64,29 @@ module DrivingPhysics
64
64
  dir
65
65
  end
66
66
 
67
+ def self.torque_vector(force, radius)
68
+ if !force.is_a?(Vector) or force.size != 2
69
+ raise(ArgumentError, "force must be a 2D vector")
70
+ end
71
+ if !radius.is_a?(Vector) or radius.size != 2
72
+ raise(ArgumentError, "radius must be a 2D vector")
73
+ end
74
+ force = Vector[force[0], force[1], 0]
75
+ radius = Vector[radius[0], radius[1], 0]
76
+ force.cross(radius)
77
+ end
78
+
79
+ def self.force_vector(torque, radius)
80
+ if !torque.is_a?(Vector) or torque.size != 3
81
+ raise(ArgumentError, "torque must be a 3D vector")
82
+ end
83
+ if !radius.is_a?(Vector) or radius.size != 2
84
+ raise(ArgumentError, "radius must be a 2D vector")
85
+ end
86
+ radius = Vector[radius[0], radius[1], 0]
87
+ radius.cross(torque) / radius.dot(radius)
88
+ end
89
+
67
90
  module VectorForce
68
91
  #
69
92
  # Resistance Forces
@@ -1,37 +1,36 @@
1
+ #
2
+ # Units: metric
3
+ #
4
+ # distance: meter
5
+ # velocity: meter / sec
6
+ # acceleration: meter / sec^2
7
+ # volume: Liter
8
+ # temperature: Celsius
9
+ #
1
10
  module DrivingPhysics
2
- #
3
- # Units: metric
4
- #
5
- # distance: meter
6
- # velocity: meter / sec
7
- # acceleration: meter / sec^2
8
- # volume: Liter
9
- # temperature: Celsius
10
- #
11
+ # runtime check; this returns false by default
12
+ # Vector is not currently/easily available in mruby
13
+ def self.has_vector?
14
+ Vector rescue false
15
+ end
11
16
 
12
- #
13
17
  # environmental defaults
14
- #
15
18
  HZ = 1000
16
19
  TICK = Rational(1) / HZ
17
20
  G = 9.8 # m/s^2
18
21
  AIR_TEMP = 25 # deg c
19
22
  AIR_DENSITY = 1.29 # kg / m^3
20
- PETROL_DENSITY = 0.71 # kg / L TODO: move to car.rb
23
+ PETROL_DENSITY = 0.71 # kg / L
21
24
 
22
- #
23
25
  # defaults for resistance forces
24
- #
25
- FRONTAL_AREA = 2.2 # m^2, based roughly on 2000s-era Chevrolet Corvette
26
- DRAG_COF = 0.3 # based roughly on 2000s-era Chevrolet Corvette
27
- DRAG = 0.4257 # air_resistance at 1 m/s given above numbers
28
- ROT_COF = 12.771 # if rotating resistance matches air resistance at 30 m/s
29
- ROT_CONST = 0.05 # N opposing drive force / torque
30
- ROLL_COF = 0.01 # roughly: street tires on concrete
26
+ FRONTAL_AREA = 2.2 # m^2, based roughly on 2000s-era Chevrolet Corvette
27
+ DRAG_COF = 0.3 # based roughly on 2000s-era Chevrolet Corvette
28
+ DRAG = 0.4257 # air_resistance at 1 m/s given above numbers
29
+ ROT_COF = 12.771 # if rot matches air at 30 m/s
30
+ ROT_CONST = 0.05 # N opposing drive force / torque
31
+ ROLL_COF = 0.01 # roughly: street tires on concrete
31
32
 
32
- #
33
33
  # constants
34
- #
35
34
  SECS_PER_MIN = 60
36
35
  MINS_PER_HOUR = 60
37
36
  SECS_PER_HOUR = SECS_PER_MIN * MINS_PER_HOUR
@@ -70,4 +69,11 @@ module DrivingPhysics
70
69
  alias_method(:omega, :accum)
71
70
  alias_method(:theta, :accum)
72
71
  end
72
+
73
+ def self.unit_interval!(val)
74
+ if val < 0.0 or val > 1.0
75
+ raise(ArgumentError, "val #{val.inspect} should be between 0 and 1")
76
+ end
77
+ val
78
+ end
73
79
  end
data/test/disk.rb CHANGED
@@ -1,113 +1,78 @@
1
1
  require 'minitest/autorun'
2
2
  require 'driving_physics/disk'
3
+ require 'matrix'
3
4
 
4
- D = DrivingPhysics::Disk
5
+ include DrivingPhysics
5
6
 
6
- describe D do
7
+ describe Disk do
7
8
  describe "Disk.volume" do
8
9
  it "calculates the volume (m^3) of disk given radius and width" do
9
- cubic_m = D.volume(1.0, 1.0)
10
+ cubic_m = Disk.volume(1.0, 1.0)
10
11
  expect(cubic_m).must_equal Math::PI
11
12
 
12
- cubic_m = D.volume(0.35, 0.2)
13
+ cubic_m = Disk.volume(0.35, 0.2)
13
14
  expect(cubic_m).must_be_within_epsilon 0.076969
14
15
  end
15
16
  end
16
17
 
17
18
  describe "Disk.volume_l" do
18
19
  it "calculates the volume (L) of a disk given radius and width" do
19
- liters = D.volume_l(1.0, 1.0)
20
+ liters = Disk.volume_l(1.0, 1.0)
20
21
  expect(liters).must_equal Math::PI * 1000
21
22
 
22
- liters = D.volume_l(0.35, 0.2)
23
+ liters = Disk.volume_l(0.35, 0.2)
23
24
  expect(liters).must_be_within_epsilon 76.96902
24
25
  end
25
26
  end
26
27
 
27
28
  describe "Disk.density" do
28
29
  it "calculates the density (kg/L) given mass and volume" do
29
- expect(D.density(25.0, 25.0)).must_equal 1.0
30
- expect(D.density(50.0, 25.0)).must_equal 2.0
30
+ expect(Disk.density(25.0, 25.0)).must_equal 1.0
31
+ expect(Disk.density(50.0, 25.0)).must_equal 2.0
31
32
  end
32
33
  end
33
34
 
34
35
  describe "Disk.mass" do
35
36
  it "calculates the mass (kg) of a disk given radius, width, and density" do
36
- skip
37
- expect(D.mass(0.35, 0.2, D::DENSITY)).must_be_within_epsilon 25.015
37
+ expect(Disk.mass(0.35, 0.2, Disk::DENSITY)).must_be_within_epsilon 76.969
38
38
  end
39
39
  end
40
40
 
41
41
  describe "Disk.rotational_inertia" do
42
42
  it "calculates rotational inertia for a disk given radius and mass" do
43
- expect(D.rotational_inertia(0.35, 25.0)).must_be_within_epsilon 1.53125
43
+ expect(Disk.rotational_inertia(0.35, 25.0)).must_be_within_epsilon 1.53125
44
44
  end
45
45
  end
46
46
 
47
47
  describe "Disk.alpha" do
48
48
  it "calculates angular acceleration from torque and inertia" do
49
49
  scalar_torque = 1000
50
- inertia = D.rotational_inertia(0.35, 25.0)
51
- expect(D.alpha scalar_torque, inertia).must_be_within_epsilon 653.061
50
+ inertia = Disk.rotational_inertia(0.35, 25.0)
51
+ expect(Disk.alpha scalar_torque, inertia).must_be_within_epsilon 653.061
52
52
 
53
+ skip unless DrivingPhysics.has_vector?
53
54
  vector_torque = Vector[0, 0, 1000]
54
- vector_alpha = D.alpha vector_torque, inertia
55
+ vector_alpha = Disk.alpha vector_torque, inertia
55
56
  expect(vector_alpha).must_be_instance_of Vector
56
57
  expect(vector_alpha.size).must_equal 3
57
58
  expect(vector_alpha[2]).must_be_within_epsilon 653.06
58
59
  end
59
60
  end
60
61
 
61
- describe "Disk.torque_vector" do
62
- it "calculates a torque in the 3rd dimension given 2D force and radius" do
63
- force = Vector[1000, 0]
64
- radius = Vector[0, 5]
65
- torque = D.torque_vector(force, radius)
66
- expect(torque).must_be_instance_of Vector
67
- expect(torque.size).must_equal 3
68
- expect(torque[2]).must_be_within_epsilon 5000.0
69
- end
70
- end
71
-
72
- describe "Disk.force_vector" do
73
- it "calculates a (3D) force given 3D torque and 2D radius" do
74
- # let's invert the Disk.torque_vector case from above:
75
- torque = Vector[0, 0, 5000]
76
- radius = Vector[0, 5]
77
- force = D.force_vector(torque, radius)
78
- expect(force).must_be_instance_of Vector
79
- expect(force.size).must_equal 3
80
- expect(force[0]).must_be_within_epsilon 1000.0
81
-
82
- # now let's rotate the radius into the x-dimension
83
- # right hand rule, positive torque means thumb into screen, clockwise
84
- # negative-x radius means positive-y force
85
- torque = Vector[0, 0, 500]
86
- radius = Vector[-5, 0]
87
- force = D.force_vector(torque, radius)
88
- expect(force).must_be_instance_of Vector
89
- expect(force.size).must_equal 3
90
- expect(force[1]).must_be_within_epsilon 100.0
91
- end
92
- end
93
-
94
62
  describe "instance methods" do
95
63
  before do
96
64
  @env = DrivingPhysics::Environment.new
97
- @disk = D.new(@env)
65
+ @disk = Disk.new(@env)
98
66
  end
99
67
 
100
68
  it "initializes" do
101
- skip
102
- expect(@disk).must_be_instance_of D
103
- expect(@disk.density).must_equal D::DENSITY # sanity check
104
- expect(@disk.mass).must_be_within_epsilon 25.01
105
-
106
- with_mass = D.new(@env) { |w|
107
- w.mass = 99.01
108
- }
69
+ expect(@disk).must_be_instance_of Disk
70
+ expect(@disk.density).must_equal Disk::DENSITY # sanity check
71
+ expect(@disk.mass).must_be_within_epsilon 76.969
72
+
73
+ with_mass = Disk.new(@env) { |w| w.mass = 99.01 }
109
74
  expect(with_mass.mass).must_equal 99.01
110
- expect(with_mass.density).wont_equal D::DENSITY
75
+ expect(with_mass.density).wont_equal Disk::DENSITY
111
76
  end
112
77
 
113
78
  it "has a string representation" do
@@ -122,8 +87,7 @@ describe D do
122
87
  end
123
88
 
124
89
  it "has inertia" do
125
- skip
126
- expect(@disk.rotational_inertia).must_be_within_epsilon 1.5321
90
+ expect(@disk.rotational_inertia).must_be_within_epsilon 4.714
127
91
  end
128
92
  end
129
93
  end
data/test/gearbox.rb ADDED
@@ -0,0 +1,36 @@
1
+ require 'minitest/autorun'
2
+ require 'driving_physics/gearbox'
3
+
4
+ include DrivingPhysics
5
+
6
+ describe Gearbox do
7
+ it "has gear ratios" do
8
+ end
9
+
10
+ it "has a final drive" do
11
+ end
12
+
13
+ it "has a neutral gear" do
14
+ end
15
+
16
+ it "has a clutch with state" do
17
+ end
18
+
19
+ it "has mass" do
20
+ end
21
+
22
+ it "has rotating mass" do
23
+ end
24
+
25
+ it "converts crank torque to axle torque" do
26
+ end
27
+
28
+ it "has losses due to inertia and friction" do
29
+ end
30
+
31
+ it "converts crank omega to axle omega (and vice versa)" do
32
+ end
33
+
34
+ it "varies torque delivery based on gear ratio and clutch" do
35
+ end
36
+ end
data/test/motor.rb ADDED
@@ -0,0 +1,236 @@
1
+ require 'minitest/autorun'
2
+ require 'driving_physics/motor'
3
+
4
+ include DrivingPhysics
5
+
6
+ describe "interpolate" do
7
+ it "validates xs and ys match in size" do
8
+ xs = [0, 5, 10, 15, 20]
9
+ ys = [10, 10, 10, 10, 5]
10
+ expect(DrivingPhysics.interpolate(1, xs: xs, ys: ys)).must_equal 10
11
+ expect { DrivingPhysics.interpolate(1, xs: xs + [10], ys: ys) }.must_raise
12
+ expect { DrivingPhysics.interpolate(1, xs: xs, ys: ys + [10]) }.must_raise
13
+ end
14
+
15
+ it "validates x is within the range of xs" do
16
+ xs = [0, 5, 10, 15, 20]
17
+ ys = [10, 10, 10, 10, 5]
18
+ expect(DrivingPhysics.interpolate(1, xs: xs, ys: ys)).must_equal 10
19
+ expect { DrivingPhysics.interpolate(-1, xs: xs, ys: ys) }.must_raise
20
+ expect { DrivingPhysics.interpolate(25, xs: xs, ys: ys) }.must_raise
21
+ end
22
+
23
+ it "validates the xs are in ascending order" do
24
+ xs = [0, 5, 10, 15, 20]
25
+ ys = [10, 10, 10, 10, 5]
26
+ expect(DrivingPhysics.interpolate(1, xs: xs, ys: ys)).must_equal 10
27
+ xs[1] = 15
28
+ expect {
29
+ DrivingPhysics.interpolate(16, xs: xs, ys: ys)
30
+ }.must_raise
31
+ end
32
+
33
+ it "performs linear interpolation to yield a y value for a valid x" do
34
+ xs = [0, 5, 10, 15, 20]
35
+ ys = [5, 5, 10, 10, 15]
36
+
37
+ expect(DrivingPhysics.interpolate(0, xs: xs, ys: ys)).must_equal 5
38
+ expect(DrivingPhysics.interpolate(1, xs: xs, ys: ys)).must_equal 5
39
+ expect(DrivingPhysics.interpolate(4, xs: xs, ys: ys)).must_equal 5
40
+ expect(DrivingPhysics.interpolate(5, xs: xs, ys: ys)).must_equal 5
41
+ expect(DrivingPhysics.interpolate(6, xs: xs, ys: ys)).must_equal 6
42
+ expect(DrivingPhysics.interpolate(7, xs: xs, ys: ys)).must_equal 7
43
+ expect(DrivingPhysics.interpolate(8, xs: xs, ys: ys)).must_equal 8
44
+ expect(DrivingPhysics.interpolate(9, xs: xs, ys: ys)).must_equal 9
45
+ expect(DrivingPhysics.interpolate(10, xs: xs, ys: ys)).must_equal 10
46
+ expect(DrivingPhysics.interpolate(11, xs: xs, ys: ys)).must_equal 10
47
+ expect(DrivingPhysics.interpolate(12, xs: xs, ys: ys)).must_equal 10
48
+ expect(DrivingPhysics.interpolate(14, xs: xs, ys: ys)).must_equal 10
49
+ expect(DrivingPhysics.interpolate(15, xs: xs, ys: ys)).must_equal 10
50
+ expect(DrivingPhysics.interpolate(16, xs: xs, ys: ys)).must_equal 11
51
+ expect(DrivingPhysics.interpolate(17, xs: xs, ys: ys)).must_equal 12
52
+ expect(DrivingPhysics.interpolate(18, xs: xs, ys: ys)).must_equal 13
53
+ expect(DrivingPhysics.interpolate(19, xs: xs, ys: ys)).must_equal 14
54
+ expect(DrivingPhysics.interpolate(20, xs: xs, ys: ys)).must_equal 15
55
+ end
56
+ end
57
+
58
+ # shorthand
59
+ def tc(rpms, torques)
60
+ TorqueCurve.new(rpms: rpms, torques: torques)
61
+ end
62
+
63
+ describe TorqueCurve do
64
+ before do
65
+ @default = TorqueCurve.new
66
+ @rpms = [500, 1000, 3500, 6000, 7000, 7100]
67
+ @torques = [ 0, 100, 300, 300, 250, 0]
68
+ @minr = [0, 1]
69
+ @mint = [0, 0]
70
+ end
71
+
72
+ it "maps rpm values to torque values" do
73
+ expect(@default.torque(3500)).must_be(:>, 100)
74
+ end
75
+
76
+ describe "initialize" do
77
+ it "accepts two arrays: rpms, and the corresponding torques" do
78
+ expect(tc(@rpms, @torques)).must_be_kind_of(TorqueCurve)
79
+ end
80
+
81
+ it "has defaults for rpms and torques" do
82
+ expect(@default).must_be_kind_of(TorqueCurve)
83
+ end
84
+
85
+ it "validates size match for rpms and torques" do
86
+ expect( tc( @minr, @mint) ).must_be_kind_of TorqueCurve
87
+ expect { tc( [0], @mint) }.must_raise
88
+ expect { tc([0,1,2], @mint) }.must_raise
89
+ expect { tc(@minr, [0]) }.must_raise
90
+ expect { tc(@minr, [0,1,0]) }.must_raise
91
+
92
+ rpms = [100, 2000, 30_000]
93
+ torques = [0, 500, 0]
94
+
95
+ expect( tc( rpms, torques) ).must_be_kind_of TorqueCurve
96
+ expect { tc( rpms, [0, 0]) }.must_raise
97
+ expect { tc([1,2], torques) }.must_raise
98
+ expect { tc([1,2,3,4], torques) }.must_raise
99
+ end
100
+
101
+
102
+ describe "rpms" do
103
+ it "validates rpms are positive" do
104
+ expect( tc( @minr, @mint) ).must_be_kind_of TorqueCurve
105
+ expect { tc([-10, 10], @mint) }.must_raise
106
+ end
107
+
108
+ it "validates rpms are in ascending order" do
109
+ expect( tc( @minr, @mint) ).must_be_kind_of TorqueCurve
110
+ expect { tc([0, 0], @mint) }.must_raise
111
+ expect( tc([99, 100], @mint) ).must_be_kind_of TorqueCurve
112
+ expect { tc([100, 99], @mint) }.must_raise
113
+ end
114
+ end
115
+
116
+ describe "torques" do
117
+ it "validates that torques start and end at zero" do
118
+ expect( tc(@minr, @mint) ).must_be_kind_of TorqueCurve
119
+ expect { tc(@minr, [1,0]) }.must_raise
120
+ expect { tc(@minr, [0,1]) }.must_raise
121
+ expect { tc(@minr, [1,1]) }.must_raise
122
+
123
+ expect( tc([1,2,3], [0,500,0]) ).must_be_kind_of TorqueCurve
124
+ expect { tc([1,2,3], [1,500,0]) }.must_raise
125
+ expect { tc([1,2,3], [0,500,1]) }.must_raise
126
+ end
127
+
128
+ it "validates that torques are positive" do
129
+ expect( tc([1,2,3], [0, 5,0]) ).must_be_kind_of TorqueCurve
130
+ expect { tc([1,2,3], [0,-5,0]) }.must_raise
131
+ end
132
+ end
133
+ end
134
+
135
+ it "finds the peak torque and corresponding RPM" do
136
+ rpm, torque = *@default.peak
137
+ expect(rpm).must_be(:>, 1000)
138
+ expect(rpm).must_be(:<, 10_000)
139
+ expect(torque).must_be(:>, 0)
140
+ expect(torque).must_be(:<, 10_000)
141
+ end
142
+
143
+ it "interpolates to find the torque for a valid RPM" do
144
+ tc = tc(@rpms, @torques)
145
+ r1 = @rpms[1]
146
+ r2 = @rpms[2]
147
+
148
+ expect(tc.torque(r1)).must_equal @torques[1]
149
+ expect(tc.torque(r2)).must_equal @torques[2]
150
+
151
+ r3 = (r1 + r2) / 2
152
+ t3 = tc.torque(r3)
153
+ t3_expect = (@torques[1] + @torques[2]) / 2.0
154
+
155
+ expect(t3).must_be :>, @torques[1]
156
+ expect(t3).must_be :<, @torques[2]
157
+ expect(t3).must_be :>=, t3_expect.floor
158
+ expect(t3).must_be :<=, t3_expect.ceil
159
+ end
160
+
161
+ it "tracks min, idle, redline, and max rpms" do
162
+ expect(@default.min).must_be :>, 0
163
+ expect(@default.min).must_be :<, 1000
164
+ expect(@default.idle).must_be :>, @default.min
165
+ expect(@default.idle).must_be :<, 3000
166
+ expect(@default.redline).must_be :>, @default.idle
167
+ expect(@default.redline).must_be :<, 20_000
168
+ expect(@default.max).must_be :>, @default.redline
169
+ expect(@default.max).must_be :<, 20_000
170
+ end
171
+ end
172
+
173
+ describe Motor do
174
+ before do
175
+ @default = Motor.new(Environment.new)
176
+ end
177
+
178
+ it "has a throttle with state" do
179
+ expect(@default.throttle).must_equal 0.0
180
+ @default.throttle = 0.5
181
+ expect(@default.throttle).must_equal 0.5
182
+ expect(@default.throttle_pct).must_equal "50.0%"
183
+
184
+ expect { @default.throttle = 1.5 }.must_raise
185
+ end
186
+
187
+ it "has mass" do
188
+ expect(@default.mass).must_be :>, 0
189
+ expect(@default.fixed_mass).must_be :>, 0
190
+ expect(@default.rotating_mass).must_be :>, 0
191
+ end
192
+
193
+ it "has a torque curve" do
194
+ expect(@default.torque_curve).must_be_kind_of TorqueCurve
195
+ end
196
+
197
+ it "has idle RPM and redline RPM" do
198
+ expect(@default.idle).must_be :>, 500
199
+ expect(@default.idle).must_be :<, 1500
200
+
201
+ expect(@default.redline).must_be :>, @default.idle
202
+ expect(@default.redline).must_be :<, 10_000
203
+ end
204
+
205
+ it "has inertia and energy" do
206
+ expect(@default.inertia).must_be :>, 0
207
+ expect(@default.energy(99)).must_be :>, 0
208
+ end
209
+
210
+ it "determines crank alpha from torque" do
211
+ expect(@default.alpha(50)).must_be :>, 0
212
+ end
213
+
214
+ it "determines torque from crank alpha" do
215
+ a = @default.alpha(50, omega: 20)
216
+ t = @default.implied_torque(a)
217
+ # frictional losses
218
+ expect(t).must_be :>, 40
219
+ expect(t).must_be :<, 50
220
+ end
221
+
222
+ it "determines torque based on torque curve, RPM and throttle" do
223
+ @default.throttle = 1.0
224
+ expect(@default.torque(1000)).must_be :>, 0
225
+ expect(@default.torque(3500)).must_be :>, @default.torque(1000)
226
+ end
227
+
228
+ it "has an engine braking effect when the throttle is closed" do
229
+ @default.throttle = 0
230
+ expect(@default.torque(3500)).must_be :<, 0
231
+ end
232
+
233
+ it "has a starter motor to get running" do
234
+ expect(@default.starter_torque).must_be :>, 0
235
+ end
236
+ end
@@ -0,0 +1,21 @@
1
+ require 'minitest/autorun'
2
+ require 'driving_physics/powertrain'
3
+
4
+ include DrivingPhysics
5
+
6
+ describe Powertrain do
7
+ it "has a motor and a gearbox" do
8
+ end
9
+
10
+ it "has mass" do
11
+ end
12
+
13
+ it "coverts rpm to axle torque" do
14
+ end
15
+
16
+ it "converts rpm to axle omega" do
17
+ end
18
+
19
+ it "determines crank rpm from axle_omega" do
20
+ end
21
+ end
data/test/scalar_force.rb CHANGED
@@ -12,8 +12,7 @@ describe ScalarForce do
12
12
  # ROT_COF's value is from observing that rotational resistance
13
13
  # matches air resistance at roughly 30 m/s in street cars
14
14
  it "approximates a reasonable rotational resistance constant" do
15
- expect(30 * ScalarForce.air_resistance(1)).
16
- must_be_within_epsilon(-1 * ROT_COF)
15
+ _(30 * ScalarForce.air_resistance(1)).must_be_within_epsilon(-1 * ROT_COF)
17
16
  end
18
17
 
19
18
  it "approximates a positive drag force" do
@@ -21,12 +20,10 @@ describe ScalarForce do
21
20
  end
22
21
 
23
22
  it "approximates a positive rotational resistance force" do
24
- expect(ScalarForce.rotational_resistance 30).
25
- must_be_within_epsilon(-383.13)
23
+ _(ScalarForce.rotational_resistance 30).must_be_within_epsilon(-383.13)
26
24
  end
27
25
 
28
26
  it "approximates a positive rolling resistance force" do
29
- nf = 1000 * G
30
- expect(ScalarForce.rolling_resistance nf).must_be_within_epsilon(-98.0)
27
+ _(ScalarForce.rolling_resistance(1000 * G)).must_be_within_epsilon(-98.0)
31
28
  end
32
29
  end