mirror of
https://github.com/orange-cpp/omath.git
synced 2026-02-13 07:03:25 +00:00
163 lines
5.5 KiB
Markdown
163 lines
5.5 KiB
Markdown
# `omath::projectile_prediction::ProjPredEngineInterface` — Aim-point solver interface
|
||
|
||
> Header: your project’s `projectile_prediction/proj_pred_engine_interface.hpp`
|
||
> Namespace: `omath::projectile_prediction`
|
||
> Depends on: `Vector3<float>`, `Projectile`, `Target`
|
||
> Purpose: **contract** for engines that compute a lead/aim point to hit a moving target.
|
||
|
||
---
|
||
|
||
## Overview
|
||
|
||
`ProjPredEngineInterface` defines a single pure-virtual method that attempts to compute the **world-space aim point** where a projectile should be launched to intersect a target under the engine’s physical model (e.g., constant projectile speed, gravity, drag, max flight time, etc.).
|
||
|
||
If a valid solution exists, the engine returns the 3D aim point. Otherwise, it returns `std::nullopt` (no feasible intercept).
|
||
|
||
---
|
||
|
||
## API
|
||
|
||
```cpp
|
||
namespace omath::projectile_prediction {
|
||
|
||
class ProjPredEngineInterface {
|
||
public:
|
||
[[nodiscard]]
|
||
virtual std::optional<Vector3<float>>
|
||
maybe_calculate_aim_point(const Projectile& projectile,
|
||
const Target& target) const = 0;
|
||
|
||
virtual ~ProjPredEngineInterface() = default;
|
||
};
|
||
|
||
} // namespace omath::projectile_prediction
|
||
```
|
||
|
||
### Semantics
|
||
|
||
* **Input**
|
||
|
||
* `Projectile` — engine-specific projectile properties (typical: muzzle speed, gravity vector, drag flag/coeff, max range / flight time).
|
||
* `Target` — target state (typical: position, velocity, possibly acceleration).
|
||
|
||
* **Output**
|
||
|
||
* `std::optional<Vector3<float>>`
|
||
|
||
* `value()` — world-space point to aim at **now** so that the projectile intersects the target under the model.
|
||
* `std::nullopt` — no solution (e.g., target outruns projectile, blocked by constraints, numerical failure).
|
||
|
||
* **No side effects**: method is `const` and should not modify inputs.
|
||
|
||
---
|
||
|
||
## Typical usage
|
||
|
||
```cpp
|
||
using namespace omath::projectile_prediction;
|
||
|
||
std::unique_ptr<ProjPredEngineInterface> engine = /* your implementation */;
|
||
Projectile proj = /* fill from weapon config */;
|
||
Target tgt = /* read from tracking system */;
|
||
|
||
if (auto aim = engine->maybe_calculate_aim_point(proj, tgt)) {
|
||
// Rotate/steer to (*aim)
|
||
} else {
|
||
// Fall back: no-lead, predictive UI, or do not fire
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## Implementation guidance (for engine authors)
|
||
|
||
**Common models:**
|
||
|
||
1. **No gravity, constant speed**
|
||
Closed form intersect time `t` solves `‖p_t + v_t t − p_0‖ = v_p t`.
|
||
Choose the smallest non-negative real root; aim point = `p_t + v_t t`.
|
||
|
||
2. **Gravity (constant g), constant speed**
|
||
Solve ballistics with vertical drop: either numerical (Newton–Raphson on time) or 2D elevation + azimuth decomposition. Ensure convergence caps and time bounds.
|
||
|
||
3. **Drag**
|
||
Typically requires numeric integration (e.g., RK4) wrapped in a root find on time-of-flight.
|
||
|
||
**Robustness tips:**
|
||
|
||
* **Feasibility checks:** return `nullopt` when:
|
||
|
||
* projectile speed ≤ 0; target too fast in receding direction; solution time outside `[0, t_max]`.
|
||
* **Bounds:** clamp search time to reasonable `[t_min, t_max]` (e.g., `[0, max_flight_time]` or by range).
|
||
* **Tolerances:** use epsilons for convergence (e.g., `|f(t)| < 1e-4`, `|Δt| < 1e-4 s`).
|
||
* **Determinism:** fix iteration counts or seeds if needed for replayability.
|
||
|
||
---
|
||
|
||
## Example: constant-speed, no-gravity intercept (closed form)
|
||
|
||
```cpp
|
||
// Solve ||p + v t|| = s t where p = target_pos - shooter_pos, v = target_vel, s = projectile_speed
|
||
// Quadratic: (v·v - s^2) t^2 + 2 (p·v) t + (p·p) = 0
|
||
inline std::optional<float> intercept_time_no_gravity(const Vector3<float>& p,
|
||
const Vector3<float>& v,
|
||
float s) {
|
||
const float a = v.dot(v) - s*s;
|
||
const float b = 2.f * p.dot(v);
|
||
const float c = p.dot(p);
|
||
if (std::abs(a) < 1e-6f) { // near linear
|
||
if (std::abs(b) < 1e-6f) return std::nullopt;
|
||
float t = -c / b;
|
||
return t >= 0.f ? std::optional{t} : std::nullopt;
|
||
}
|
||
const float disc = b*b - 4.f*a*c;
|
||
if (disc < 0.f) return std::nullopt;
|
||
const float sqrtD = std::sqrt(disc);
|
||
float t1 = (-b - sqrtD) / (2.f*a);
|
||
float t2 = (-b + sqrtD) / (2.f*a);
|
||
float t = (t1 >= 0.f ? t1 : t2);
|
||
return t >= 0.f ? std::optional{t} : std::nullopt;
|
||
}
|
||
```
|
||
|
||
Aim point (given shooter origin `S`, target pos `T`, vel `V`):
|
||
|
||
```
|
||
p = T - S
|
||
t* = intercept_time_no_gravity(p, V, speed)
|
||
aim = T + V * t*
|
||
```
|
||
|
||
Return `nullopt` if `t*` is absent.
|
||
|
||
---
|
||
|
||
## Testing checklist
|
||
|
||
* **Stationary target**: aim point equals target position when `s > 0`.
|
||
* **Target perpendicular motion**: lead equals lateral displacement `V⊥ * t`.
|
||
* **Receding too fast**: expect `nullopt`.
|
||
* **Gravity model**: verify arc solutions exist for short & long trajectories (if implemented).
|
||
* **Numerics**: convergence within max iterations; monotonic improvement of residuals.
|
||
|
||
---
|
||
|
||
## Notes
|
||
|
||
* This is an **interface** only; concrete engines (e.g., `SimpleNoGravityEngine`, `BallisticGravityEngine`) should document their assumptions (gravity, drag, wind, bounds) and units (meters, seconds).
|
||
* The coordinate system and handedness should be consistent with `Vector3<float>` and the rest of your math stack.
|
||
|
||
---
|
||
|
||
## See Also
|
||
|
||
- [Projectile Documentation](projectile.md) - Projectile properties
|
||
- [Target Documentation](target.md) - Target state representation
|
||
- [Legacy Implementation](proj_pred_engine_legacy.md) - Standard projectile prediction engine
|
||
- [AVX2 Implementation](proj_pred_engine_avx2.md) - Optimized AVX2 engine
|
||
- [Tutorials - Projectile Prediction](../tutorials.md#tutorial-3-projectile-prediction-aim-bot) - Complete aim-bot tutorial
|
||
|
||
---
|
||
|
||
*Last updated: 1 Nov 2025*
|