【IOS】惯性导航详解(包含角度、加速度、修正方式的api分析)

2024-01-08 11:28

本文主要是介绍【IOS】惯性导航详解(包含角度、加速度、修正方式的api分析),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

参考文献

iPhone的惯性导航,基于步态。https://www.docin.com/p-811792664.html
Inertial Odometry on Handheld Smartphones: https://arxiv.org/pdf/1703.00154.pdf
惯性导航项目相关代码:https://github.com/topics/inertial-navigation-systems
useracceleration苹果官方文档:https://developer.apple.com/documentation/coremotion/cmdevicemotion/1616149-useracceleration
手机导航https://ieeexplore.ieee.org/document/6139701

give me example that use iOS api to get accelarate in xyz.
I use it in swift. print the acceleration of x y z.
make the data collection part in a class. and show it in CintentView using the data in class.

using a filter in the acceleration data

时间间隔获取

在iOS中进行积分时,您可以选择使用motionManager.accelerometerUpdateInterval(motion.timestamp - lastLocation.timestamp)作为时间间隔。

motionManager.accelerometerUpdateInterval:

motionManager.accelerometerUpdateInterval是CMMotionManager类的属性,表示加速度计更新的时间间隔。
这个值是由您设置的,通常用于控制加速度计数据的采样率。
如果您使用加速度计数据进行积分,可以使用这个时间间隔来估计每个采样点的时间间隔。
例如,如果您的加速度计更新间隔为0.01秒,您可以将其作为每个采样点之间的时间间隔。
这种方法适用于简单的运动情况,但可能受到加速度计的噪声和误差的影响。

(motion.timestamp - lastLocation.timestamp):

motion.timestamp是CMDeviceMotion对象的属性,表示获取数据的时间戳。
lastLocation.timestamp是上一个位置更新的时间戳,如果您使用位置数据进行积分,可以使用这个时间戳来计算时间间隔。
这种方法适用于使用位置数据进行积分的情况,例如计算行进距离。
请注意,这种方法要求您同时获取位置数据,并且需要在每个位置更新时记录时间戳

加速度获取

class MileMeter {let motionManager = CMMotionManager()var referenceAttitude: CMAttitude?func startMotionUpdates() {// 检查设备是否支持加速度计和陀螺仪guard motionManager.isAccelerometerAvailable, motionManager.isGyroAvailable else {print("设备不支持加速度计或陀螺仪")return}// 设置更新频率motionManager.accelerometerUpdateInterval = 1.0 / 100.0 // 启动加速度计和陀螺仪更新motionManager.startAccelerometerUpdates()motionManager.startGyroUpdates()// 获取初始参考姿态if let referenceAttitude = motionManager.deviceMotion?.attitude {self.referenceAttitude = referenceAttitude}// 处理加速度计数据motionManager.startDeviceMotionUpdates(to: .main) { (motionData, error) inguard let motionData = motionData else {print("无法获取加速度计数据: \(error?.localizedDescription ?? "")")return}// 获取用户加速度,而不是混合// 校准加速度计数据
//            if let referenceAttitude = self.referenceAttitude {
//                motionData.acceleration = motionData.acceleration.applying(referenceAttitude.rotationMatrix)
//            }// 进行距离估计let acceleration = motionData.userAcceleration   //用户对设备施加的加速度,而不包括重力的影响// 在此处可以使用估计的速度和位移数据进行进一步的处理print("加速度: \(acceleration)")}}func stopMotionUpdates() {motionManager.stopAccelerometerUpdates()motionManager.stopGyroUpdates()motionManager.stopDeviceMotionUpdates()}
}
在这里插入代码片

角度获取

陀螺仪有两种:var attitude: CMAttitude { get }和var rotationRate: CMRotationRate { get } :

CMAttitude:绝对角度

CMAttitude represents the device’s orientation or attitude in space.
It provides information about the device’s pitch, roll, and yaw angles.
The attitude is expressed as a quaternion, which is a mathematical representation of orientation.
You can access the attitude using the attitude property of a CMMotionManager object.
Example usage: let attitude = motionManager.deviceMotion?.attitude

CMRotationRate:旋转角度

CMRotationRate represents the device’s rotation rate or angular velocity.
It provides information about the device’s rotation speed around each axis (x, y, and z).
The rotation rate is expressed in radians per second.
You can access the rotation rate using the rotationRate property of a CMMotionManager object.
Example usage: let rotationRate = motionManager.deviceMotion?.rotationRate

校准

坐标系变换

            // 校准加速度计数据
//            if let referenceAttitude = self.referenceAttitude {
//                motionData.acceleration = motionData.acceleration.applying(referenceAttitude.rotationMatrix)
//            }

滤波器

func lowPassFilter(_ x: Double) -> Double {if abs(x) < 0.01 {return 0} else {return x}
}

最终代码

class DistanceCalculator {private let motionManager = CMMotionManager()@Published var totalDistance: Double = 0.0@Published var lastLocation: CMDeviceMotion?@Published var ax: Double = 0.0 // 距离@Published var ay: Double = 0.0@Published var az: Double = 0.0@Published var acc_ax: Double = 0.0 // 加速度@Published var acc_ay: Double = 0.0@Published var acc_az: Double = 0.0@Published var m_acc_ax: Double = 0.0 // 修正后的加速度@Published var m_acc_ay: Double = 0.0@Published var m_acc_az: Double = 0.0@Published var m_dis_ax: Double = 0.0 // 修正后的路程@Published var m_dis_ay: Double = 0.0@Published var m_dis_az: Double = 0.0@Published var m_totalDistance: Double = 0.0init() {// 检查设备是否支持运动数据的获取guard motionManager.isDeviceMotionAvailable else {print("设备不支持运动数据")return}// 设置更新间隔 官方推荐100hz以上motionManager.deviceMotionUpdateInterval = 0.01// 开始获取设备运动数据motionManager.startDeviceMotionUpdates(to: .main) { [weak self] (motion, error) inguard let motion = motion else {return}if let lastLocation = self?.lastLocation {self?.acc_ax = motion.userAcceleration.xself?.acc_ay = motion.userAcceleration.yself?.acc_az = motion.userAcceleration.zlet velocity_x = motion.userAcceleration.x * (motion.timestamp - lastLocation.timestamp)let velocity_y = motion.userAcceleration.y * (motion.timestamp - lastLocation.timestamp)let velocity_z = motion.userAcceleration.z * (motion.timestamp - lastLocation.timestamp)self?.ax = velocity_xself?.ay += velocity_yself?.az += velocity_z// sqrt 有问题?变成nanself?.totalDistance += abs(velocity_x*velocity_x)
//                self?.totalDistance += sqrt(velocity_x*velocity_x + velocity_y+velocity_y + velocity_z*velocity_z)print("欧式距离里程:\(self?.totalDistance ?? 0)") //如果可选类型的值为nil,空合运算符会返回它的右侧的默认值(在这里是0)print("加速度:\(motion.userAcceleration)")// 使用低通滤波器let _m_acc_x = lowPassFilter(motion.userAcceleration.x)self?.m_acc_ax = _m_acc_xlet _m_acc_y = lowPassFilter(motion.userAcceleration.y)self?.m_acc_ay = _m_acc_ylet _m_acc_z = lowPassFilter(motion.userAcceleration.z)self?.m_acc_az = _m_acc_zlet m_velocity_x = _m_acc_x * (motion.timestamp - lastLocation.timestamp)let m_velocity_y = _m_acc_y * (motion.timestamp - lastLocation.timestamp)let m_velocity_z = _m_acc_z * (motion.timestamp - lastLocation.timestamp)self?.m_dis_ax = m_velocity_xself?.m_dis_ay += m_velocity_yself?.m_dis_az += m_velocity_zself?.m_totalDistance += abs(m_velocity_x)}self?.lastLocation = motion}}
}

这篇关于【IOS】惯性导航详解(包含角度、加速度、修正方式的api分析)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/583301

相关文章

golang程序打包成脚本部署到Linux系统方式

《golang程序打包成脚本部署到Linux系统方式》Golang程序通过本地编译(设置GOOS为linux生成无后缀二进制文件),上传至Linux服务器后赋权执行,使用nohup命令实现后台运行,完... 目录本地编译golang程序上传Golang二进制文件到linux服务器总结本地编译Golang程序

Linux下删除乱码文件和目录的实现方式

《Linux下删除乱码文件和目录的实现方式》:本文主要介绍Linux下删除乱码文件和目录的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux下删除乱码文件和目录方法1方法2总结Linux下删除乱码文件和目录方法1使用ls -i命令找到文件或目录

MySQL中的LENGTH()函数用法详解与实例分析

《MySQL中的LENGTH()函数用法详解与实例分析》MySQLLENGTH()函数用于计算字符串的字节长度,区别于CHAR_LENGTH()的字符长度,适用于多字节字符集(如UTF-8)的数据验证... 目录1. LENGTH()函数的基本语法2. LENGTH()函数的返回值2.1 示例1:计算字符串

Spring Boot spring-boot-maven-plugin 参数配置详解(最新推荐)

《SpringBootspring-boot-maven-plugin参数配置详解(最新推荐)》文章介绍了SpringBootMaven插件的5个核心目标(repackage、run、start... 目录一 spring-boot-maven-plugin 插件的5个Goals二 应用场景1 重新打包应用

mybatis执行insert返回id实现详解

《mybatis执行insert返回id实现详解》MyBatis插入操作默认返回受影响行数,需通过useGeneratedKeys+keyProperty或selectKey获取主键ID,确保主键为自... 目录 两种方式获取自增 ID:1. ​​useGeneratedKeys+keyProperty(推

Python通用唯一标识符模块uuid使用案例详解

《Python通用唯一标识符模块uuid使用案例详解》Pythonuuid模块用于生成128位全局唯一标识符,支持UUID1-5版本,适用于分布式系统、数据库主键等场景,需注意隐私、碰撞概率及存储优... 目录简介核心功能1. UUID版本2. UUID属性3. 命名空间使用场景1. 生成唯一标识符2. 数

Linux在线解压jar包的实现方式

《Linux在线解压jar包的实现方式》:本文主要介绍Linux在线解压jar包的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux在线解压jar包解压 jar包的步骤总结Linux在线解压jar包在 Centos 中解压 jar 包可以使用 u

Linux系统性能检测命令详解

《Linux系统性能检测命令详解》本文介绍了Linux系统常用的监控命令(如top、vmstat、iostat、htop等)及其参数功能,涵盖进程状态、内存使用、磁盘I/O、系统负载等多维度资源监控,... 目录toppsuptimevmstatIOStatiotopslabtophtopdstatnmon

Android kotlin中 Channel 和 Flow 的区别和选择使用场景分析

《Androidkotlin中Channel和Flow的区别和选择使用场景分析》Kotlin协程中,Flow是冷数据流,按需触发,适合响应式数据处理;Channel是热数据流,持续发送,支持... 目录一、基本概念界定FlowChannel二、核心特性对比数据生产触发条件生产与消费的关系背压处理机制生命周期

java使用protobuf-maven-plugin的插件编译proto文件详解

《java使用protobuf-maven-plugin的插件编译proto文件详解》:本文主要介绍java使用protobuf-maven-plugin的插件编译proto文件,具有很好的参考价... 目录protobuf文件作为数据传输和存储的协议主要介绍在Java使用maven编译proto文件的插件