driving_physics 0.0.0.3 → 0.0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,120 @@
1
+ require 'driving_physics/disk'
2
+
3
+ module DrivingPhysics
4
+
5
+ # a Tire is a Disk with lighter density and meaningful surface friction
6
+
7
+ class Tire < Disk
8
+ # Note, this is not the density of solid rubber. This density
9
+ # yields a sensible mass for a wheel / tire combo at common radius
10
+ # and width, assuming a uniform density
11
+ # e.g. 25kg at 350mm R x 200mm W
12
+ #
13
+ DENSITY = 0.325 # kg / L
14
+
15
+ # * the traction force opposes the axle torque / drive force
16
+ # thus, driving the car forward
17
+ # * if the drive force exceeds the traction force, slippage occurs
18
+ # * slippage reduces the available traction force further
19
+ # * if the drive force is not reduced, the slippage increases
20
+ # until resistance forces equal the drive force
21
+ def self.traction(normal_force, cof)
22
+ normal_force * cof
23
+ end
24
+
25
+ attr_accessor :mu_s, :mu_k, :omega_friction, :base_friction, :roll_cof
26
+
27
+ def initialize(env)
28
+ @env = env
29
+ @radius = 0.35
30
+ @width = 0.2
31
+ @density = DENSITY
32
+ @temp = @env.air_temp
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
+ @roll_cof = DrivingPhysics::ROLL_COF
38
+
39
+ yield self if block_given?
40
+ end
41
+
42
+ def to_s
43
+ [[format("%d mm x %d mm (RxW)", @radius * 1000, @width * 1000),
44
+ format("%.1f kg %.1f C", self.mass, @temp),
45
+ format("cF: %.1f / %.1f", @mu_s, @mu_k),
46
+ ].join(" | "),
47
+ ].join("\n")
48
+ end
49
+
50
+ def wear!(amount)
51
+ @radius -= amount
52
+ end
53
+
54
+ def heat!(amount_deg_c)
55
+ @temp += amount_deg_c
56
+ end
57
+
58
+ def traction(nf, static: true)
59
+ self.class.traction(nf, static ? @mu_s : @mu_k)
60
+ end
61
+
62
+ # require a normal_force to be be passed in
63
+ def rotating_friction(omega, normal_force:)
64
+ super(omega, normal_force: normal_force)
65
+ end
66
+
67
+ # rolling loss in terms of axle torque
68
+ def rolling_friction(omega, normal_force:)
69
+ return omega if omega.zero?
70
+ mag = omega.abs
71
+ sign = omega / mag
72
+ -1 * sign * (normal_force * @roll_cof) * @radius
73
+ end
74
+
75
+ # inertial loss in terms of axle torque when used as a drive wheel
76
+ def inertial_loss(axle_torque, driven_mass:)
77
+ drive_force = self.force(axle_torque)
78
+ force_loss = 0
79
+ # The force loss depends on the acceleration, but the acceleration
80
+ # depends on the force loss. Converge the value via 5 round trips.
81
+ # This is a rough way to compute an integral and should be accurate
82
+ # to 8+ digits.
83
+ 5.times {
84
+ acc = DrivingPhysics.acc(drive_force - force_loss, driven_mass)
85
+ alpha = acc / @radius
86
+ force_loss = self.implied_torque(alpha) / @radius
87
+ }
88
+ force_loss * @radius
89
+ end
90
+
91
+ def net_torque(axle_torque, mass:, omega:, normal_force:)
92
+ # friction forces oppose omega
93
+ net = axle_torque +
94
+ self.rolling_friction(omega, normal_force: normal_force) +
95
+ self.rotating_friction(omega, normal_force: normal_force)
96
+
97
+ # inertial loss has interdependencies; calculate last
98
+ # it opposes net torque, not omega
99
+ sign = net / net.abs
100
+ net - sign * self.inertial_loss(net, driven_mass: mass)
101
+ end
102
+
103
+ def net_tractable_torque(axle_torque,
104
+ mass:, omega:, normal_force:, static: true)
105
+ net = self.net_torque(axle_torque,
106
+ mass: mass,
107
+ omega: omega,
108
+ normal_force: normal_force)
109
+ tt = self.tractable_torque(normal_force, static: static)
110
+ net > tt ? tt : net
111
+ end
112
+
113
+ # this doesn't take inertial losses or internal frictional losses
114
+ # into account. input torque required to saturate traction will be
115
+ # higher than what this method returns
116
+ def tractable_torque(nf, static: true)
117
+ traction(nf, static: static) * @radius
118
+ end
119
+ end
120
+ end
@@ -84,12 +84,25 @@ module DrivingPhysics
84
84
  frontal_area: FRONTAL_AREA,
85
85
  drag_cof: DRAG_COF,
86
86
  air_density: AIR_DENSITY)
87
+ return velocity if velocity.zero?
87
88
  -1 * 0.5 * frontal_area * drag_cof * air_density *
88
89
  velocity * velocity.magnitude
89
90
  end
90
91
 
91
- def self.rotational_resistance(velocity, rot_cof: ROT_COF)
92
- -1 * velocity * rot_cof
92
+ # return a force opposing velocity, representing friction / hysteresis
93
+ def self.rotational_resistance(velocity,
94
+ rot_const: ROT_CONST,
95
+ rot_cof: ROT_COF)
96
+ return velocity if velocity.zero?
97
+ -1 * velocity * rot_cof + -1 * velocity.normalize * rot_const
98
+ end
99
+
100
+ # return a torque opposing omega, representing friction / hysteresis
101
+ def self.omega_resistance(omega,
102
+ rot_const: ROT_TQ_CONST,
103
+ rot_cof: ROT_TQ_COF)
104
+ return 0 if omega == 0.0
105
+ omega * ROT_TQ_COF + ROT_TQ_CONST
93
106
  end
94
107
 
95
108
  # dir is drive_force vector or velocity vector; will be normalized
@@ -26,6 +26,7 @@ module DrivingPhysics
26
26
  DRAG_COF = 0.3 # based roughly on 2000s-era Chevrolet Corvette
27
27
  DRAG = 0.4257 # air_resistance at 1 m/s given above numbers
28
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
29
30
  ROLL_COF = 0.01 # roughly: street tires on concrete
30
31
 
31
32
  #
@@ -35,6 +36,7 @@ module DrivingPhysics
35
36
  MINS_PER_HOUR = 60
36
37
  SECS_PER_HOUR = SECS_PER_MIN * MINS_PER_HOUR
37
38
 
39
+ # HH::MM::SS.mmm
38
40
  def self.elapsed_display(elapsed_ms)
39
41
  elapsed_s, ms = elapsed_ms.divmod 1000
40
42
 
data/test/disk.rb ADDED
@@ -0,0 +1,132 @@
1
+ require 'minitest/autorun'
2
+ require 'driving_physics/disk'
3
+
4
+ D = DrivingPhysics::Disk
5
+
6
+ describe D do
7
+ describe "Disk.volume" do
8
+ it "calculates the volume (m^3) of disk given radius and width" do
9
+ cubic_m = D.volume(1.0, 1.0)
10
+ expect(cubic_m).must_equal Math::PI
11
+
12
+ cubic_m = D.volume(0.35, 0.2)
13
+ expect(cubic_m).must_be_within_epsilon 0.076969
14
+ end
15
+ end
16
+
17
+ describe "Disk.volume_l" do
18
+ it "calculates the volume (L) of a disk given radius and width" do
19
+ liters = D.volume_l(1.0, 1.0)
20
+ expect(liters).must_equal Math::PI * 1000
21
+
22
+ liters = D.volume_l(0.35, 0.2)
23
+ expect(liters).must_be_within_epsilon 76.96902
24
+ end
25
+ end
26
+
27
+ describe "Disk.density" do
28
+ 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
31
+ end
32
+ end
33
+
34
+ describe "Disk.mass" do
35
+ 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
38
+ end
39
+ end
40
+
41
+ describe "Disk.rotational_inertia" do
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
44
+ end
45
+ end
46
+
47
+ describe "Disk.alpha" do
48
+ it "calculates angular acceleration from torque and inertia" do
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
52
+
53
+ skip # Vector
54
+ vector_torque = Vector[0, 0, 1000]
55
+ vector_alpha = D.alpha vector_torque, inertia
56
+ expect(vector_alpha).must_be_instance_of Vector
57
+ expect(vector_alpha.size).must_equal 3
58
+ expect(vector_alpha[2]).must_be_within_epsilon 653.06
59
+ end
60
+ end
61
+
62
+ describe "Disk.torque_vector" do
63
+ it "calculates a torque in the 3rd dimension given 2D force and radius" do
64
+ skip # Vector
65
+ force = Vector[1000, 0]
66
+ radius = Vector[0, 5]
67
+ torque = D.torque_vector(force, radius)
68
+ expect(torque).must_be_instance_of Vector
69
+ expect(torque.size).must_equal 3
70
+ expect(torque[2]).must_be_within_epsilon 5000.0
71
+ end
72
+ end
73
+
74
+ describe "Disk.force_vector" do
75
+ it "calculates a (3D) force given 3D torque and 2D radius" do
76
+ skip # Vector
77
+ # let's invert the Disk.torque_vector case from above:
78
+ torque = Vector[0, 0, 5000]
79
+ radius = Vector[0, 5]
80
+ force = D.force_vector(torque, radius)
81
+ expect(force).must_be_instance_of Vector
82
+ expect(force.size).must_equal 3
83
+ expect(force[0]).must_be_within_epsilon 1000.0
84
+
85
+ # now let's rotate the radius into the x-dimension
86
+ # right hand rule, positive torque means thumb into screen, clockwise
87
+ # negative-x radius means positive-y force
88
+ torque = Vector[0, 0, 500]
89
+ radius = Vector[-5, 0]
90
+ force = D.force_vector(torque, radius)
91
+ expect(force).must_be_instance_of Vector
92
+ expect(force.size).must_equal 3
93
+ expect(force[1]).must_be_within_epsilon 100.0
94
+ end
95
+ end
96
+
97
+ describe "instance methods" do
98
+ before do
99
+ @env = DrivingPhysics::Environment.new
100
+ @disk = D.new(@env)
101
+ end
102
+
103
+ it "initializes" do
104
+ skip
105
+ expect(@disk).must_be_instance_of D
106
+ expect(@disk.density).must_equal D::DENSITY # sanity check
107
+ expect(@disk.mass).must_be_within_epsilon 25.01
108
+
109
+ with_mass = D.new(@env) { |w|
110
+ w.mass = 99.01
111
+ }
112
+ expect(with_mass.mass).must_equal 99.01
113
+ expect(with_mass.density).wont_equal D::DENSITY
114
+ end
115
+
116
+ it "has a string representation" do
117
+ str = @disk.to_s
118
+ expect(str).must_be_instance_of String
119
+ expect(str.length).must_be(:>, 5)
120
+ end
121
+
122
+ it "has volume" do
123
+ expect(@disk.volume).must_be_within_epsilon 0.07697
124
+ expect(@disk.volume_l).must_be_within_epsilon 76.96902
125
+ end
126
+
127
+ it "has inertia" do
128
+ skip
129
+ expect(@disk.rotational_inertia).must_be_within_epsilon 1.5321
130
+ end
131
+ end
132
+ end
data/test/scalar_force.rb CHANGED
@@ -6,25 +6,27 @@ include DrivingPhysics
6
6
  describe ScalarForce do
7
7
  # i.e. multiply this number times speed^2 to approximate drag force
8
8
  it "calculates a reasonable drag constant" do
9
- expect(ScalarForce.air_resistance 1).must_be_within_epsilon DRAG
9
+ expect(ScalarForce.air_resistance 1).must_be_within_epsilon(-1 * DRAG)
10
10
  end
11
11
 
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)).must_be_within_epsilon ROT_COF
15
+ expect(30 * ScalarForce.air_resistance(1)).
16
+ must_be_within_epsilon(-1 * ROT_COF)
16
17
  end
17
18
 
18
19
  it "approximates a positive drag force" do
19
- expect(ScalarForce.air_resistance 30).must_be_within_epsilon 383.13
20
+ expect(ScalarForce.air_resistance 30).must_be_within_epsilon(-383.13)
20
21
  end
21
22
 
22
23
  it "approximates a positive rotational resistance force" do
23
- expect(ScalarForce.rotational_resistance 30).must_be_within_epsilon 383.13
24
+ expect(ScalarForce.rotational_resistance 30).
25
+ must_be_within_epsilon(-383.13)
24
26
  end
25
27
 
26
28
  it "approximates a positive rolling resistance force" do
27
29
  nf = 1000 * G
28
- expect(ScalarForce.rolling_resistance nf).must_be_within_epsilon 98.0
30
+ expect(ScalarForce.rolling_resistance nf).must_be_within_epsilon(-98.0)
29
31
  end
30
32
  end
@@ -1,92 +1,96 @@
1
1
  require 'minitest/autorun'
2
- require 'driving_physics/wheel'
2
+ require 'driving_physics/tire'
3
3
 
4
- W = DrivingPhysics::Wheel
4
+ T = DrivingPhysics::Tire
5
5
 
6
- describe W do
7
- describe "Wheel.traction" do
6
+ describe T do
7
+ describe "Tire.traction" do
8
8
  it "calculates traction force from normal force and coeff of friction" do
9
9
  scalar_nf = 9800 # N
10
10
  cof = 1.1
11
- scalar_t = W.traction(scalar_nf, cof)
11
+ scalar_t = T.traction(scalar_nf, cof)
12
12
  expect(scalar_t).must_equal 10780.0
13
13
 
14
+ skip # Vector
14
15
  vector_nf = Vector[9800, 0]
15
- vector_t = W.traction(vector_nf, cof)
16
+ vector_t = T.traction(vector_nf, cof)
16
17
  expect(vector_t).must_equal Vector[10780.0, 0.0]
17
18
  end
18
19
  end
19
20
 
20
- describe "Wheel.volume" do
21
+ describe "Tire.volume" do
21
22
  it "calculates the volume (m^3) of disk given radius and width" do
22
- cubic_m = W.volume(1.0, 1.0)
23
+ cubic_m = T.volume(1.0, 1.0)
23
24
  expect(cubic_m).must_equal Math::PI
24
25
 
25
- cubic_m = W.volume(0.35, 0.2)
26
+ cubic_m = T.volume(0.35, 0.2)
26
27
  expect(cubic_m).must_be_within_epsilon 0.076969
27
28
  end
28
29
  end
29
30
 
30
- describe "Wheel.volume_l" do
31
+ describe "Tire.volume_l" do
31
32
  it "calculates the volume (L) of a disk given radius and width" do
32
- liters = W.volume_l(1.0, 1.0)
33
+ liters = T.volume_l(1.0, 1.0)
33
34
  expect(liters).must_equal Math::PI * 1000
34
35
 
35
- liters = W.volume_l(0.35, 0.2)
36
+ liters = T.volume_l(0.35, 0.2)
36
37
  expect(liters).must_be_within_epsilon 76.96902
37
38
  end
38
39
  end
39
40
 
40
- describe "Wheel.density" do
41
+ describe "Tire.density" do
41
42
  it "calculates the density (kg/L) given mass and volume" do
42
- expect(W.density(25.0, 25.0)).must_equal 1.0
43
- expect(W.density(50.0, 25.0)).must_equal 2.0
43
+ expect(T.density(25.0, 25.0)).must_equal 1.0
44
+ expect(T.density(50.0, 25.0)).must_equal 2.0
44
45
  end
45
46
  end
46
47
 
47
- describe "Wheel.mass" do
48
+ describe "Tire.mass" do
48
49
  it "calculates the mass (kg) of a disk given radius, width, and density" do
49
- expect(W.mass(0.35, 0.2, W::DENSITY)).must_be_within_epsilon 25.015
50
+ expect(T.mass(0.35, 0.2, T::DENSITY)).must_be_within_epsilon 25.015
50
51
  end
51
52
  end
52
53
 
53
- describe "Wheel.rotational_inertia" do
54
+ describe "Tire.rotational_inertia" do
54
55
  it "calculates rotational inertia for a disk given radius and mass" do
55
- expect(W.rotational_inertia(0.35, 25.0)).must_be_within_epsilon 1.53125
56
+ expect(T.rotational_inertia(0.35, 25.0)).must_be_within_epsilon 1.53125
56
57
  end
57
58
  end
58
59
 
59
- describe "Wheel.alpha" do
60
+ describe "Tire.alpha" do
60
61
  it "calculates angular acceleration from torque and inertia" do
61
62
  scalar_torque = 1000
62
- inertia = W.rotational_inertia(0.35, 25.0)
63
- expect(W.alpha scalar_torque, inertia).must_be_within_epsilon 653.061
63
+ inertia = T.rotational_inertia(0.35, 25.0)
64
+ expect(T.alpha scalar_torque, inertia).must_be_within_epsilon 653.061
64
65
 
66
+ skip # Vector
65
67
  vector_torque = Vector[0, 0, 1000]
66
- vector_alpha = W.alpha vector_torque, inertia
68
+ vector_alpha = T.alpha vector_torque, inertia
67
69
  expect(vector_alpha).must_be_instance_of Vector
68
70
  expect(vector_alpha.size).must_equal 3
69
71
  expect(vector_alpha[2]).must_be_within_epsilon 653.06
70
72
  end
71
73
  end
72
74
 
73
- describe "Wheel.torque_vector" do
75
+ describe "Tire.torque_vector" do
74
76
  it "calculates a torque in the 3rd dimension given 2D force and radius" do
77
+ skip # Vector
75
78
  force = Vector[1000, 0]
76
79
  radius = Vector[0, 5]
77
- torque = W.torque_vector(force, radius)
80
+ torque = T.torque_vector(force, radius)
78
81
  expect(torque).must_be_instance_of Vector
79
82
  expect(torque.size).must_equal 3
80
83
  expect(torque[2]).must_be_within_epsilon 5000.0
81
84
  end
82
85
  end
83
86
 
84
- describe "Wheel.force_vector" do
87
+ describe "Tire.force_vector" do
85
88
  it "calculates a (3D) force given 3D torque and 2D radius" do
86
- # let's invert the Wheel.torque_vector case from above:
89
+ # let's invert the Tire.torque_vector case from above:
90
+ skip # Vector
87
91
  torque = Vector[0, 0, 5000]
88
92
  radius = Vector[0, 5]
89
- force = W.force_vector(torque, radius)
93
+ force = T.force_vector(torque, radius)
90
94
  expect(force).must_be_instance_of Vector
91
95
  expect(force.size).must_equal 3
92
96
  expect(force[0]).must_be_within_epsilon 1000.0
@@ -96,7 +100,7 @@ describe W do
96
100
  # negative-x radius means positive-y force
97
101
  torque = Vector[0, 0, 500]
98
102
  radius = Vector[-5, 0]
99
- force = W.force_vector(torque, radius)
103
+ force = T.force_vector(torque, radius)
100
104
  expect(force).must_be_instance_of Vector
101
105
  expect(force.size).must_equal 3
102
106
  expect(force[1]).must_be_within_epsilon 100.0
@@ -106,72 +110,78 @@ describe W do
106
110
  describe "instance methods" do
107
111
  before do
108
112
  @env = DrivingPhysics::Environment.new
109
- @w = W.new(@env)
113
+ @tire = T.new(@env)
110
114
  end
111
115
 
112
116
  it "initializes" do
113
- expect(@w).must_be_instance_of W
114
- expect(@w.density).must_equal W::DENSITY # sanity check
115
- expect(@w.mass).must_be_within_epsilon 25.01
117
+ expect(@tire).must_be_instance_of T
118
+ expect(@tire.density).must_equal T::DENSITY # sanity check
119
+ expect(@tire.mass).must_be_within_epsilon 25.01
116
120
 
117
- with_mass = W.new(@env, mass: 99.01)
121
+ with_mass = T.new(@env) { |w|
122
+ w.mass = 99.01
123
+ }
118
124
  expect(with_mass.mass).must_equal 99.01
119
- expect(with_mass.density).wont_equal W::DENSITY
125
+ expect(with_mass.density).wont_equal T::DENSITY
120
126
  end
121
127
 
122
128
  it "has a string representation" do
123
- str = @w.to_s
129
+ str = @tire.to_s
124
130
  expect(str).must_be_instance_of String
125
131
  expect(str.length).must_be(:>, 5)
126
132
  end
127
133
 
128
134
  it "loses radius as it wears" do
129
- expect(@w.radius).must_equal 350.0
130
- @w.wear!(50)
131
- expect(@w.radius).must_equal 300.0
135
+ old_r = @tire.radius
136
+ wear_amt = 50/1000r
137
+ @tire.wear! wear_amt
138
+ expect(@tire.radius).must_equal old_r - wear_amt
132
139
  end
133
140
 
134
141
  it "calculates mass from current radius" do
135
- expect(@w.mass).must_be_within_epsilon 25.01
136
- @w.wear!(50)
137
- expect(@w.mass).must_be_within_epsilon 18.378
142
+ expect(@tire.mass).must_be_within_epsilon 25.01
143
+ @tire.wear!(50/1000r)
144
+ expect(@tire.mass).must_be_within_epsilon 18.378
138
145
  end
139
146
 
140
147
  it "has volume" do
141
- expect(@w.volume).must_be_within_epsilon 0.07697
142
- expect(@w.volume_l).must_be_within_epsilon 76.96902
148
+ expect(@tire.volume).must_be_within_epsilon 0.07697
149
+ expect(@tire.volume_l).must_be_within_epsilon 76.96902
143
150
  end
144
151
 
145
152
  it "has inertia" do
146
- expect(@w.rotational_inertia).must_be_within_epsilon 1.5321
153
+ expect(@tire.rotational_inertia).must_be_within_epsilon 1.5321
147
154
  end
148
155
 
149
156
  it "has traction force based on normal force" do
150
157
  scalar_nf = 9800
151
- expect(@w.traction scalar_nf).must_equal 10780.0
152
- expect(@w.traction scalar_nf, static: false).must_equal 6860.0
158
+ expect(@tire.traction scalar_nf).must_equal 10780.0
159
+ expect(@tire.traction scalar_nf, static: false).must_equal 6860.0
153
160
 
161
+ skip # Vector
154
162
  vector_nf = Vector[9800, 0]
155
- expect(@w.traction vector_nf).must_equal Vector[10780.0, 0.0]
156
- expect(@w.traction vector_nf, static: false).
163
+ expect(@tire.traction vector_nf).must_equal Vector[10780.0, 0.0]
164
+ expect(@tire.traction vector_nf, static: false).
157
165
  must_equal Vector[6860.0, 0.0]
158
166
  end
159
167
 
160
168
  it "determines (e.g. thrust) force based on axle torque" do
161
- expect(@w.force 1000).must_be_within_epsilon 2857.143
162
- @w.wear! 50
163
- expect(@w.force 1000).must_be_within_epsilon 3333.333
169
+ expect(@tire.force 1000).must_be_within_epsilon 2857.143
170
+ @tire.wear! 50/1000r
171
+ expect(@tire.force 1000).must_be_within_epsilon 3333.333
164
172
  end
165
173
 
166
174
  it "determines tractable torque" do
167
175
  scalar_nf = 9800
168
- expect(@w.tractable_torque scalar_nf).must_be_within_epsilon 3773.0
169
- kin_tq = @w.tractable_torque scalar_nf, static: false
176
+ expect(@tire.tractable_torque scalar_nf).must_be_within_epsilon 3773.0
177
+ kin_tq = @tire.tractable_torque scalar_nf, static: false
170
178
  expect(kin_tq).must_be_within_epsilon 2401.0
171
179
 
172
180
  # not sure about how torque vectors work, but the "math" "works":
181
+ skip # Vector
173
182
  vector_nf = Vector[9800, 0]
174
- expect(@w.tractable_torque(vector_nf)[0]).must_be_within_epsilon 3773.0
183
+ expect(@tire.tractable_torque(vector_nf)[0]).
184
+ must_be_within_epsilon 3773.0
175
185
  end
176
186
  end
177
187
  end
data/test/vector_force.rb CHANGED
@@ -74,9 +74,15 @@ describe VectorForce do
74
74
  end
75
75
 
76
76
  it "calculates the rotational resistance as a function of velocity" do
77
+ rr = VectorForce.rotational_resistance(@v, rot_const: 0)
78
+ rr2 = VectorForce.rotational_resistance(@v * 2, rot_const: 0)
79
+ expect(rr2).must_equal rr * 2
80
+
81
+ # now with rot_const != 0, the relationship is skewed
77
82
  rr = VectorForce.rotational_resistance(@v)
78
83
  rr2 = VectorForce.rotational_resistance(@v * 2)
79
- expect(rr2).must_equal rr * 2
84
+ expect(rr2).wont_equal rr * 2 # because of rot_const
85
+ expect(rr2.magnitude).must_be(:<, (rr * 2).magnitude)
80
86
  end
81
87
 
82
88
  it "sums resistance forces" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: driving_physics
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0.3
4
+ version: 0.0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rick Hull
@@ -19,20 +19,36 @@ files:
19
19
  - README.md
20
20
  - Rakefile
21
21
  - VERSION
22
+ - demo/car.rb
23
+ - demo/disk.rb
24
+ - demo/gearbox.rb
25
+ - demo/motor.rb
26
+ - demo/mruby/disk.rb
27
+ - demo/mruby/motor.rb
28
+ - demo/powertrain.rb
22
29
  - demo/scalar_force.rb
30
+ - demo/tire.rb
23
31
  - demo/vector_force.rb
24
- - demo/wheel.rb
25
32
  - driving_physics.gemspec
26
33
  - lib/driving_physics.rb
34
+ - lib/driving_physics/car.rb
35
+ - lib/driving_physics/cli.rb
36
+ - lib/driving_physics/disk.rb
27
37
  - lib/driving_physics/environment.rb
38
+ - lib/driving_physics/gearbox.rb
28
39
  - lib/driving_physics/imperial.rb
40
+ - lib/driving_physics/motor.rb
41
+ - lib/driving_physics/mruby.rb
42
+ - lib/driving_physics/power.rb
43
+ - lib/driving_physics/powertrain.rb
29
44
  - lib/driving_physics/scalar_force.rb
45
+ - lib/driving_physics/tire.rb
30
46
  - lib/driving_physics/vector_force.rb
31
- - lib/driving_physics/wheel.rb
47
+ - test/disk.rb
32
48
  - test/driving_physics.rb
33
49
  - test/scalar_force.rb
50
+ - test/tire.rb
34
51
  - test/vector_force.rb
35
- - test/wheel.rb
36
52
  homepage: https://github.com/rickhull/driving_physics
37
53
  licenses:
38
54
  - LGPL-3.0