driving_physics 0.0.0.2 → 0.0.1.2
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 +4 -4
- data/README.md +12 -1
- data/Rakefile +11 -4
- data/VERSION +1 -1
- data/demo/car.rb +165 -18
- data/demo/disk.rb +83 -0
- data/demo/gearbox.rb +52 -0
- data/demo/motor.rb +141 -0
- data/demo/powertrain.rb +47 -0
- data/demo/scalar_force.rb +41 -15
- data/demo/tire.rb +80 -162
- data/demo/vector_force.rb +46 -16
- data/lib/driving_physics/car.rb +77 -248
- data/lib/driving_physics/cli.rb +51 -0
- data/lib/driving_physics/disk.rb +185 -0
- data/lib/driving_physics/gearbox.rb +109 -0
- data/lib/driving_physics/imperial.rb +6 -0
- data/lib/driving_physics/motor.rb +103 -0
- data/lib/driving_physics/power.rb +20 -0
- data/lib/driving_physics/powertrain.rb +50 -0
- data/lib/driving_physics/scalar_force.rb +6 -3
- data/lib/driving_physics/tire.rb +90 -258
- data/lib/driving_physics/vector_force.rb +15 -2
- data/lib/driving_physics.rb +2 -0
- data/test/disk.rb +129 -0
- data/test/scalar_force.rb +7 -5
- data/test/tire.rb +144 -88
- data/test/vector_force.rb +7 -1
- metadata +12 -5
- data/demo/wheel.rb +0 -84
- data/lib/driving_physics/wheel.rb +0 -191
- data/test/car.rb +0 -156
- data/test/wheel.rb +0 -177
data/demo/tire.rb
CHANGED
@@ -1,169 +1,87 @@
|
|
1
1
|
require 'driving_physics/tire'
|
2
|
+
require 'driving_physics/imperial'
|
3
|
+
require 'driving_physics/cli'
|
2
4
|
|
3
5
|
include DrivingPhysics
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
dynamic_g += 0.2
|
82
|
-
end
|
83
|
-
end
|
84
|
-
else
|
85
|
-
if !cooldown and
|
86
|
-
t.condition.temp_c <= critical_temp and
|
87
|
-
Random.rand(1000) >= 999
|
88
|
-
|
89
|
-
puts "PUSHING!"
|
90
|
-
pushing = true
|
91
|
-
dynamic_g += 0.2
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
if sliding
|
96
|
-
# 5% chance to end the slide
|
97
|
-
if Random.rand(100) >= 95
|
98
|
-
puts " -= CAUGHT THE SLIDE! =-"
|
99
|
-
sliding = false
|
100
|
-
slide_speed = 0
|
101
|
-
end
|
102
|
-
else
|
103
|
-
# 1% chance to start a small slide
|
104
|
-
# 0.1% chance to start a big slide
|
105
|
-
if Random.rand(100) >= 99
|
106
|
-
puts " -= SMALL SLIDE! =-"
|
107
|
-
sliding = true
|
108
|
-
slide_speed = sector_map[:small_slide]
|
109
|
-
elsif Random.rand(1000) >= 999
|
110
|
-
puts " -= BIG SLIDE! =-"
|
111
|
-
sliding = true
|
112
|
-
slide_speed = sector_map[:big_slide]
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
# fuel consumption
|
117
|
-
# 5L of fuel should last 5 minutes
|
118
|
-
# ~3.5 kg of fuel consumption
|
119
|
-
# 1.2e-4 kg / tick
|
120
|
-
mass -= sector_map[:fuel]
|
121
|
-
|
122
|
-
begin
|
123
|
-
t.condition.tick!(ambient_temp: ambient_temp, g: dynamic_g,
|
124
|
-
slide_speed: slide_speed,
|
125
|
-
mass: mass, tire_mass: 12, critical_temp: critical_temp)
|
126
|
-
|
127
|
-
if i % 10 == 0
|
128
|
-
condition = if pushing
|
129
|
-
"Pushing"
|
130
|
-
elsif cooldown
|
131
|
-
"Cooldown"
|
132
|
-
else
|
133
|
-
"Normal"
|
134
|
-
end
|
135
|
-
|
136
|
-
puts [sector_map[:label].ljust(12, ' '),
|
137
|
-
'%.2f' % dynamic_g,
|
138
|
-
'%.1f' % slide_speed,
|
139
|
-
'%.3f' % t.condition.temp_c,
|
140
|
-
].join(' ')
|
141
|
-
end
|
142
|
-
if i % 600 == 0
|
143
|
-
puts
|
144
|
-
puts "Condition: #{condition}"
|
145
|
-
puts "Mass: #{'%.2f' % mass} kg"
|
146
|
-
if t.condition.tread_mm > 0
|
147
|
-
puts "Tread remaining: #{'%.3f' % t.condition.tread_mm}"
|
148
|
-
else
|
149
|
-
puts "Cords remaining: #{'%.3f' % t.condition.cords_mm}"
|
150
|
-
end
|
151
|
-
puts "Heat cycles: #{t.condition.heat_cycles}"
|
152
|
-
puts DrivingPhysics.elapsed_display(i * 10)
|
153
|
-
puts "[Enter] to continue"
|
154
|
-
gets
|
155
|
-
end
|
156
|
-
rescue Tire::Condition::Error => e
|
157
|
-
puts "FATAL:"
|
158
|
-
puts [e.class, e.message].join(': ')
|
159
|
-
break
|
160
|
-
end
|
161
|
-
|
162
|
-
if drive_time > sector_map[:seconds] * 100
|
163
|
-
sector_map = drive_map[sector_map[:next_sector]]
|
164
|
-
drive_time = 0
|
7
|
+
env = Environment.new
|
8
|
+
tire = Tire.new(env)
|
9
|
+
puts env
|
10
|
+
puts tire
|
11
|
+
puts
|
12
|
+
|
13
|
+
duration = 100 # sec
|
14
|
+
axle_torque = 500 # N*m
|
15
|
+
supported_mass = 1500 # kg
|
16
|
+
|
17
|
+
puts "Given:"
|
18
|
+
puts "* #{axle_torque} Nm axle torque"
|
19
|
+
puts "* #{supported_mass} kg supported mass"
|
20
|
+
puts "* 4 tires"
|
21
|
+
puts "* #{duration} seconds"
|
22
|
+
puts
|
23
|
+
|
24
|
+
total_mass = supported_mass + 4 * tire.mass
|
25
|
+
corner_mass = Rational(total_mass) / 4
|
26
|
+
normal_force = corner_mass * env.g
|
27
|
+
|
28
|
+
puts "Therefore:"
|
29
|
+
puts format("* %.1f kg total mass", total_mass)
|
30
|
+
puts format("* %.1f kg per corner", corner_mass)
|
31
|
+
puts format("* %.1f N normal force", normal_force)
|
32
|
+
puts
|
33
|
+
|
34
|
+
traction = tire.traction(normal_force)
|
35
|
+
drive_force = tire.force(axle_torque)
|
36
|
+
|
37
|
+
puts "Tires:"
|
38
|
+
puts format("* %.1f N traction", traction)
|
39
|
+
puts format("* %.1f N drive force", drive_force)
|
40
|
+
|
41
|
+
CLI.pause
|
42
|
+
|
43
|
+
acc = 0.0 # meters/s/s
|
44
|
+
speed = 0.0 # meters/s
|
45
|
+
dist = 0.0 # meters
|
46
|
+
|
47
|
+
alpha = 0.0 # radians/s/s
|
48
|
+
omega = 0.0 # radians/s
|
49
|
+
theta = 0.0 # radians
|
50
|
+
|
51
|
+
start = Timer.now
|
52
|
+
paused = 0.0
|
53
|
+
num_ticks = duration * env.hz + 1
|
54
|
+
|
55
|
+
num_ticks.times { |i|
|
56
|
+
torque = tire.net_tractable_torque(axle_torque,
|
57
|
+
mass: total_mass,
|
58
|
+
omega: omega,
|
59
|
+
normal_force: normal_force)
|
60
|
+
force = tire.force(torque)
|
61
|
+
|
62
|
+
# translational kinematics
|
63
|
+
acc = DrivingPhysics.acc(force, total_mass)
|
64
|
+
speed += acc * env.tick
|
65
|
+
dist += speed * env.tick
|
66
|
+
mph = Imperial.mph(speed)
|
67
|
+
|
68
|
+
# rotational kinematics
|
69
|
+
alpha = acc / tire.radius
|
70
|
+
omega += alpha * env.tick
|
71
|
+
theta += omega * env.tick
|
72
|
+
|
73
|
+
if i < 10 or
|
74
|
+
(i < 20_000 and i%1000 == 0) or
|
75
|
+
(i % 10_000 == 0)
|
76
|
+
|
77
|
+
puts DrivingPhysics.elapsed_display(i)
|
78
|
+
puts format(" Tire: %.1f r %.2f r/s %.3f r/s^2", theta, omega, alpha)
|
79
|
+
puts format(" Car: %.1f m %.2f m/s %.3f m/s^2 (%d mph)",
|
80
|
+
dist, speed, acc, mph)
|
81
|
+
puts format("Torque: %.1f Nm (%d N) Loss: %.1f%%",
|
82
|
+
torque, force, (1.0 - torque / axle_torque) * 100)
|
165
83
|
puts
|
166
|
-
puts sector_map[:label]
|
167
|
-
puts '---'
|
168
84
|
end
|
169
85
|
}
|
86
|
+
|
87
|
+
puts Timer.summary(start, num_ticks, paused)
|
data/demo/vector_force.rb
CHANGED
@@ -1,26 +1,56 @@
|
|
1
1
|
require 'driving_physics/vector_force'
|
2
|
+
require 'driving_physics/environment'
|
3
|
+
require 'driving_physics/cli'
|
2
4
|
|
3
|
-
|
5
|
+
include DrivingPhysics
|
6
|
+
|
7
|
+
env = Environment.new
|
8
|
+
puts env
|
4
9
|
|
5
|
-
p = Vector[0, 0] # m
|
6
|
-
v = Vector[0, 0] # m/s
|
7
10
|
mass = 1000 # kg
|
8
|
-
weight = mass *
|
11
|
+
weight = mass * env.g # N
|
12
|
+
drive_force = DrivingPhysics.random_unit_vector * 7000 # N
|
9
13
|
duration = 100 # seconds
|
10
|
-
drive_force = DP.random_unit_vector * 7000 # N
|
11
|
-
tick = 1.0 / DP::HZ
|
12
14
|
|
13
|
-
(
|
14
|
-
|
15
|
+
puts format("Force: %d N Dir: %s",
|
16
|
+
drive_force.magnitude,
|
17
|
+
DrivingPhysics.compass_dir(drive_force.normalize))
|
18
|
+
puts format("Mass: %d kg for %d seconds", mass, duration)
|
19
|
+
CLI.pause
|
20
|
+
|
21
|
+
acc = Vector[0, 0] # m/s/s
|
22
|
+
vel = Vector[0, 0] # m/s
|
23
|
+
pos = Vector[0, 0] # m
|
24
|
+
|
25
|
+
num_ticks = duration * env.hz + 1
|
26
|
+
|
27
|
+
flag = false
|
28
|
+
phase = :accelerate
|
29
|
+
paused = 0.0
|
30
|
+
start = Timer.now
|
15
31
|
|
16
|
-
|
17
|
-
|
18
|
-
|
32
|
+
num_ticks.times { |i|
|
33
|
+
net_force = drive_force +
|
34
|
+
VectorForce.all_resistance(vel, dir: vel, nf_mag: weight)
|
19
35
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
36
|
+
acc = DrivingPhysics.acc(net_force, mass)
|
37
|
+
vel += acc * env.tick
|
38
|
+
pos += vel * env.tick
|
39
|
+
|
40
|
+
if phase == :accelerate and vel.magnitude > 100
|
41
|
+
flag = true
|
42
|
+
phase = :coast
|
43
|
+
drive_force = Vector[0, 0]
|
44
|
+
end
|
45
|
+
|
46
|
+
if flag or (i % 1000 == 0)
|
47
|
+
puts format("%d %.3f m/s/s %.2f m/s %.1f m",
|
48
|
+
i.to_f / env.hz, acc.magnitude, vel.magnitude, pos.magnitude)
|
49
|
+
if flag
|
50
|
+
paused = CLI.pause
|
51
|
+
flag = false
|
52
|
+
end
|
25
53
|
end
|
26
54
|
}
|
55
|
+
|
56
|
+
puts Timer.summary(start, num_ticks, paused)
|