Skip to content

FW nav: replace roll PT1 smoothing with a triggered S-curve (no steady-state lag) - #11804

Open
b14ckyy wants to merge 4 commits into
iNavFlight:maintenance-10.xfrom
b14ckyy:fw-roll-smoothing
Open

FW nav: replace roll PT1 smoothing with a triggered S-curve (no steady-state lag)#11804
b14ckyy wants to merge 4 commits into
iNavFlight:maintenance-10.xfrom
b14ckyy:fw-roll-smoothing

Conversation

@b14ckyy

@b14ckyy b14ckyy commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

Summary

nav_fw_control_smoothness currently applies a PT1 low-pass to the fixed-wing nav roll command. That buys smoothness at the cost of a permanent, uncompensated lag between what the navigation controller commands and what gets executed: every course correction is delayed — including during steady tracking, where no smoothing is needed at all — and the lag grows with the smoothness setting.

This PR replaces the roll-axis PT1 with a triggered S-curve easing:

  • Fires only on an abrupt commanded-bank step (setpoint-rate change above 20% of the configured roll rate between nav loops), e.g. a new course at a waypoint or a nav-mode entry (RTH engage, WP start).
  • Eases from the pre-step output to the live target with a smoothstep over a control_smoothness-derived window (n × 100 ms, 0 = off, capped at 900 ms), then passes the command 1:1 again — zero added lag in steady tracking.
  • The window timer does not reset on further steps mid-ramp, so the smoother can never get stuck damping continuous corrections.
  • On position-controller reset the state is re-seeded to the neutral baseline: stale state cannot fire a spurious ramp, a nav-engage bank step is still detected and eased in, and a pilot roll-out already in progress (cruise stick release) is not re-commanded.

Because the smoothing is purely time-based, behavior is airframe-independent: aircraft whose natural roll response is slower than the easing window simply won't notice it.

  • Review follow-up: course lock now uses the current COG directly. The previous gyroRateDps(YAW) lead term mixed a rate (deg/s) into an angle — effectively a fixed one-second yaw lead. With the bank gate the residual turn rate at lock time is negligible, making the term obsolete.
  • Review follow-up: easing cap constant aligned to 900 ms — the documented and effective maximum with control_smoothness ≤ 9 (the previous 1000 ms cap was unreachable).

Related fix: cruise course lock only once rolled out

Flight testing the smoothing surfaced a longstanding COURSE_HOLD/CRUISE quirk that softer roll-outs make more visible: the course is locked the moment the stick is released or the mode engages — while the aircraft is still banked. It then keeps turning through the level-off, overshoots the locked course and flies a reverse correction turn.

The second commit delays the course lock until the bank is below 10°; until then the course follows the actual COG. This covers all three lock paths (roll-stick release, yaw-stick release, and a banked mode entry such as switching out of an RTH turn into CRUISE). The course now locks where the aircraft has effectively stopped turning — no overshoot, no reverse correction — and the controller reset/re-engage happens near wings-level. Fixed-wing only; multicopter course hold is unchanged.

What does NOT change

  • Same knob, same range (0–9), same intent: soft control feel and structural protection on large airframes. With control_smoothness = 0 (default) the roll command path is a pure pass-through.
  • Pitch and pitch-to-throttle PT1 smoothing are deliberately untouched.
  • No new settings, no parameter-group layout change.

Context

This is groundwork for an upcoming fixed-wing coordinated-turn / turn-predictor PR: a predictive turn controller must know its own roll-in dynamics, which an output low-pass hides. Splitting this out keeps that (much larger) PR reviewable and lets this behavior change be evaluated on its own.

Testing

  • HITL-tested on real hardware (MATEKF765) through several iterations; the n × 100 ms window scaling and the neutral re-seed behavior were both derived from these tests (RTH engage easing, cruise stick-release roll-out, mode switch out of a banked turn).
  • Field testing on multiple airframes is in progress.
  • Settings.md regenerated; nav_fw_control_smoothness description updated to match the new mechanics.

Demo: Smoothing OFF, Level 5 (500ms) and Level 9 (900ms). RTH Engage, Roll turn, yaw turn.

smoothing.mp4

@qodo-code-review

Copy link
Copy Markdown
Contributor

ⓘ Qodo reviews are paused because the subscription is no longer active. Ask your workspace admin to reactivate the subscription to resume reviews. Manage billing

@b14ckyy b14ckyy added this to the 10.0 milestone Aug 20, 2026
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

FW nav: step-triggered roll S-curve smoothing + delayed CRUISE course lock

✨ Enhancement 🐞 Bug fix 📝 Documentation 🕐 40+ Minutes

Grey Divider

AI Description

• Replace fixed-wing nav roll PT1 smoothing with a step-triggered S-curve easing window.
• Re-seed roll smoothing after controller resets to prevent stale-state ramps.
• Delay fixed-wing CRUISE course lock until bank <10° to prevent overshoot/reverse turns.
Diagram

graph TD
  A[("nav_fw_control_smoothness")] --> C["Roll S-curve smoother"]
  B["FW position controller"] --> C
  D["FW CRUISE course hold"] --> E{"Bank < 10°?"}
  H["Attitude roll"] --> E
  E -->|No| F["Follow COG (pending lock)"]
  E -->|Yes| G["Lock course + controller reset"]

  subgraph Legend
    direction LR
    _cfg[("Setting/config")] ~~~ _proc["Process/module"] ~~~ _dec{"Decision"}
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Rate/acceleration limiter on roll setpoint
  • ➕ Simpler mental model (caps roll step size per cycle)
  • ➕ Predictable bounds on commanded roll slew
  • ➖ Still modifies steady-state corrections unless carefully gated
  • ➖ Harder to guarantee “no added lag” during continuous small updates
2. Keep PT1 filter but add lead compensation / feed-forward
  • ➕ Maintains continuous smoothing behavior while reducing phase lag
  • ➕ Can be tuned to match airframe dynamics
  • ➖ More tuning complexity and airframe dependence
  • ➖ Risk of overshoot/instability if lead is mis-tuned
3. Smooth the desired course/heading target instead of roll output
  • ➕ Keeps roll controller deterministic while shaping mission/CRUISE setpoints
  • ➕ Potentially smoother behavior across multiple control axes
  • ➖ More invasive (touches nav state machine and setpoint generation paths)
  • ➖ Can distort path tracking and interacts with waypoint turn logic

Recommendation: The triggered, time-bounded S-curve on roll output is a good tradeoff for fixed-wing nav: it targets the problematic discontinuities (mode entry/waypoint heading changes) while explicitly avoiding steady-state lag. The added reseed-on-reset and non-resetting ramp timer are important safeguards. Alternatives are viable but either reintroduce steady-state bias (rate limiting), require deeper tuning/airframe-specific dynamics (lead-compensated PT1), or broaden the change surface significantly (smoothing at the course/heading level).

Files changed (4) +99 / -17

Enhancement (1) +73 / -7
navigation_fixedwing.cReplace roll PT1 smoothing with step-triggered S-curve easing +73/-7

Replace roll PT1 smoothing with step-triggered S-curve easing

• Removes the fixed-wing nav roll PT1 correction filter and adds a triggered smoothstep-based easing function that runs only when commanded-bank steps are abrupt relative to configured roll rate. Adds a reseed flag on position-controller reset to neutralize state and avoid spurious ramps after re-entry; otherwise passes roll commands 1:1 to avoid steady-state lag.

src/main/navigation/navigation_fixedwing.c

Bug fix (1) +24 / -8
navigation.cDelay FW CRUISE course lock until roll-out completes +24/-8

Delay FW CRUISE course lock until roll-out completes

• Introduces a fixed-wing-only bank-angle threshold (10°) and a persistent pending-lock flag so CRUISE/COURSE_HOLD follows actual COG while still banked. Locks course and resets the position controller only once below the bank threshold, preventing overshoot and reverse correction turns after stick release or banked mode entry.

src/main/navigation/navigation.c

Documentation (1) +1 / -1
Settings.mdDocument roll S-curve behavior for nav_fw_control_smoothness +1/-1

Document roll S-curve behavior for nav_fw_control_smoothness

• Updates the user-facing description of nav_fw_control_smoothness to reflect pitch PT1 filtering and the new roll S-curve easing window that triggers only on abrupt bank-command steps. Clarifies that steady tracking is not lagged and that 0 disables roll smoothing.

docs/Settings.md

Other (1) +1 / -1
settings.yamlUpdate nav_fw_control_smoothness setting description +1/-1

Update nav_fw_control_smoothness setting description

• Aligns the YAML settings metadata text with the new control behavior: pitch remains low-pass filtered while roll uses a triggered S-curve easing window (n×100ms, effectively max 900ms at n=9). Keeps the same parameter name/range and default.

src/main/fc/settings.yaml

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Course lock unit mismatch 🐞 Bug ≡ Correctness
Description
When FW course lock finally engages, code subtracts gyroRateDps(YAW) (deg/s) from
posControl.actualState.cog (centidegrees), mixing rate and angle units and potentially offsetting
the locked course by multiple degrees. This path is now reachable on banked mode entry due to the
new fwCruiseCourseLockPending logic, so a residual yaw rate during rollout can bias the locked
heading and cause an unnecessary correction turn.
Code

src/main/navigation/navigation.c[R1459-1462]

+        } else {
+            posControl.cruise.course = posControl.actualState.cog - DEGREES_TO_CENTIDEGREES(gyroRateDps(YAW));
+            resetPositionController();
+            fwCruiseCourseLockPending = false;
Evidence
The PR-added pending-lock logic causes the course to be locked after rollout, and at that moment it
subtracts a yaw rate (deg/s) from a course angle (centidegrees). gyroRateDps() is confirmed to
return deg/s from gyro.gyroADCf, while cruise heading is explicitly represented as centidegrees
elsewhere in navigation code.

src/main/navigation/navigation.c[1396-1401]
src/main/navigation/navigation.c[1454-1462]
src/main/sensors/gyro.c[624-631]
src/main/navigation/navigation.c[3973-3995]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`posControl.cruise.course` is stored in **centidegrees** (angle), but the lock code subtracts `DEGREES_TO_CENTIDEGREES(gyroRateDps(YAW))`, which is a **rate** (deg/s). This introduces a unit mismatch and can shift the locked course by an amount proportional to instantaneous yaw rate.

This became more impactful in this PR because the new `fwCruiseCourseLockPending` mechanism can invoke the lock path after a **banked mode entry** (not only after stick adjustment), so the course may be locked with non-zero yaw rate even though the intent is “fly straight from here”.

### Issue Context
- `gyroRateDps()` returns degrees/second.
- `posControl.cruise.course` is documented/used as centidegrees.

### Fix Focus Areas
- src/main/navigation/navigation.c[1459-1462]

### Suggested fix
Pick one of these consistent approaches:
1) **Simplest / likely intended now that you wait for bank < 10°**: lock directly to current COG:
  - `posControl.cruise.course = posControl.actualState.cog;`

2) If you truly need a rate-based correction, convert rate to an **angle delta** by multiplying by an explicit time step `dt` (seconds) available at this site (or pass it in), then subtract `yawRate * dt` (converted to centidegrees).

Keep `resetPositionController()` after locking so the controller re-engages cleanly.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

2. Smoother max-time inconsistency 🐞 Bug ⚙ Maintainability
Description
Roll smoothing is documented as “max 900 ms” (because control_smoothness max is 9), but the
code/comment defines a 1000 ms cap, which is currently unreachable and can confuse future
maintainers or doc users. This mismatch increases the risk of later changing the setting max (or
reuse) and silently diverging from docs.
Code

src/main/navigation/navigation_fixedwing.c[R62-68]

+// Roll-command S-curve smoothing: control_smoothness (0..9) -> easing window = n*100 ms (0 = off),
+// capped at 1000 ms. Triggered only on an abrupt commanded-bank step (>20% of the configured roll
+// rate between nav loops), then eased over the window and passed 1:1 afterwards. Unlike the previous
+// PT1 low-pass this never lags steady tracking, so the controller command stays deterministic.
+#define NAV_FW_SMOOTH_TCONST_PER_STEP_MS  100.0f
+#define NAV_FW_SMOOTH_TCONST_MAX_MS       1000.0f
+#define NAV_FW_SMOOTH_STEP_FRACTION       0.2f
Evidence
The PR updates docs/settings to describe a 900ms maximum and keeps the setting max at 9, while the
PR also introduces a 1000ms cap constant and comment in code.

src/main/fc/settings.yaml[3058-3064]
docs/Settings.md[3641-3644]
src/main/navigation/navigation_fixedwing.c[62-68]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
Docs/settings say the roll easing window is `n * 100ms (max 900ms)` and the setting max is 9, but code comments/constants claim a 1000ms cap. Today the effective max is still 900ms, but the inconsistency is misleading.

### Issue Context
- `nav_fw_control_smoothness` max is 9.
- Docs describe max 900ms.
- Code defines `NAV_FW_SMOOTH_TCONST_MAX_MS 1000.0f` and comment says “capped at 1000 ms”.

### Fix Focus Areas
- src/main/navigation/navigation_fixedwing.c[62-68]
- src/main/fc/settings.yaml[3058-3064]
- docs/Settings.md[3641-3644]

### Suggested fix
Either:
- Change `NAV_FW_SMOOTH_TCONST_MAX_MS` and the comment to 900ms, matching the setting range and docs, **or**
- Keep 1000ms and update docs/setting max accordingly (e.g., allow 10) so behavior matches documentation.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can copy the agent prompt from any finding and feed it to your IDE agent

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread src/main/navigation/navigation.c
Comment thread src/main/navigation/navigation_fixedwing.c Outdated
…y-state lag)

nav_fw_control_smoothness applied a PT1 low-pass to the FW nav roll command.
That trades smoothness for a permanent, uncompensated lag between what the
navigation controller commands and what is executed: every course correction
is delayed, also during steady tracking where no smoothing is needed, and the
lag grows with the smoothness setting.

Replace the roll-axis PT1 with a triggered S-curve easing:

- Fires only on an abrupt commanded-bank step (setpoint-rate change above 20%
  of the configured roll rate between nav loops), e.g. a new course at a
  waypoint or a nav-mode entry (RTH engage, WP start).
- Eases from the pre-step output to the live target with a smoothstep over a
  control_smoothness-derived window (n x 100 ms, 0 = off, capped at 1000 ms),
  then passes the command 1:1 again.
- The window timer does not reset on further steps mid-ramp, so the smoother
  can never get stuck damping steady tracking.
- On position-controller reset the smoother re-seeds from the last applied
  nav roll command when nav was commanding until just now (nav-mode to
  nav-mode transition, e.g. RTH -> CRUISE: the level-off is eased), and from
  the neutral baseline after a pilot-flown phase (stick release: a roll-out
  in progress is not re-commanded). Stale state can never fire a spurious
  ramp.

Same knob, same range and same intent (soft control feel, structural
protection on large airframes); the pitch/pitch-to-throttle PT1 smoothing is
deliberately unchanged. No settings or PG layout changes.

HITL-tested on real hardware (window rescaled to n x 100 ms from flight
observation; re-seed behavior derived from RTH engage, cruise stick release
and RTH->CRUISE fallback tests).
In COURSE_HOLD/CRUISE the course is locked the moment the mode engages or the
pilot releases the stick (roll-stick path: last course stored in ADJUSTING;
yaw path: on release with a one-iteration gyro lead; mode entry: in
INITIALIZE). If the aircraft is still banked at that moment - stick released
mid-turn, or the mode switched out of e.g. an RTH turn - it keeps turning
through the level-off, overshoots the locked course and flies a reverse
correction turn. A longstanding annoyance, made more visible by softer
roll-out (control smoothing).

Delay the course lock until the roll-out is actually complete: while the bank
is above 10 deg the course keeps following the actual COG (roll-stick path
stays in ADJUSTING; yaw release and banked mode entry share one lock-pending
flag), then locks with the gyro-lead compensation. The course now locks where
the aircraft has effectively stopped turning - no overshoot, no reverse
correction - and the controller reset/re-engage happens near wings-level, so
the smoothing re-seed cannot cause a roll jerk.

Fixed-wing only; multicopter course hold is unaffected.
@b14ckyy
b14ckyy force-pushed the fw-roll-smoothing branch from f6ca64d to 4c9288a Compare August 20, 2026 18:20
@github-actions

github-actions Bot commented Aug 20, 2026

Copy link
Copy Markdown

Test firmware build ready — commit fb3ccf0

Download firmware for PR #11804

244 targets built. Find your board's .hex file by name on that page (e.g. MATEKF405SE.hex). Files are individually downloadable — no GitHub login required.

Development build for testing only. Use Full Chip Erase when flashing.

@github-actions

github-actions Bot commented Aug 20, 2026

Copy link
Copy Markdown

RAM / Flash usage vs. base branch — commit fb3ccf0

Target Flash Δ RAM Δ
MATEKF405 ⚠️ +332 B (+0.05%) +24 B (+0.02%)
MATEKF722 ⚠️ +408 B (+0.09%) +40 B (+0.03%)
MATEKF765 ⚠️ +456 B (+0.07%) +32 B (+0.02%)
MATEKH743 ⚠️ +472 B (+0.07%) ±0 B (±0.00%)

See RAM/flash optimization guide for techniques to reduce usage.

…asing cap to 900ms

The course-lock applied 'cog - DEGREES_TO_CENTIDEGREES(gyroRateDps(YAW))',
mixing a rate (deg/s) into an angle - effectively a fixed one-second yaw
lead. With the new bank gate the turn has essentially stopped at lock time,
so lock directly to the current COG.

NAV_FW_SMOOTH_TCONST_MAX_MS claimed a 1000ms cap that was unreachable with
control_smoothness max 9 (n x 100ms = 900ms); set the cap and comments to
900ms to match the setting range and documentation.
@b14ckyy

b14ckyy commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator Author

Resource cost vs maintenance-10.x (8994327)

Target Flash Δ RAM Δ
MATEKF405 +256 B +24 B
MATEKF722 +384 B +32 B
MATEKF765 +384 B +24 B
MATEKH743 +384 B +32 B

(measured with arm-none-eabi-size: flash = text+data, RAM = data+bss)

@sensei-hacker

Copy link
Copy Markdown
Member

Hmm something I'm not sure aobut:

COURSE_HOLD/CRUISE: the course is locked the moment the stick is released or the mode engages — while the aircraft is still banked. It then keeps turning through the level-off, overshoots the locked course and flies a reverse correction turn.

The second commit delays the course lock until the bank is below 10°; until then the course follows the actual COG.

Centering the stick in COURSE_HOLD sets the course. Yeah I'm not sure that's a bug?
I'm not overly committed to keeping that, but I'm not sure if we need to change it?

@b14ckyy

b14ckyy commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator Author

The problem is that when you are in a CRSH or CRUZ turn with roll or yaw stick and you quickly release it, the plane is still at full bank. So it continues to turn for a few degrees before it levels off. that means it ALWAYS overshoots the new set COG at stick center time and makes an S-turn correction the other way. Even worse, if you enable cruise mode out of a sharp turn in angle mode or WP mode, the plane is all over the place going back to the ground course the plane had at the time of mode enabling.

Roll smoothing boosts this behavior even more (also the old PT1 method).

Locking the course at level off instead is fully adaptive and always guarantees a solid flight that only does commanded maneuvers and no weaving. Plus it prevents the plane from permanent S-Turns if the Roll FF is overturned as it won't start to hunt its own nose.

@b14ckyy

b14ckyy commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator Author

But if we make that change the docs need an update I just realize. If you give the OK I will do that

@sensei-hacker

Copy link
Copy Markdown
Member

the plane is still at full bank. So it continues to turn for a few degrees before it levels off. that means it ALWAYS overshoots the new set COG

Yes, agreed - if you're in a steep bank and center the stick, the plane will continue to turn briefly. Always, meaning we can't change that, agreed.

What is proposed here is to make it continue to overshoot the course that the pilot requested? I'm not clear on why that's a great idea.

@b14ckyy

b14ckyy commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator Author

It makes it more intuitive and nicer/smoother to fly.
Intuitively centering the stick means "level off the plane" and not "set a course wherever your nose points at that moment"

If you fly a real plane and you want to fly towards heading 120° you also don't keep full stick until you reach 120, then start to level off and turn back to actually hit 120. Right?

So with the change the pilot still can ease down the bank turn rate and level off exactly where he wants to go and if its a snap release, its whatever the plane ends off when level. And then stays on that course

@b14ckyy

b14ckyy commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator Author

Compromise: I make it a setting nav_fw_cruise_lock_on_level as a boolean. With configurator
So you can switch the behavior.

@breadoven

breadoven commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator

Compromise: I make it a setting nav_fw_cruise_lock_on_level as a boolean. With configurator So you can switch the behavior.

This would be a better idea because one of the reasons for #10187 was to stop the problem of the course drifting away from the course at stick centre making it awkward to get the plane pointing where you want it. Although admittedly that was largely down to the fact that the controller wasn't being reset after adjustment using the Yaw stick prior to 10187.

@b14ckyy

b14ckyy commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator Author

Alright I will make it settings gated. With Stick Center lock, your #10187 still matters. Roll turns in cruise will still overshoot and back-correct. With Level-Lock both control options will be steady and lock course exactly when levelled off.

@b14ckyy

b14ckyy commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator Author

Setting implemented. Configurator PR open and will commit firmware side when tested.

…fault ON)

On maintainer feedback the level-off course lock in course hold is a
behavior change, so make it optional: ON locks the course only once
rolled out below 10 deg bank (new behavior), OFF locks on stick
center / mode entry as before. Bumps PG_NAV_CONFIG to 9.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@b14ckyy

b14ckyy commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator Author

Setting works as expected. Default is the new behavior, can be turned off for old behavior. Hope thats okay.

level_lock.mp4

@MartinovEm

MartinovEm commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Hey Mark, I was checking this PR against my terrain following PR (#11785 lives in 3D Cruise for now, so I wanted to be sure the new course-lock logic doesn't interact with it - it doesn't, great :)) ) and one thing popped out - the lock-on-level wait has no timeout. If the plane stays banked over 10dg for a while (wind gusts, bumpy air around the threshold, or just a badly trimmed plane, the angle loop doesn't fully level), the course is never locked - Cruise follows the COG with zero roll command and quietly stops holding a course, while still showing CRUZ. It doesn't seem dangerous to me (well i might be wrong, so I won't conclude that strongly), but the pilot can't tell. Maybe lock anyway after 2–3 s as a fallback won't hurt anyone.

@b14ckyy

b14ckyy commented Aug 22, 2026

Copy link
Copy Markdown
Collaborator Author

Hey, its Marc ;)
JK. The "will never level" is technically impossible. Even if its bumpy it will randomly roll over that 20° range (10° each direction) and unless each bumpyness is so strong and so perfectly timed that the plane rolls over the zone at more than 1000°/s every time, perfectly timed that it misses each of the 50hz navigation loop rate, its impossible to miss. Otherwise you should play the lottery and win a few million every time 10 times in a row.

and as long as there is an error in the angle, the Angle P control will keep pushing and the roll PID controller will push harder and harder until it goes level. if something on the plane is so broken that it will be stuck outside of that 10° threshold, then you should not even fly in a nav mode and fix it.

@MartinovEm

Copy link
Copy Markdown
Contributor

That makes sense, was focused on the lock logic itself and forgot the angle loop is pushing toward level the whole time.
And the "k" - I went by the German analogy: ECG is EKG over there, so Marc became Mark :D sorry :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants