Skip to content

Commit 2f9c651

Browse files
committed
Improve velocity for impact calculation
1 parent 30bc300 commit 2f9c651

File tree

4 files changed

+42
-39
lines changed

4 files changed

+42
-39
lines changed

src/main/kotlin/com/kylecorry/sol/math/optimization/IOptimizer.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import com.kylecorry.sol.math.Range
55
interface IOptimizer {
66
fun optimize(
77
xRange: Range<Double>,
8-
yRange: Range<Double>,
8+
yRange: Range<Double> = Range(0.0, 0.0),
99
maximize: Boolean = true,
1010
fn: (x: Double, y: Double) -> Double
1111
): Pair<Double, Double>

src/main/kotlin/com/kylecorry/sol/science/physics/IPhysicsService.kt

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ package com.kylecorry.sol.science.physics
33
import com.kylecorry.sol.math.Quaternion
44
import com.kylecorry.sol.math.Vector2
55
import com.kylecorry.sol.math.Vector3
6+
import com.kylecorry.sol.math.interpolation.Interpolator
7+
import com.kylecorry.sol.math.interpolation.LinearInterpolator
8+
import com.kylecorry.sol.math.optimization.HillClimbingOptimizer
9+
import com.kylecorry.sol.math.optimization.IOptimizer
610
import com.kylecorry.sol.science.geology.Geology
7-
import com.kylecorry.sol.units.Bearing
8-
import com.kylecorry.sol.units.Distance
9-
import com.kylecorry.sol.units.Energy
10-
import com.kylecorry.sol.units.Speed
11-
import com.kylecorry.sol.units.Weight
11+
import com.kylecorry.sol.units.*
1212
import java.time.Duration
1313

1414
interface IPhysicsService {
@@ -58,8 +58,10 @@ interface IPhysicsService {
5858
maxTime: Float = 10f,
5959
minAngle: Float = 0f,
6060
maxAngle: Float = 90f,
61-
angleStep: Float = 1f,
62-
tolerance: Float = 0.01f,
61+
optimizer: IOptimizer = HillClimbingOptimizer(0.001, initialValue = 0.0 to 0.0),
62+
getInterpolator: (points: List<Vector2>) -> Interpolator = { points ->
63+
LinearInterpolator(points)
64+
}
6365
): Vector2
6466

6567
/**

src/main/kotlin/com/kylecorry/sol/science/physics/Physics.kt

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
package com.kylecorry.sol.science.physics
22

3-
import com.kylecorry.sol.math.Quaternion
4-
import com.kylecorry.sol.math.SolMath
5-
import com.kylecorry.sol.math.Vector2
6-
import com.kylecorry.sol.math.Vector3
3+
import com.kylecorry.sol.math.*
4+
import com.kylecorry.sol.math.interpolation.Interpolator
5+
import com.kylecorry.sol.math.optimization.IOptimizer
76
import com.kylecorry.sol.science.geology.Geology
87
import com.kylecorry.sol.units.*
98
import java.time.Duration
9+
import kotlin.math.absoluteValue
1010

1111
object Physics : IPhysicsService {
1212

@@ -82,34 +82,36 @@ object Physics : IPhysicsService {
8282
maxTime: Float,
8383
minAngle: Float,
8484
maxAngle: Float,
85-
angleStep: Float,
86-
tolerance: Float,
85+
optimizer: IOptimizer,
86+
getInterpolator: (points: List<Vector2>) -> Interpolator
8787
): Vector2 {
88-
var currentAngle = minAngle
89-
var bestAngle = minAngle
90-
var bestError = Float.MAX_VALUE
91-
var bestVelocity = Vector2.zero
92-
93-
while (currentAngle <= maxAngle) {
88+
val bestAngle = optimizer.optimize(
89+
Range(minAngle.toDouble(), maxAngle.toDouble()),
90+
maximize = false
91+
) { angle, _ ->
9492
val initialVelocity =
95-
Vector2(velocity * SolMath.cosDegrees(currentAngle), velocity * SolMath.sinDegrees(currentAngle))
96-
val trajectory = getTrajectory2D(initialPosition, initialVelocity, dragModel, timeStep, maxTime)
97-
98-
for (point in trajectory) {
99-
val error = (point.position - targetPosition).magnitude()
100-
if (error < bestError) {
101-
bestError = error
102-
bestAngle = currentAngle
103-
bestVelocity = initialVelocity
104-
}
105-
if (error < tolerance) {
106-
return initialVelocity
107-
}
108-
}
109-
currentAngle += angleStep
93+
Vector2(
94+
velocity * SolMath.cosDegrees(angle.toFloat()),
95+
velocity * SolMath.sinDegrees(angle.toFloat())
96+
)
97+
val trajectory =
98+
getTrajectory2D(
99+
initialPosition,
100+
initialVelocity,
101+
dragModel,
102+
timeStep,
103+
maxTime
104+
)
105+
val interpolated =
106+
getInterpolator(trajectory.map { it.position }).interpolate(
107+
targetPosition.x
108+
)
109+
(interpolated - targetPosition.y).absoluteValue.toDouble()
110110
}
111-
112-
return bestVelocity
111+
return Vector2(
112+
velocity * SolMath.cosDegrees(bestAngle.first.toFloat()),
113+
velocity * SolMath.sinDegrees(bestAngle.first.toFloat())
114+
)
113115
}
114116

115117
override fun getKineticEnergy(mass: Weight, speed: Speed): Energy {

src/test/kotlin/com/kylecorry/sol/science/physics/PhysicsTest.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,7 @@ class PhysicsTest {
4646
timeStep = 0.01f,
4747
maxTime = 1f,
4848
minAngle = 0f,
49-
maxAngle = 1f,
50-
angleStep = 0.001f
49+
maxAngle = 1f
5150
)
5251

5352
val launchAngle = initialVelocityVector.angle()

0 commit comments

Comments
 (0)