# PedestrianNav **Repository Path**: bistu_liuning_admin_admin/PedestrianNav ## Basic Information - **Project Name**: PedestrianNav - **Description**: 行人GNSS/INS组合导航系统 - Android端 - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-02-25 - **Last Updated**: 2026-02-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # PedestrianNav - Android行人组合导航系统 ## 项目概述 PedestrianNav是一个运行在Android手机端的GNSS/INS组合导航程序,用于行人导航。程序采集手机端的陀螺仪、加速度计、地磁和卫星数据,通过扩展卡尔曼滤波器(EKF)实现高精度的组合导航解算,并支持实时曲线绘制和数据存储。 --- ## 功能特性 - **多传感器融合**:IMU(加速度计+陀螺仪+磁力计) + GNSS(GPS) - **15维EKF滤波器**:姿态误差(3) + 速度误差(3) + 位置误差(3) + IMU零偏(6) - **零速修正(ZUPT)**:自动检测行人静止状态并修正误差 - **实时曲线显示**:位置/速度/姿态实时曲线 - **数据本地存储**:CSV格式导出原始数据和解算结果 --- ## 项目结构 ``` PedestrianNav/ ├── app/ │ ├── src/main/ │ │ ├── cpp/ # C++核心导航算法 │ │ │ ├── CMakeLists.txt # CMake构建配置 │ │ │ ├── nav_types.h # 数据类型定义 │ │ │ ├── ins_navigation.h/cpp # INS导航+卡尔曼滤波 │ │ │ └── native_interface.cpp # JNI接口 │ │ │ │ │ ├── java/com/nav/pedestrian/ │ │ │ ├── jni/ # JNI接口层 │ │ │ │ ├── NavigationNative.java │ │ │ │ └── NavigationCallback.java │ │ │ │ │ │ │ ├── sensors/ # 传感器采集 │ │ │ │ ├── SensorCollector.java │ │ │ │ └── NavigationService.java │ │ │ │ │ │ │ ├── data/ # 数据存储 │ │ │ │ ├── NavigationState.java │ │ │ │ └── DataLogger.java │ │ │ │ │ │ │ └── ui/ # UI界面 │ │ │ └── MainActivity.java │ │ │ │ │ ├── res/layout/activity_main.xml # 界面布局 │ │ ├── res/values/ # 资源文件 │ │ └── AndroidManifest.xml # 应用配置 │ │ │ ├── build.gradle # App模块配置 │ └── proguard-rules.pro # 混淆规则 │ ├── ndk/ # NDK r25c (本地) ├── cmake/3.22.1/ # CMake (本地) ├── gradle/wrapper/ # Gradle Wrapper ├── build.gradle # 项目配置 ├── settings.gradle # 项目设置 ├── gradle.properties # Gradle属性 ├── gradlew / gradlew.bat # Gradle Wrapper脚本 ├── build_apk.bat # 编译脚本 └── README.md # 本文档 ``` --- ## 开发环境要求 | 工具 | 版本要求 | 说明 | |------|---------|------| | Android Studio | Flamingo (2022.2.1)+ | 推荐使用最新版 | | Android SDK | API 34 | Android 14 | | Android NDK | r25c (25.2.9519653) | C++编译支持 | | CMake | 3.22.1 | NDK编译工具 | | Gradle | 8.2 | 通过Wrapper自动下载 | | JDK | 17+ | Android Studio自带 | --- ## 编译步骤 ### 方法一:使用Android Studio(推荐) #### 步骤1:安装Android Studio 1. 下载地址:https://developer.android.com/studio 2. 运行安装程序,选择以下组件: - Android SDK - Android NDK - CMake - Android Virtual Device(可选) #### 步骤2:打开项目 ``` 1. 启动 Android Studio 2. 选择 File -> Open 3. 浏览到 PedestrianNav 文件夹并选择 4. 点击 OK ``` #### 步骤3:同步Gradle 首次打开项目会自动提示同步Gradle依赖: ``` 点击 "Sync Now" 按钮 或 File -> Sync Project with Gradle Files ``` 等待Gradle同步完成(首次可能需要几分钟下载依赖)。 #### 步骤4:配置NDK(如需要) 如果提示NDK未找到: ``` 1. File -> Project Structure 2. SDK Location -> NDK Location 3. 点击 Download 下载NDK 4. 选择版本 r25c 或更高 ``` #### 步骤5:编译项目 ``` Build -> Make Project (Ctrl+F9) ``` 编译输出: ``` BUILD SUCCESSFUL in Xs ``` #### 步骤6:生成APK **Debug版本:** ``` Build -> Build Bundle(s) / APK(s) -> Build APK(s) ``` **Release版本(需要签名):** ``` Build -> Generate Signed Bundle / APK -> 选择 APK -> 创建或选择密钥库 -> 选择 release 构建变体 ``` APK输出路径: ``` app/build/outputs/apk/debug/app-debug.apk app/build/outputs/apk/release/app-release.apk ``` --- ### 方法二:命令行编译 #### 前提条件 **Windows:** ```powershell # 设置环境变量(使用Android Studio自带的JDK) $env:JAVA_HOME = "C:\Program Files\Android\Android Studio\jbr" $env:ANDROID_HOME = "C:\Users\用户名\AppData\Local\Android\Sdk" # 验证 java -version ``` **Linux/Mac:** ```bash # 设置环境变量 export JAVA_HOME=/path/to/jdk export ANDROID_HOME=/path/to/android-sdk # 验证 java -version ``` #### 编译命令 **Windows (PowerShell):** ```powershell cd d:\WorkProject\SoftSources_01_20260225\NavigationSources\PedestrianNav # 清理项目 .\gradlew.bat clean # 编译Debug版本 .\gradlew.bat assembleDebug # 编译Release版本 .\gradlew.bat assembleRelease # 运行单元测试 .\gradlew.bat test # 安装到连接的设备 .\gradlew.bat installDebug ``` **Linux/Mac:** ```bash cd /path/to/PedestrianNav # 赋予执行权限 chmod +x gradlew # 编译 ./gradlew assembleDebug ``` --- ## 安装与运行 ### 安装APK **方法一:Android Studio直装** ``` 1. 连接Android手机(开启USB调试) 2. Run -> Run 'app' (Shift+F10) 3. 选择目标设备 ``` **方法二:ADB命令** ```bash adb install -r app/build/outputs/apk/debug/app-debug.apk ``` **方法三:直接安装** ``` 1. 将APK复制到手机 2. 在手机文件管理器中点击安装 ``` ### 运行步骤 1. **授予权限** - 位置权限(必须) - 后台位置权限(推荐) - 通知权限(Android 13+) 2. **开始导航** - 点击"开始导航"按钮 - 等待GPS定位(需在户外环境) - 首次定位后自动初始化 3. **查看数据** - 实时位置/速度/姿态显示 - 曲线图实时更新 4. **保存数据** - 点击"保存数据"按钮 - 数据存储在:`Documents/PedestrianNav/时间戳/` --- ## 算法说明 ### 状态向量(15维) | 索引 | 状态变量 | 维度 | 含义 | 单位 | |-----|---------|------|------|------| | 0-2 | δp | 3 | 位置误差(N,E,D) | m | | 3-5 | δv | 3 | 速度误差(N,E,D) | m/s | | 6-8 | φ | 3 | 姿态误差角 | rad | | 9-11 | ∇ | 3 | 加速度计零偏 | m/s² | | 12-14 | ε | 3 | 陀螺零偏 | rad/s | ### 滤波方程 **时间更新(预测):** ``` x̂(k|k-1) = Φ(k,k-1) · x̂(k-1) P(k|k-1) = Φ(k,k-1) · P(k-1) · Φ^T(k,k-1) + Q(k) ``` **测量更新(校正):** ``` K(k) = P(k|k-1) · H^T · (H · P(k|k-1) · H^T + R)^(-1) x̂(k) = x̂(k|k-1) + K(k) · (z(k) - H · x̂(k|k-1)) P(k) = (I - K(k) · H) · P(k|k-1) ``` ### 观测模型 **GNSS位置/速度观测:** ``` z = [δp_N, δp_E, δp_D, δv_N, δv_E, δv_D]^T H = [0₃ₓ₃ 0₃ₓ₃ I₃ 0₃ₓ₃ 0₃ₓ₃] (位置) [0₃ₓ₃ I₃ 0₃ₓ₃ 0₃ₓ₃ 0₃ₓ₃] (速度) ``` **ZUPT零速观测:** ``` z = [v_N, v_E, v_D]^T (静止时速度应为0) H = [0₃ₓ₃ I₃ 0₃ₓ₉] ``` ### INS更新算法 采用Savage高精度捷联算法: **姿态更新:** ```cpp // 四元数更新 q_new = q_old ⊗ q(ω·dt) ⊗ q(-ω_in·dt) ``` **速度更新:** ```cpp // 比力转换 + 哥氏 + 重力 v_new = v_old + (Cnb·f - (2ωie + ωen)×v + g)·dt ``` **位置更新:** ```cpp // 考虑地球曲率 lat += vn·dt / (Rm + h) lon += ve·dt / ((Rn + h)·cos(lat)) alt -= vd·dt ``` --- ## 输出数据格式 ### CSV文件说明 | 文件名 | 内容 | 字段数 | |-------|------|--------| | `imu.csv` | IMU原始数据 | 7 | | `gnss.csv` | GNSS数据 | 9 | | `nav.csv` | 导航解算结果 | 10 | | `mag.csv` | 磁力计数据 | 4 | | `attitude.csv` | 姿态数据 | 4 | ### 数据示例 **imu.csv:** ```csv timestamp,acc_x,acc_y,acc_z,gyro_x,gyro_y,gyro_z 1708849200.123456,0.12,-0.05,9.81,0.001,-0.002,0.0005 ``` **gnss.csv:** ```csv timestamp,lat,lon,alt,vn,ve,vd,satellites,accuracy 1708849200.5,39.90421400,116.40741300,50.12,0.5,0.3,0.0,12,3.5 ``` **nav.csv:** ```csv timestamp,lat,lon,alt,vn,ve,vd,roll,pitch,yaw 1708849200.6,39.90421500,116.40741400,50.15,0.48,0.32,-0.01,1.23,-0.45,89.5 ``` --- ## 开发过程记录 ### 开发时间线 **2026-02-25** #### 1. 项目创建 (14:30) **创建目录结构:** ``` PedestrianNav/ ├── app/src/main/ │ ├── cpp/ │ ├── java/com/nav/pedestrian/ │ │ ├── jni/ │ │ ├── sensors/ │ │ ├── data/ │ │ └── ui/ │ └── res/ ├── gradle/wrapper/ └── ... ``` **配置文件:** - `settings.gradle` - 项目设置,包含JitPack仓库 - `build.gradle` (项目级) - AGP 8.2.0 - `build.gradle` (App级) - SDK配置、NDK配置、依赖 - `gradle.properties` - JVM参数 - `gradle-wrapper.properties` - Gradle 8.2 #### 2. C++核心算法开发 (14:40) **参考程序分析:** - WanGang_S1: 标准15维SINS算法结构 - bit_flight2: EKF滤波器实现 - psins251010: PSINS工具箱(西北工大严恭敏教授) - GINavPostProcess: 半三角P矩阵存储优化 **创建文件:** | 文件 | 行数 | 功能 | |------|------|------| | `nav_types.h` | 200+ | 基础数据类型定义 | | `ins_navigation.h` | 80+ | 导航类声明 | | `ins_navigation.cpp` | 600+ | 核心算法实现 | | `native_interface.cpp` | 150+ | JNI接口 | **算法实现要点:** - Vec3/Matrix3/Quaternion数学类型 - 15维误差状态向量 - 半三角P矩阵存储(节省47%内存) - GNSS松组合观测更新 - ZUPT零速检测与修正 - 闭环反馈校正 #### 3. Java层开发 (15:00) **创建文件:** | 文件 | 行数 | 功能 | |------|------|------| | `NavigationNative.java` | 40 | Native方法声明 | | `NavigationCallback.java` | 15 | 回调接口 | | `SensorCollector.java` | 200+ | 传感器采集 | | `NavigationService.java` | 250+ | 后台服务 | | `NavigationState.java` | 80+ | 状态数据类 | | `DataLogger.java` | 200+ | CSV日志记录 | | `MainActivity.java` | 400+ | 主界面 | **关键实现:** - SensorEventListener采集IMU数据 - LocationListener采集GNSS数据 - ForegroundService保持后台运行 - Callback机制更新UI - 异步文件写入 #### 4. UI界面开发 (15:20) **布局文件:** - `activity_main.xml` - 主界面布局 **UI组件:** - 控制按钮区(开始/停止/重置/保存) - 状态显示区(IMU/GPS状态) - 位置信息区(经纬高) - 速度信息区(北东地速度) - 姿态信息区(航向俯仰横滚) - 曲线图区(3个LineChart) **图表库:** - MPAndroidChart v3.1.0 - 支持实时数据更新 - 支持缩放拖动 - 平滑曲线(Cubic Bezier) #### 5. 资源文件配置 (15:30) | 文件 | 内容 | |------|------| | `AndroidManifest.xml` | 权限声明、Service注册 | | `strings.xml` | 字符串资源 | | `colors.xml` | 颜色定义 | | `themes.xml` | Material 3主题 | --- ## 编译过程记录 ### 编译环境 | 组件 | 版本 | 来源 | |------|------|------| | JDK | 21.0.4 | Android Studio自带 | | Android SDK | API 34 | 已安装 | | Android NDK | 25.2.9519653 | 本地ndk目录 | | CMake | 3.22.1 | 本地cmake目录 | | Gradle | 8.2 | Wrapper自动下载 | ### 编译步骤 #### 步骤1:环境准备 **1.1 使用Android Studio自带JDK** ``` JAVA_HOME = C:\Program Files\Android\Android Studio\jbr ``` **1.2 解压NDK** ``` 来源:d:\WorkProject\SoftSources_01_20260225\NavigationSources\NDK_Sources\android-ndk-r25c-windows.zip 目标:PedestrianNav\ndk\ 版本:25.2.9519653 ``` **1.3 安装CMake** ``` 来源:https://dl.google.com/android/repository/cmake-3.22.1-windows.zip 目标:PedestrianNav\cmake\3.22.1\ ``` #### 步骤2:配置local.properties ```properties sdk.dir=C:\\Users\\liuni\\AppData\\Local\\Android\\Sdk ndk.dir=D:\\WorkProject\\SoftSources_01_20260225\\NavigationSources\\PedestrianNav\\ndk cmake.dir=D:\\WorkProject\\SoftSources_01_20260225\\NavigationSources\\PedestrianNav\\cmake\\3.22.1 ``` #### 步骤3:执行编译 ```powershell .\build_apk.bat ``` **编译脚本内容:** ```batch @echo off set "JAVA_HOME=C:\Program Files\Android\Android Studio\jbr" set "ANDROID_HOME=%LOCALAPPDATA%\Android\Sdk" set "Path=%JAVA_HOME%\bin;%ANDROID_HOME%\platform-tools;%Path%" call gradlew.bat assembleDebug ``` ### 编译遇到的问题及解决方案 #### 问题1:Gradle文件编码错误 **错误信息:** ``` unexpected char: 0xFFFD ``` **原因:** 文件包含UTF-8 BOM头 **解决方案:** 使用PowerShell脚本重新写入无BOM的UTF-8文件 ```powershell $utf8NoBom = New-Object System.Text.UTF8Encoding $false [System.IO.File]::WriteAllText("settings.gradle", $content, $utf8NoBom) ``` #### 问题2:缺少gradle-wrapper.jar **错误信息:** ``` Error: Could not find or load main class org.gradle.wrapper.GradleWrapperMain ``` **原因:** gradle-wrapper.jar文件缺失 **解决方案:** 从官方下载 ```powershell $url = "https://raw.githubusercontent.com/gradle/gradle/v8.2.0/gradle/wrapper/gradle-wrapper.jar" Invoke-WebRequest -Uri $url -OutFile "gradle\wrapper\gradle-wrapper.jar" ``` #### 问题3:NDK未找到 **错误信息:** ``` No version of NDK matched the requested version 25.1.8937393 ``` **原因:** NDK版本号不匹配 **解决方案:** 1. 检查NDK版本:`cat ndk/source.properties` 2. 实际版本为 `25.2.9519653` 3. 更新 `app/build.gradle` 中的 `ndkVersion` #### 问题4:CMake未安装 **错误信息:** ``` CMake '3.22.1' was not found ``` **原因:** SDK目录中未安装CMake **解决方案:** 下载CMake到项目目录 ```batch powershell -Command "Invoke-WebRequest -Uri 'https://dl.google.com/android/repository/cmake-3.22.1-windows.zip' -OutFile '%TEMP%\cmake.zip'" powershell -Command "Expand-Archive -Path '%TEMP%\cmake.zip' -DestinationPath 'cmake\3.22.1'" ``` #### 问题5:C++代码编译错误 **错误信息:** ```cpp D:/WorkProject/.../ins_navigation.cpp:379:54: error: use of undeclared identifier 'l' double P_kj = (k <= j) ? P(k, j) : P(l, j); ``` **原因:** 半三角矩阵索引代码中的打字错误,`l` 应为 `j` **解决方案:** 修复代码 ```cpp // 修复前 double P_kj = (k <= j) ? P(k, j) : P(l, j); // 修复后 double P_kj = (k <= j) ? P(k, j) : P(j, k); ``` #### 问题6:Java包名使用保留字 **错误信息:** ``` error: expected package com.nav.pedestrian.native; ^ ``` **原因:** `native` 是Java保留关键字,不能用作包名 **解决方案:** 1. 重命名包目录:`native` → `jni` 2. 更新所有Java文件中的package声明和import语句 3. 更新JNI C++函数名:`Java_com_nav_pedestrian_native_*` → `Java_com_nav_pedestrian_jni_*` **影响的文件:** - `NavigationNative.java` - package声明 - `NavigationCallback.java` - package声明 - `SensorCollector.java` - import语句 - `NavigationService.java` - import语句 - `native_interface.cpp` - 所有JNI函数名 #### 问题7:Android 14前台服务权限崩溃 **错误信息:** ``` java.lang.SecurityException: Starting FGS with type location callerApp=ProcessRecord{...} targetSDK=34 requires permissions: all of the permissions allOf=true [android.permission.FOREGROUND_SERVICE_LOCATION] any of the permissions allOf=false [android.permission.ACCESS_COARSE_LOCATION, android.permission.ACCESS_FINE_LOCATION] ``` **原因:** Android 14 (API 34) 对位置类型前台服务要求更严格: 1. 必须在启动前台服务前已获得位置权限 2. 必须使用带类型参数的 `startForeground()` 方法 **解决方案:** **1. NavigationService.java 添加权限检查:** ```java import android.content.pm.ServiceInfo; @Override public int onStartCommand(Intent intent, int flags, int startId) { if (!hasLocationPermission()) { stopSelf(); return START_NOT_STICKY; } startForegroundWithPermission(); return START_STICKY; } private boolean hasLocationPermission() { return ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED; } private void startForegroundWithPermission() { Notification notification = createNotification("行人导航运行中"); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { startForeground(NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION); } else { startForeground(NOTIFICATION_ID, notification); } } ``` **2. MainActivity.java 在绑定服务前检查权限:** ```java @Override protected void onStart() { super.onStart(); if (checkLocationPermission()) { Intent intent = new Intent(this, NavigationService.class); startService(intent); bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE); } } ``` #### 问题8:缺少WAKE_LOCK权限 **错误信息:** ``` java.lang.SecurityException: Neither user 10426 nor current process has android.permission.WAKE_LOCK at android.os.PowerManager$WakeLock.acquire(PowerManager.java:4112) at com.nav.pedestrian.sensors.NavigationService.startNavigation(NavigationService.java:112) ``` **原因:** AndroidManifest.xml中未声明WAKE_LOCK权限 **解决方案:** 在AndroidManifest.xml中添加权限声明: ```xml ``` ### 编译成功输出(第三次编译) ``` BUILD SUCCESSFUL in 14s 36 actionable tasks: 9 executed, 27 up-to-date === Build Complete === APK generated successfully Location: app\build\outputs\apk\debug\app-debug.apk 2026/02/25 17:29 8,044,181 app-debug.apk ``` ### 最终APK信息 | 属性 | 值 | |------|-----| | 文件名 | app-debug.apk | | 大小 | 8,044,181 字节 (7.7 MB) | | 路径 | `app\build\outputs\apk\debug\app-debug.apk` | | 构建类型 | Debug | | 支持架构 | arm64-v8a, armeabi-v7a | | 编译时间 | 2026-02-25 17:29 | --- ## 常见问题 ### Q1: 编译时找不到NDK ``` 解决方案: 1. 打开 SDK Manager 2. SDK Tools -> 勾选 NDK (Side by side) 3. 点击 Apply 下载 ``` ### Q2: CMake编译失败 ``` 解决方案: 1. 确保安装了 CMake 3.22.1 2. SDK Manager -> SDK Tools -> CMake 3. 勾选 "Show Package Details" 选择版本 ``` ### Q3: Gradle同步失败 ``` 解决方案: 1. 检查网络连接 2. 使用国内镜像(阿里云) 3. 清理缓存:gradlew clean 4. 删除 .gradle 文件夹重试 ``` ### Q4: 手机无法获取GPS ``` 解决方案: 1. 确保在户外环境 2. 开启手机定位服务 3. 授予应用位置权限 4. 等待2-3分钟定位 ``` ### Q5: 曲线不显示 ``` 解决方案: 1. 确保已开始导航 2. 等待数据积累 3. 检查 MPAndroidChart 依赖 ``` ### Q6: Java包名使用保留字 ``` 解决方案: 不要使用Java保留关键字作为包名,如:native, class, interface, import等 本项目将 native 改为 jni ``` ### Q7: Gradle文件编码问题 ``` 解决方案: 确保Gradle配置文件使用无BOM的UTF-8编码 可使用PowerShell脚本重新生成: $utf8NoBom = New-Object System.Text.UTF8Encoding $false [System.IO.File]::WriteAllText($path, $content, $utf8NoBom) ``` ### Q8: Android 14前台服务崩溃 ``` 错误:SecurityException: Starting FGS with type location requires permissions 解决方案: 1. 在AndroidManifest.xml中声明FOREGROUND_SERVICE_LOCATION权限(已有) 2. 在Service中启动前台服务前检查位置权限 3. 使用带ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION参数的startForeground() 4. 在Activity中绑定服务前检查权限 ``` ### Q9: WAKE_LOCK权限缺失 ``` 错误:SecurityException: Neither user xxx nor current process has android.permission.WAKE_LOCK 解决方案: 在AndroidManifest.xml中添加: ``` --- ## 参考文档 1. Paul G. Savage, "Strapdown Inertial Navigation Integration Algorithm Design Part 1 & Part 2" 2. 严恭敏, 《惯性导航与组合导航》 3. Groves P.D., "Principles of GNSS, Inertial, and Multisensor Integrated Navigation Systems" 4. PSINS工具箱文档 - 西北工业大学 5. Android Developer Documentation --- ## 许可证 本项目仅供学习和研究使用。 --- ## 更新日志 ### v1.0.0 (2026-02-25) - 初始版本发布 - 支持15维EKF组合导航 - 支持ZUPT零速修正 - 支持实时曲线显示 - 支持CSV数据导出 - 完成首次成功编译 (APK: 7.7MB) ### v1.0.1 (2026-02-25) - 修复Android 14前台服务权限问题 - 添加ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION支持 - 添加WAKE_LOCK权限声明 - 优化服务启动前的权限检查逻辑 --- **文档编写时间:** 2026-02-25 **项目路径:** `d:\WorkProject\SoftSources_01_20260225\NavigationSources\PedestrianNav` **最后编译时间:** 2026-02-25 17:29 **APK文件:** `app\build\outputs\apk\debug\app-debug.apk`