1 #include "a/trajtrap.h"
4 #if A_PREREQ_GNUC(3, 0) || __has_warning("-Wfloat-equal")
5 #pragma GCC diagnostic ignored "-Wfloat-equal"
6 #endif /* -Wfloat-equal */
8 a_float
a_trajtrap_gen(a_trajtrap
*ctx
, a_float vm
, a_float ac
, a_float de
,
9 a_float p0
, a_float p1
, a_float v0
, a_float v1
)
11 a_float v02
, v12
, vc2
;
12 a_float
const p
= p1
- p0
;
13 a_float
const _2p
= 2 * p
;
14 a_bool
const reversed
= p
< 0;
15 if (ac
== de
) { return 0; }
16 if (vm
< 0) { vm
= -vm
; }
17 v0
= A_SAT(v0
, -vm
, +vm
);
18 v1
= A_SAT(v1
, -vm
, +vm
);
25 vc2
= (v12
* ac
- v02
* de
- _2p
* ac
* de
) / (ac
- de
);
26 if (vc2
<= 0) { return 0; }
27 if (vc2
> vm
* vm
) /* acceleration, constant velocity, deceleration */
29 ctx
->vc
= reversed
? -vm
: vm
;
30 ctx
->ta
= (ctx
->vc
- v0
) / ac
;
31 ctx
->t
= (v1
- ctx
->vc
) / de
;
32 ctx
->pa
= p0
+ ctx
->v0
* ctx
->ta
+ A_FLOAT_C(0.5) * ac
* ctx
->ta
* ctx
->ta
;
33 ctx
->pd
= p1
- ctx
->vc
* ctx
->t
- A_FLOAT_C(0.5) * de
* ctx
->t
* ctx
->t
;
34 ctx
->td
= ctx
->ta
+ (ctx
->pd
- ctx
->pa
) / ctx
->vc
;
37 else if (vc2
> v02
&& vc2
<= v12
) /* acceleration */
40 if (v12
< 0) { return 0; }
41 ctx
->v1
= a_float_sqrt(v12
);
42 if (reversed
) { ctx
->v1
= -ctx
->v1
; }
44 ctx
->t
= (ctx
->v1
- v0
) / ac
;
47 ctx
->pa
= p0
+ ctx
->v0
* ctx
->t
+ A_FLOAT_C(0.5) * ac
* ctx
->t
* ctx
->t
;
50 else if (vc2
<= v02
&& vc2
> v12
) /* deceleration */
53 if (v12
< 0) { return 0; }
54 ctx
->v1
= a_float_sqrt(v12
);
55 if (reversed
) { ctx
->v1
= -ctx
->v1
; }
57 ctx
->t
= (ctx
->v1
- v0
) / de
;
63 else /* acceleration, deceleration */
65 ctx
->vc
= a_float_sqrt(vc2
);
66 if (reversed
) { ctx
->vc
= -ctx
->vc
; }
67 ctx
->t
= (ctx
->vc
- v0
) / ac
;
70 ctx
->pa
= p0
+ ctx
->v0
* ctx
->t
+ A_FLOAT_C(0.5) * ac
* ctx
->t
* ctx
->t
;
71 ctx
->t
+= (v1
- ctx
->vc
) / de
;
79 a_float
a_trajtrap_pos(a_trajtrap
const *ctx
, a_float dt
)
83 if (dt
< ctx
->td
) /* linear motion */
85 return ctx
->pa
+ ctx
->vc
* (dt
- ctx
->ta
);
87 if (dt
< ctx
->t
) /* final blend */
90 return ctx
->pd
+ ctx
->vc
* dt
+ A_FLOAT_C(0.5) * ctx
->de
* dt
* dt
;
94 if (dt
> 0) /* initial blend */
96 return ctx
->p0
+ ctx
->v0
* dt
+ A_FLOAT_C(0.5) * ctx
->ac
* dt
* dt
;
101 a_float
a_trajtrap_vel(a_trajtrap
const *ctx
, a_float dt
)
105 if (dt
< ctx
->td
) /* linear motion */
109 if (dt
< ctx
->t
) /* final blend */
111 return ctx
->vc
+ ctx
->de
* (dt
- ctx
->td
);
115 if (dt
> 0) /* initial blend */
117 return ctx
->v0
+ ctx
->ac
* dt
;
122 a_float
a_trajtrap_acc(a_trajtrap
const *ctx
, a_float dt
)
126 if (dt
>= 0) /* initial blend */
131 else if (dt
>= ctx
->td
)
133 if (dt
<= ctx
->t
) /* final blend */
138 return 0; /* linear motion */