driving_physics 0.0.0.3 → 0.0.2.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.
@@ -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