-
Notifications
You must be signed in to change notification settings - Fork 369
Maintenance 9.x to master #2479
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Update SITL binaries for 9.0.0-RC3
Reduce MSP requests from 64 to 1+N (mask + configured conditions only). Requires firmware support for MSP2_INAV_LOGIC_CONDITIONS_CONFIGURED (0x203C).
…optimized-load Optimize logic conditions loading
Changes Settings.processHtml to call its callback immediately instead of waiting for all settings to load. This allows tabs to start rendering while settings populate in the background. Key changes: - js/settings.js: configureInputs() now runs async, callback fires immediately for progressive rendering - tabs/osd.js: Added guards in updatePreviews(), updatePilotAndCraftNames(), and fillCustomElementsValues() to handle being called before data loads - tabs/osd.js: Call updatePilotAndCraftNames() from updateAll() to ensure it runs after OSD data is available This significantly improves perceived load time for tabs with many settings (e.g., OSD tab with 67+ settings).
Apply qodo-merge suggestion: check that customElementItems exists before entering the inner loop, not just the parent items[i] object.
The settingsPromise is now passed to the processHtml callback, allowing tabs to optionally await it if they need settings values immediately. Existing tabs work unchanged - they can simply ignore the parameter. Also reverts settingsCache.js to match original code structure.
… or master Replace semver version checks with runtime capability detection for loading logic conditions. This will allow a newer configurator to work with 9.0.0-RC1 firmware. ALso nightly firmware build from between 8 and 9. Always tries the optimized CONFIGURED mask path first (MSP2_INAV_LOGIC_CONDITIONS_CONFIGURED) Falls back to legacy path (fetch all 64) if: - Firmware returns unsupported/empty response - No response within 500ms timeout This approach removes hardcoded version checks (5.0.0, 9.0.0)
…c-conditions Make optimized logic condition loading compatible with earlier 9.0-RCx or master
- Remove premature loadOsdCustomElements() call during tab init (OSD.reload() already calls it in proper sequence) - Remove premature updatePilotAndCraftNames() call during tab init (already added to updateAll() in previous commit) - Remove explanatory comments (code is self-documenting)
… or master Replace semver version checks with runtime capability detection for loading logic conditions. This will allow a newer configurator to work with 9.0.0-RC1 firmware. ALso nightly firmware build from between 8 and 9. Always tries the optimized CONFIGURED mask path first (MSP2_INAV_LOGIC_CONDITIONS_CONFIGURED) Falls back to legacy path (fetch all 64) if: - Firmware returns unsupported/empty response - No response within 500ms timeout This approach removes hardcoded version checks (5.0.0, 9.0.0)
The Common Subexpression Elimination (CSE) optimizer incorrectly reused
cached conditions when the underlying variable had been mutated between
uses. This caused incorrect code generation where the second check would
reuse the first condition's result instead of re-evaluating.
Example that was broken:
```javascript
if (gvar[1] < 2) { gvar[1]++; }
if (gvar[1] < 2) { gvar[1]++; } // This incorrectly reused first check
```
Root causes and fixes:
1. Parser: transformBodyStatement() didn't handle UpdateExpression (++/--)
inside if bodies, causing them to be silently dropped
2. Optimizer: CSE cache wasn't invalidated when variables were mutated
in statement bodies
3. Analyzer: detectConflicts() incorrectly grouped separate if statements
with the same condition, causing spurious "Multiple assignments" warnings
Changes:
- parser.js: Handle UpdateExpression in transformBodyStatement()
- optimizer.js: Add findMutatedVariables(), invalidateCacheForVariable(),
and conditionKeyReferencesVariable() to track mutations and invalidate
affected cache entries after processing each statement
- analyzer.js: Use unique keys per if statement (by index) instead of
grouping by condition, fixing spurious assignment conflict warnings
- action_generator.js: Pass conditionGenerator reference for additional
codegen-level cache invalidation
- codegen.js: Pass conditionGenerator to ActionGenerator context
- condition_generator.js: Add invalidateCacheForVariable() and
cacheKeyReferencesVariable() for runtime cache invalidation
Test coverage:
- test_cse_mutation_bug.js: 6 tests covering increment, assignment,
pre-increment, unrelated mutation (should NOT invalidate), multiple
mutations, and complex expressions
Add full support for programming PID controllers (pid[0] through pid[3])
in the JavaScript transpiler. INAV exposes only the output property via
logic conditions (operand type 6).
Changes:
- codegen.js: Add pid[N] and pid[N].output parsing in getOperand()
- decompiler.js: Convert PID operands to pid[N].output syntax
- decompiler.js: Auto-import pid when PID operands are detected
- property_access_checker.js: Validate pid[0-3] array access
Usage:
// Both forms are equivalent (like rc[N] and rc[N].value)
gvar[0] = pid[0].output;
gvar[0] = pid[0];
// Use in conditions
if (pid[0] > 500) {
gvar[1] = pid[0] + 100;
}
CLI command "logic 0 1 -1 14 6 3 0 3000 0" now decompiles to:
gvar[0] = (pid[3].output + 3000);
Improves decompilation quality by distinguishing between: - Boolean operations (EQUAL, GT, LT, AND, OR, etc.) - chain in if() conditions - Value operations (ADD, SUB, MUL, DIV, MIN, MAX) - inline as expressions - Action operations (GVAR_SET, OVERRIDE_THROTTLE) - output as statements Changes: - decompiler.js: Add isBooleanOperation() to classify operation types - decompiler.js: Only chain boolean conditions with &&, skip value computations - decompiler.js: Inline value computations when referenced, even with activators - decompiler.js: Fix gap marker handling in orphan detection loop - action_decompiler.js: Fix OVERRIDE_THROTTLE to use operandA (not operandB) Before: All non-action LCs were &&'d together creating invalid conditions After: Value computations are properly inlined into expressions Example improvement: Before: override.throttle = 0; After: override.throttle = Math.max(Math.min(1800, ((pid[3].output + 3000) / 2)), ...);
Major refactor of the decompiler to use tree-based rendering instead of
flat group processing. This properly handles INAV's activator model where
LCs with the same activator run in parallel, not as AND chains.
Key changes:
Decompiler architecture:
- New decompileWithTrees() replaces groupConditions/decompileGroup
- buildConditionTree() creates hierarchical {lc, children} structure
- decompileTree() recursively renders with proper nesting
- detectSpecialPatternForNode() identifies EDGE/STICKY/DELAY/TIMER
Sticky syntax - all stickys now use variable + if style:
latch1 = sticky({
on: () => condition1,
off: () => condition2
});
if (latch1) { /* body */ }
Benefits:
- Consistent style for all stickys
- Clear separation of state definition vs usage
- Referenced stickys shown even without action children
- Matches mental model of stateful latch
Other improvements:
- EDGE/DELAY rendered as function calls: edge(cond, 100)
- DELTA rendered as delta(value, threshold)
- Arithmetic simplification: x + 0 → x, x * 1 → x
- NOT operator precedence fix: !(complex expr)
- GVAR action refs shown as gvar[N] not logicCondition[N]
Test updates:
- Warning tests use invalid type (99) instead of PID (now supported)
- Chained condition tests expect nested ifs instead of && chains
Expression hoisting for deeply nested function calls: - Extracts inner Math.round/min/max calls to descriptive variables - Triggers when nesting depth exceeds 3 levels - Variable names: rounded, clamped, bounded, floored, ceiled, absolute - Deduplicates identical expressions (reuses same variable) - Removes superfluous outer parentheses from assignments Before: gvar[0] = (Math.min(110, Math.max(0, Math.round((rc[12] - 1000) * 110 / 1000))) * 28); After: let rounded = Math.round((rc[12] - 1000) * 110 / 1000); gvar[0] = Math.min(110, Math.max(0, rounded)) * 28; Other changes: - Sticky latch declarations now use 'var' instead of 'let' to allow reassignment (transpiler requires 'var' for mutable variables) - Multi-line action output (hoisted vars + assignment) properly indented
Adds nested 'mode' object to flight API allowing code like:
if (flight.mode.poshold === 1) { ... }
if (flight.mode.rth) { ... }
This uses OPERAND_TYPE.FLIGHT_MODE (type 3) instead of OPERAND_TYPE.FLIGHT,
mapping to INAV's logic condition flight mode operands.
Available modes:
- failsafe, manual, rth, poshold, cruise, althold
- angle, horizon, air, acro, anglehold
- courseHold, waypointMission
- user1, user2, user3, user4
This fixes the decompiler/compiler round-trip where decompiled code
containing flight.mode.* couldn't be recompiled.
This commit enables decompiled JavaScript code to compile back to logic conditions (round-trip support). Key fixes: Compiler improvements: - parser.js: Add StickyAssignment node type, preserve CallExpression AST for function calls in arithmetic expressions - codegen.js: Track latch variables with latchVariables Map, generate STICKY logic conditions from sticky() calls, handle nested stickys - condition_generator.js: Add edge() and delta() handlers for sticky on/off conditions, resolve latch variable references to LC indices - arrow_function_helper.js: Preserve CallExpression in transformCondition - expression_generator.js: Add Literal, Identifier, MemberExpression cases to expression type switch Decompiler improvements: - decompiler.js: Skip conditions consumed by STICKY/EDGE/DELAY siblings, prevent duplicate variable declarations - condition_decompiler.js: Remove unsupported Math.round() from MAP_INPUT/MAP_OUTPUT (INAV integer division truncates) - action_decompiler.js: Update hoisting patterns to exclude Math.round Tests: - Add 3 new tests for duplicate sticky and empty block prevention - All 126 transpiler tests pass The full jetrell-logic.txt now round-trips successfully: decompile → 37 commands → recompile → 37 commands
This commit fixes several issues with compiling decompiled JavaScript
code that contains sticky assignments inside if blocks.
Parser fixes:
- parser.js: Recognize var latch = sticky({...}) in variable declarations
- parser.js: Add VariableDeclaration support in transformBodyStatement()
Analyzer fixes:
- analyzer.js: Add StickyAssignment case to analyzeStatement()
- analyzer.js: Add handleStickyAssignment() to register latch variables
- variable_handler.js: Add addLatchVariable() for sticky state variables
Codegen fixes:
- codegen.js: Pass activatorId to generateStickyAssignment()
- codegen.js: generateStickyAssignment() now properly inherits activator
Decompiler fixes:
- decompiler.js: reconstructVarVariables() skips latch variables to
avoid duplicate declarations (latch vars use sticky declarations)
Tests:
- Added test for nested sticky compilation with correct activators
- All 27 decompiler tests pass, 127+ total transpiler tests pass
Example that now works:
if (flight.gpsValid === 1) {
var latch1 = sticky({on: () => ..., off: () => ...});
if (latch1) { gvar[0] = 1; }
}
This commit fixes several issues that caused decompiled code to compile incorrectly on subsequent round-trips. Parser fixes (parser.js): - Add BinaryExpression handling in extractValue() to compute constant expressions like (50 * 28) at parse time - Add CallExpression handling for Math.min/Math.max expressions Arrow Function Helper fixes (arrow_function_helper.js): - Add BinaryExpression handling in extractValue() for expressions in arrow function conditions like () => flight.airSpeed > (50 * 28) Condition Generator fixes (condition_generator.js): - Fix gvar truthy checks: gvar[0] now compiles to NOT(gvar[0] === 0) instead of gvar[0] === 1, which correctly handles any non-zero value as truthy rather than only checking for value 1 Condition Decompiler fixes (condition_decompiler.js): - Fix NOT simplification: !(x === 0) now correctly simplifies to x (truthy check), not !x (falsy check) - these have opposite semantics - Fix double negation: !(!x) correctly simplifies to x - Preserve correct semantics for falsy vs truthy checks Decompiler fixes (decompiler.js): - Skip latch* variables in reconstructVarVariables() to avoid outputting stale latch variable declarations from previous compilations All 127+ tests pass.
This commit fixes two issues that caused "Variable already declared"
errors when recompiling decompiled JavaScript code:
1. Sticky variable declarations now use inline syntax:
- Changed renderStickyWithLatch() to output "var latch1 = sticky({...})"
instead of just "latch1 = sticky({...})"
- Removed generateStickyVarDeclarations() function entirely
- Sticky variables are now declared at their point of use
2. Let variable declarations skip duplicates from hoisting:
- generateBoilerplate() now filters let declarations from variableMap
if the body already contains a declaration for that variable
- Prevents duplicate "let clamped" from both variableMap and
expression hoisting
Also adds toMatch() assertion to the test runner for regex matching.
Tests added:
- "should use inline var declarations for sticky"
- "should not produce duplicate let declarations from variableMap and hoisting"
All 29 decompiler tests pass, round-trip compilation verified with
complex jetrell_logic test case (48 commands).
Changed the decompiler to output explicit comparisons for clearer, simpler round-trip compilation: - `gvar[0]` (truthy) now outputs as `gvar[0] !== 0` - `!gvar[1]` (negated truthy) now outputs as `gvar[1] === 0` This simplifies both compiler and decompiler: - Compiler: explicit comparison generates 1 LC (GREATER_THAN or EQUAL) vs truthy which generates 2 LCs (EQUAL + NOT) - Decompiler: direct output vs pattern detection to simplify NOT(x===0) The explicit syntax is also semantically unambiguous - truthy could mean either "!= 0" or "=== 1" depending on context.
Consolidates duplicated code from parser.js and arrow_function_helper.js into a single expression_utils.js module. Changes: - New: expression_utils.js with extractValue(), extractIdentifier(), and createExtractionHelpers() functions - parser.js: Delegates to shared implementation, adds CallExpression hook - arrow_function_helper.js: Delegates to shared implementation - New: 34 tests covering all cases in expression_utils.test.cjs This addresses Item #1 from the transpiler simplification review. Reduces ~150 lines of duplicated code to a single shared module. All 34 expression_utils tests pass All 29 decompiler tests pass All 37 variable_handler tests pass All 14 let_integration tests pass
Removes 240 lines of unused code that was replaced by the tree-based decompiler (decompileWithTrees): - collectDescendants() - only called from groupConditions() - groupConditions() - never called - decompileActionOrCondition() - only called from decompileGroup() - decompileGroup() - never called These were remnants of the older group-based decompilation approach. The tree-based approach provides better output and is what's currently used. All 29 decompiler tests pass.
Decompiler (121 lines): - detectSpecialPattern() - was used by removed decompileGroup() - isVarInitialization() - was used by removed groupConditions() - Updated stale comment referencing removed generateStickyVarDeclarations() Analyzer (9 lines): - serializeCondition() - never called All 29 decompiler tests pass.
Co-authored-by: TelegaOvoshey <[email protected]>
- Add PID controller output examples (pid[0-3].output) - Add flight mode detection examples (flight.mode.*) - Update sticky examples to use variable assignment syntax - Add mode-based VTX control example - Add sticky with variable reuse example
Russian translation
The blackbox tab was using the deprecated fs.writeFileSync() which is not available in the Electron renderer process due to context isolation. Updated to use the secure window.electronAPI.appendFile() method exposed through the preload script. Changes: - Replace fs.writeFileSync() with window.electronAPI.appendFile() - Add proper error handling with GUI feedback - Use Promise-based async flow for file writing This brings the code in line with other tabs (cli.js, logging.js) that already use the electronAPI correctly.
Fixes four bugs that prevented the auto-select target feature from working correctly:
1. Board selection handler using .text() instead of .val() (line 326)
- The releases object is keyed by value (raw_target), not display text
- This caused releases[target] lookups to fail, leading to forEach errors
2. Missing safety check before forEach (line 342)
- Added check to prevent crash when releases[target] is undefined
- Handles cases where board has no available firmware releases
3. Inefficient board selection code (line 864)
- Changed from broken attribute selector to .val() method
- More reliable and cleaner implementation
4. Trigger change only when board found (line 872-873)
- When detected board isn't in list (e.g., unstable release filtered out),
.val() fails silently but change event still triggered with null
- This caused "{-1}" to appear in firmware version dropdown
- Now only triggers change if board was successfully selected
Tested with both stable and unstable release filters enabled/disabled.
Convert JavaScript Programming transpiler from destructuring-based syntax to fully namespaced API: - Update all 22 examples to use inav.flight.*, inav.override.*, etc. - Add support for inav.events.edge() and inav.events.sticky() - Implement dispatch tables for cleaner handler routing - Add namespace normalization across parser, codegen, analyzer - Update default templates and quick reference examples - Maintain backward compatibility with old syntax This improves Monaco editor autocomplete support and provides a cleaner, more discoverable API for users. Changes: - parser.js: Recognize inav.events.* function calls - codegen.js: Event handler dispatch table, operand normalization - decompiler.js: Pattern renderer dispatch table - analyzer.js: Assignment target normalization - action_generator.js: Action target normalization - property_access_checker.js: API validation with dispatch tables - examples/index.js: All examples updated to namespaced syntax - tabs/javascript_programming.*: Default templates updated
Support both rc[N].low/mid/high and inav.rc[N].low/mid/high syntax in condition generator for member expression handling.
New script tests that all examples in examples/index.js compile successfully. Provides quick validation that the transpiler works with all user-facing examples.
Fix variable handler to detect inav.gvar[N] in addition to gvar[N] when identifying explicitly used gvar slots. This ensures var variables avoid collisions with explicitly referenced gvar slots in user code. Fix action decompiler RC channel override output to include inav. prefix (inav.rc[N] = value) for consistency with other decompiled output. Update all test files to use fully namespaced syntax: - inav.flight.* instead of flight.* - inav.gvar[N] instead of gvar[N] - inav.rc[N] instead of rc[N] - inav.override.* instead of override.* - inav.events.edge() instead of edge() - inav.events.sticky() instead of sticky() All 25 test suites now pass.
Complete the namespace refactoring by adding inav. prefix to the remaining operand types in the decompiler's operand-to-string conversion: - gvar[N] → inav.gvar[N] - rc[N] → inav.rc[N] - pid[N].output → inav.pid[N].output This matches the changes already made to action_decompiler.js and ensures all decompiled output uses the fully namespaced syntax consistently.
Add xor, nand, nor, and approxEqual to the helpers.js API definition alongside the existing mapInput and mapOutput functions. Update condition_generator.js and expression_generator.js to: - Extract function names from both simple calls (xor()) and namespaced calls (inav.helpers.xor()) - Validate that namespaced calls use the correct inav.helpers.* namespace - Reject invalid namespaces like inav.pid[0].mapInput() with clear error messages This prevents nonsensical function calls from silently succeeding and ensures all helper functions are properly namespaced for consistency with the rest of the INAV API. Backward compatibility: Global function calls (xor(), mapInput(), etc.) continue to work for existing user code.
Changed extractHelperFunctionName() to return null for invalid namespaces instead of returning an object with invalidNamespace flag. This matches the pattern used in condition_generator.js. Now inav.pid[0].mapInput() correctly produces 'Unknown function call' error instead of the confusing 'Helper function must be called as...' error. The function now: - Returns function name string for valid calls (mapInput() or inav.helpers.mapInput()) - Returns null for invalid namespaces (inav.pid[0].mapInput()) - generateCall() treats null as 'not a helper function' with generic error
Removed extractHelperFunctionName() methods from both condition_generator.js
and expression_generator.js. Inlined the namespace checking directly in
generateCall() for better clarity and efficiency.
Benefits:
- More explicit: only checks namespace when callee.object.property.name === 'helpers'
- More efficient: avoids function call overhead for non-helper namespaces
- Clearer code flow: namespace check is inline with its usage
- Consistent pattern: both generators use the same approach
Pattern:
// Backward compat: funcName()
if (callee.type === 'Identifier') {
funcName = callee.name;
}
// New syntax: inav.helpers.funcName()
else if (callee.object?.property?.name === 'helpers') {
funcName = callee.property?.name;
}
For invalid namespaces like inav.pid[0].mapInput(), funcName remains null
and produces 'Unknown function call' error.
Changed from prefix matching ('gvar[', 'rc[', 'events.', 'helpers.') to
namespace extraction for cleaner, more consistent routing.
New approach:
1. Extract namespace (first word before . or [)
2. Route to namespace-specific handler based on extracted namespace
3. Special handlers only for array-based properties (gvar, rc, pid)
4. Generic handler for all other namespaces (flight, override, helpers, events, waypoint)
Benefits:
- Consistent routing logic across all namespaces
- No special cases for helpers/events vs other API properties
- Easier to understand: if (namespace === 'gvar') vs if (path.startsWith('gvar['))
- All API properties validated the same way through checkApiPropertyAccess()
Before: Used prefix matching with special empty handlers for helpers/events
After: Extract namespace, route consistently to special or generic handler
Added new test suite to verify consistent namespace-based routing: Tests cover: - Helper function calls: inav.helpers.mapInput() vs mapInput() (backward compat) - Invalid namespace rejection: inav.pid[0].mapInput() should fail - Property access validation for all namespaces (flight, override, gvar, rc, pid) - Array index validation (gvar, rc, pid) - Invalid namespace detection Also added run_all_tests.cjs script to execute complete test suite. All 26 test suites pass (25 existing + 1 new with 15 test cases).
Fixes Qodo comment #2 from PR #2490. Previously, flight axis overrides with unprefixed syntax (e.g., override.flightAxis.roll.angle) failed because the regex in action_generator.js matched against the raw target instead of normalized target. This broke backward compatibility. Changes: - action_generator.js: Normalize target before regex matching - property_access_checker.js: Accept both prefixed and unprefixed targets - codegen.js: Normalize target in getOverrideOperation() - Added comprehensive test suite for flight axis overrides All 27 test suites passing.
The main process appendFile() handler throws/rejects on error, not resolves with an error object. The previous code checking `if (err)` in the .then() callback would never catch errors. This fixes the bug by properly using .catch() to handle rejections. Addresses Qodo code review suggestion #1. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
…tenance-9x Fix blackbox save to file functionality
Replace strict truthy check with duck typing that verifies the forEach
method exists and is callable. This is more flexible and future-proof:
- Works with arrays, NodeLists, and any iterable with forEach
- More JavaScript-idiomatic (duck typing over type checking)
- Focuses on behavior ("can iterate?") not type ("is Array?")
- Uses optional chaining (?.) for modern, concise code
Benefits over Array.isArray():
- If data structure changes to Set, NodeList, or custom collection,
code continues to work without modification
- More aligned with JavaScript best practices
- Clearer intent: we care about iteration capability, not array type
…reach Fix auto-select target functionality in firmware flasher
…ns-9-rc3 Add missing ukrainian translations 9 rc
Two fixes for intermittent connection failures:
1. Fix error handler in serial.js to correctly report errors
- The error handler was resolving with {error: false} when there
was an actual error, causing confusing "connection canceled"
messages and preventing proper error handling
2. Reset MSP decoder state before adding receive listeners
- Move FC.resetState() earlier in the connection sequence
- Add MSP.disconnect_cleanup() to reset decoder state
- This ensures garbage bytes or boot messages received during
USB enumeration don't corrupt the MSP decoder state
When serial port errors occurred, the port handle wasn't being properly cleaned up, leaving zombie handles that blocked reconnection attempts. Changes: - Add cleanup in error handler: removeAllListeners() + destroy() - Make connect() async to properly await cleanup of existing ports - Add 100ms delay after destroy() to let OS release file handle - Fix close() race condition: null reference before close callback - Handle case where port exists but isn't open This fixes the "Resource temporarily unavailable Cannot lock port" error that occurred when reconnecting after a connection failure.
…emove-destructuring Refactor JavaScript Programming to use fully namespaced inav.* syntax
…iability Fix serial connection reliability issues
Add error callback to MSP.send_message in processNextCondition() so that if an individual logic condition fetch fails, loading continues with the next condition rather than halting indefinitely. Previously, only a success callback was provided, meaning any MSP error would stop the loading sequence without ever calling the final callback.
…ing-error-handler Fix logic conditions loading to handle MSP errors
The SITL feature was broken because the code looked for binaries in the wrong location. The path used __dirname which points to the Vite build output (.vite/build/), but SITL binaries are in resources/public/sitl/. Changes: - Add getSitlBasePath() function that returns correct path based on whether app is packaged (process.resourcesPath) or in dev mode (app.getAppPath()/resources/public/sitl) - Add extraResource in forge.config.js to include SITL in packages - Add afterCopy hook to remove binaries for other platforms/architectures, reducing package size
Fix SITL binary path resolution for dev and packaged modes
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
PR Type
Other
Description
This description is generated by an AI tool. It may have inaccuracies
Maintenance merge from 9.x branch to master
Updates to SITL (Software In The Loop) binaries for multiple platforms (macOS, Linux ARM64, Linux)
Russian locale translations updated in
messages.jsonGeneral maintenance and synchronization between branches
Diagram Walkthrough
File Walkthrough