Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@ as `pr-test-builds.yml`** (secrets available even for fork PRs).

#### `pr-branch-suggestion.yml` - Branch Targeting Suggestion
**Triggers:** PRs targeting master branch
**Purpose:** Suggests using maintenance-9.x or maintenance-10.x instead
**Purpose:** Suggests using maintenance-10.x (backward-compatible) or
maintenance-11.x (breaking compatibility) instead

#### `non-code-change.yaml` - Non-Code Change Detection
**Triggers:** Pull requests
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/pr-branch-suggestion.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ jobs:

You've targeted the \`master\` branch with this PR. Please consider if a version branch might be more appropriate:

- **\`maintenance-9.x\`** - If your change is backward-compatible and won't create compatibility issues between INAV firmware and Configurator 9.x versions. This will allow your PR to be included in the next 9.x release.
- **\`maintenance-10.x\`** - If your change is backward-compatible and won't create compatibility issues between INAV firmware and Configurator 10.x versions. This will allow your PR to be included in the next 10.x release.

- **\`maintenance-10.x\`** - If your change introduces compatibility requirements between firmware and configurator that would break 9.x compatibility. This is for PRs which will be included in INAV 10.x
- **\`maintenance-11.x\`** - If your change introduces compatibility requirements between firmware and configurator that would break 10.x compatibility. This is for PRs which will be included in INAV 11.x

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

2. Suggested 11.x changes lack nightly builds 🐞 Bug ☼ Reliability

The updated suggestion directs breaking changes to maintenance-11.x, but the nightly build
workflow has no maintenance-11.x push trigger. Contributors following the new instruction can
therefore merge changes to that branch without the repository’s nightly firmware build running for
it.
Agent Prompt
## Issue description
The branch suggestion introduces `maintenance-11.x` as the destination for breaking changes, but the nightly build workflow does not run on pushes to that branch. This leaves the newly recommended release branch without nightly build coverage.

## Fix Focus Areas
- .github/workflows/pr-branch-suggestion.yml[25-25]
- .github/workflows/nightly-build.yml[5-13]

## Recommended Fix
Add `maintenance-11.x` to the nightly build workflow's branch trigger list, or update the branch suggestion to target only branches that are currently covered by the release validation workflows.

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


If \`master\` is the correct target for this change, no action is needed.
Merging to \`master\` would mean your change never ends up in any release.
Comment thread
sensei-hacker marked this conversation as resolved.

---
*This is an automated suggestion to help route contributions to the appropriate branch.*`;
Expand Down
31 changes: 4 additions & 27 deletions readme.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# INAV - navigation capable flight controller

# INAV Documentation
> For documentation on using INAV, see our new docs site at [inavflight.github.io](https://inavflight.github.io/)

# F411 PSA

> INAV no longer accepts targets based on STM32 F411 MCU.
Expand All @@ -12,40 +15,14 @@

# M7, M6 and older UBLOX GPS units PSA

> INAV 8.0 will mark those GPS as deprecated and INAV 9.0.0 will require UBLOX units with Protocol version 15.00 or newer. This means that you need a GPS unit based on UBLOX M8 or newer.

> If you want to check the protocol version of your unit, it is displayed in INAV's 7.0.0+ status cli command.
> INAV 8.0.0 will warn you if your GPS is too old.
> ```GPS: HW Version: Unknown Proto: 0.00 Baud: 115200 (UBLOX Proto >= 15.0 required)```
> INAV 8.0 marked those GPS as deprecated and INAV 9.0.0 and higher require UBLOX units with Protocol version 15.00 or newer. This means that you need a GPS unit based on UBLOX M8 or newer.


> M8, M9 and M10 GPS are the most common units in use today, are readly available and have similar capabilities.
>Mantaining and testing GPS changes across this many UBLOX versions is a challenge and takes a lot of time. Removing the support for older devices will simplify code.

![INAV](http://static.rcgroups.net/forums/attachments/6/1/0/3/7/6/a9088858-102-inav.png)

# PosHold, Navigation and RTH without compass PSA

Attention all drone pilots and enthusiasts,

Are you ready to take your flights to new heights with INAV 7.1? We've got some important information to share with you.

INAV 7.1 brings an exciting update to navigation capabilities. Now, you can soar through the skies, navigate waypoints, and even return to home without relying on a compass. Yes, you heard that right! But before you launch into the air, there's something crucial to consider.

While INAV 7.1 may not require a compass for basic navigation functions, we strongly advise you to install one for optimal flight performance. Here's why:

🛰️ Better Flight Precision: A compass provides essential data for accurate navigation, ensuring smoother and more precise flight paths.

🌐 Enhanced Reliability: With a compass onboard, your drone can maintain stability even in challenging environments, low speeds and strong wind.

🚀 Minimize Risks: Although INAV 7.1 can get you where you need to go without a compass, flying without one may result in a bumpier ride and increased risk of drift or inaccurate positioning.

Remember, safety and efficiency are paramount when operating drones. By installing a compass, you're not just enhancing your flight experience, but also prioritizing safety for yourself and those around you.

So, before you take off on your next adventure, make sure to equip your drone with a compass. It's the smart choice for smoother flights and better navigation.

Fly safe, fly smart with INAV 7.1 and a compass by your side!

# INAV Community

* [INAV Discord Server](https://discord.gg/peg2hhbYwN)
Expand Down
3 changes: 2 additions & 1 deletion src/main/drivers/accgyro/accgyro_lsm6dxx.c
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,8 @@ static void lsm6dxxConfig(gyroDev_t *gyro)
lsm6dxxWriteRegisterBits(dev, LSM6DXX_REG_CTRL6_C, (lsm6dID == LSM6DSO_CHIP_ID? LSM6DXX_MASK_CTRL6_C:LSM6DSL_MASK_CTRL6_C), (LSM6DXX_VAL_CTRL6_C_XL_HM_MODE | getLsmDlpfBandwidth(gyro)), 1);

// Configure control register 7
lsm6dxxWriteRegisterBits(dev, LSM6DXX_REG_CTRL7_G, LSM6DXX_MASK_CTRL7_G, (LSM6DXX_VAL_CTRL7_G_HP_EN_G | LSM6DXX_VAL_CTRL7_G_HPM_G_16), 1);
// Disable on-chip filter to avoid distorting runtime calibration
lsm6dxxWriteRegisterBits(dev, LSM6DXX_REG_CTRL7_G, LSM6DXX_MASK_CTRL7_G, 0, 1);

// Configure control register 9
// disable I3C interface
Expand Down
8 changes: 4 additions & 4 deletions src/main/flight/imu.c
Original file line number Diff line number Diff line change
Expand Up @@ -742,13 +742,13 @@ static void imuCalculateTurnRateacceleration(fpVector3_t *vEstcentrifugalAccelBF
// second choice is gps
static bool lastGPSHeartbeat;
static pt1Filter_t GPS3DspeedFilter;
static float GPS3DspeedFiltered = 0.0f;
static float GPS3Dspeed = 0.0f;
if (gpsSol.flags.gpsHeartbeat != lastGPSHeartbeat) {
lastGPSHeartbeat = gpsSol.flags.gpsHeartbeat;
float GPS3Dspeed = calc_length_pythagorean_3D(gpsSol.velNED[X], gpsSol.velNED[Y], gpsSol.velNED[Z]);
GPS3DspeedFiltered = pt1FilterApply4(&GPS3DspeedFilter, GPS3Dspeed, IMU_ROTATION_LPF, dT);
GPS3Dspeed = calc_length_pythagorean_3D(gpsSol.velNED[X], gpsSol.velNED[Y], gpsSol.velNED[Z]);
}
currentspeed = GPS3DspeedFiltered;
// Filter every loop: dT is the IMU loop time, not the GPS interval
currentspeed = pt1FilterApply4(&GPS3DspeedFilter, GPS3Dspeed, IMU_ROTATION_LPF, dT);
*acc_ignore_slope_multipiler = 4.0f;
}
else
Expand Down
3 changes: 3 additions & 0 deletions src/main/io/gps.c
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,10 @@ void updateEstimatedGPSFix(void)

void gpsProcessNewDriverData(void)
{
// gpsHeartbeat is toggled on gpsSol only, so the driver copy must not reset it
const bool gpsHeartbeat = gpsSol.flags.gpsHeartbeat;
gpsSol = gpsSolDRV;
gpsSol.flags.gpsHeartbeat = gpsHeartbeat;

#ifdef USE_GPS_FIX_ESTIMATION
processDisableGPSFix();
Expand Down
5 changes: 5 additions & 0 deletions src/test/unit/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ set(MAIN_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../src/main")

# Keep these alphabetically sorted by test name

set_property(SOURCE accgyro_lsm6dxx_unittest.cc PROPERTY depends
"drivers/accgyro/accgyro_lsm6dxx.c")
set_property(SOURCE accgyro_lsm6dxx_unittest.cc PROPERTY definitions USE_IMU_LSM6DXX)

set_property(SOURCE alignsensor_unittest.cc PROPERTY depends
"common/maths.c" "sensors/boardalignment.c")

Expand Down Expand Up @@ -43,6 +47,7 @@ set_property(SOURCE gps_ublox_unittest.cc PROPERTY definitions GPS_UBLOX_UNIT_TE
set_property(SOURCE gps_null_port_unittest.cc PROPERTY depends "io/gps.c")
set_property(SOURCE gps_null_port_unittest.cc PROPERTY definitions GPS_NULL_PORT_UNIT_TEST USE_GPS_PROTO_UBLOX)

set_property(SOURCE gps_heartbeat_unittest.cc PROPERTY depends "io/gps.c")
set_property(SOURCE gimbal_serial_unittest.cc PROPERTY depends "io/gimbal_serial.c" "drivers/gimbal_common.c" "common/maths.c" "drivers/headtracker_common.c")
set_property(SOURCE gimbal_serial_unittest.cc PROPERTY definitions USE_SERIAL_GIMBAL GIMBAL_UNIT_TEST USE_HEADTRACKER)

Expand Down
189 changes: 189 additions & 0 deletions src/test/unit/accgyro_lsm6dxx_unittest.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
/*
* This file is part of INAV.
*
* INAV is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* INAV is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with INAV. If not, see <http://www.gnu.org/licenses/>.
*/

// Regression test for the LSM6DSL/LSM6DSO/LSM6DS3 attitude-drift bug reported on Discord
// (custom STM32F405 + LSM6DSL board, INAV 9.1.0): roll/pitch drifted for ~10-20s after
// boot because lsm6dxxConfig() enabled the chip's on-chip gyro high-pass filter at its
// slowest (16mHz) cutoff, which has a ~10s RC time constant and keeps settling the raw
// gyro output for ~20-30s after every power-on/reset - well past INAV's ~2s startup
// gyro calibration window. This test drives the real, unmodified production entry point
// (lsm6dGyroDetect() -> gyro->initFn() -> lsm6dxxConfig()) against a fake register-map
// "chip" and asserts the byte actually written to CTRL7_G does not enable the on-chip HPF.

#include <cstring>
#include <cstdint>

extern "C" {
#include "platform.h"

#include "common/utils.h"
#include "drivers/time.h"
#include "drivers/resource.h"
#include "drivers/bus.h"
#include "drivers/accgyro/accgyro.h"
#include "drivers/accgyro/accgyro_mpu.h"
#include "drivers/accgyro/accgyro_lsm6dxx.h"
}

#include "gtest/gtest.h"

extern "C" {

bool lsm6dGyroDetect(gyroDev_t *gyro);

// --- Fake "chip": a plain byte-addressed register map, backing busRead()/busWrite() ---
static uint8_t fakeRegs[256];
static busDevice_t fakeBusDevice;
static uint32_t fakeScratchpad[(BUS_SCRATCHPAD_MEMORY_SIZE + 3) / 4];

busDevice_t * busDeviceInit(busType_e bus, devHardwareType_e hw, uint8_t tag, resourceOwner_e owner)
{
UNUSED(bus); UNUSED(hw); UNUSED(tag); UNUSED(owner);
return &fakeBusDevice;
}

busDevice_t * busDeviceOpen(busType_e bus, devHardwareType_e hw, uint8_t tag)
{
UNUSED(bus); UNUSED(hw); UNUSED(tag);
return &fakeBusDevice;
}

void busDeviceDeInit(busDevice_t *dev)
{
UNUSED(dev);
}

void * busDeviceGetScratchpadMemory(const busDevice_t *dev)
{
UNUSED(dev);
return fakeScratchpad;
}

void busSetSpeed(const busDevice_t *dev, busSpeed_e speed)
{
UNUSED(dev); UNUSED(speed);
}

bool busWrite(const busDevice_t *dev, uint8_t reg, uint8_t data)
{
UNUSED(dev);
fakeRegs[reg] = data;
return true;
}

bool busRead(const busDevice_t *dev, uint8_t reg, uint8_t *data)
{
UNUSED(dev);
*data = fakeRegs[reg];
return true;
}

bool busWriteBuf(const busDevice_t *dev, uint8_t reg, const uint8_t *data, uint8_t length)
{
UNUSED(dev);
for (uint8_t i = 0; i < length; i++) {
fakeRegs[reg + i] = data[i];
}
return true;
}

bool busReadBuf(const busDevice_t *dev, uint8_t reg, uint8_t *data, uint8_t length)
{
UNUSED(dev);
for (uint8_t i = 0; i < length; i++) {
data[i] = fakeRegs[reg + i];
}
return true;
}

void delay(timeMs_t ms)
{
UNUSED(ms);
}

void delayMicroseconds(timeUs_t us)
{
UNUSED(us);
}

// Real mpuChooseGyroConfig() only needs to pick a table row for boards sharing the MPU
// family; it's irrelevant to the CTRL7_G behavior under test, so return a fixed, valid
// config regardless of input.
const gyroFilterAndRateConfig_t * mpuChooseGyroConfig(uint8_t desiredLpf, uint16_t desiredRateHz)
{
UNUSED(desiredLpf); UNUSED(desiredRateHz);
static const gyroFilterAndRateConfig_t fakeConfig = { 0, 1000, { 0, 0 } };
return &fakeConfig;
}

bool gyroCheckDataReady(gyroDev_t *gyro)
{
UNUSED(gyro);
return true;
}

} // extern "C"

class LSM6DxxConfigTest : public ::testing::Test {
protected:
void SetUp() override
{
memset(fakeRegs, 0, sizeof(fakeRegs));
memset(&fakeBusDevice, 0, sizeof(fakeBusDevice));
memset(&gyro, 0, sizeof(gyro));
gyro.lpf = GYRO_HARDWARE_LPF_NORMAL;
gyro.requestedSampleIntervalUs = 1000;
}

gyroDev_t gyro;
};

// Drives the real production path for the LSM6DSL chip (the exact chip reported in the
// bug: attitude drift over ~10-20s caused by raw gyro X stepping after calibration closed).
TEST_F(LSM6DxxConfigTest, LSM6DSLDoesNotEnableOnChipGyroHighPassFilter)
{
fakeRegs[LSM6DXX_REG_WHO_AM_I] = 0x6A; // LSM6DSL_CHIP_ID

ASSERT_TRUE(lsm6dGyroDetect(&gyro));
ASSERT_NE(gyro.initFn, nullptr);

gyro.initFn(&gyro); // -> lsm6dxxSpiGyroInit() -> lsm6dxxConfig()

const uint8_t ctrl7g = fakeRegs[LSM6DXX_REG_CTRL7_G];
EXPECT_EQ(ctrl7g & LSM6DXX_MASK_CTRL7_G, 0)
<< "CTRL7_G HPF bits were written as 0x" << std::hex << (int)(ctrl7g & LSM6DXX_MASK_CTRL7_G)
<< " - the on-chip gyro high-pass filter must stay disabled. Its slowest cutoff has a "
<< "~10s RC time constant, so re-enabling it reproduces the reported ~10-20s attitude "
<< "drift as the chip's own filter output keeps settling well past INAV's startup "
<< "gyro calibration window.";
EXPECT_EQ(ctrl7g & LSM6DXX_VAL_CTRL7_G_HP_EN_G, 0) << "on-chip gyro HPF enable bit must not be set";
}

// Same assertion for LSM6DSO, which shares lsm6dxxConfig()'s legacy (non-"Gen V") path.
TEST_F(LSM6DxxConfigTest, LSM6DSODoesNotEnableOnChipGyroHighPassFilter)
{
fakeRegs[LSM6DXX_REG_WHO_AM_I] = 0x6C; // LSM6DSO_CHIP_ID

ASSERT_TRUE(lsm6dGyroDetect(&gyro));
ASSERT_NE(gyro.initFn, nullptr);

gyro.initFn(&gyro);

const uint8_t ctrl7g = fakeRegs[LSM6DXX_REG_CTRL7_G];
EXPECT_EQ(ctrl7g & LSM6DXX_MASK_CTRL7_G, 0);
EXPECT_EQ(ctrl7g & LSM6DXX_VAL_CTRL7_G_HP_EN_G, 0);
}
Loading
Loading