【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

相关文章

pycharm远程连接服务器运行pytorch的过程详解

《pycharm远程连接服务器运行pytorch的过程详解》:本文主要介绍在Linux环境下使用Anaconda管理不同版本的Python环境,并通过PyCharm远程连接服务器来运行PyTorc... 目录linux部署pytorch背景介绍Anaconda安装Linux安装pytorch虚拟环境安装cu

一文详解如何在Python中使用Requests库

《一文详解如何在Python中使用Requests库》:本文主要介绍如何在Python中使用Requests库的相关资料,Requests库是Python中常用的第三方库,用于简化HTTP请求的发... 目录前言1. 安装Requests库2. 发起GET请求3. 发送带有查询参数的GET请求4. 发起PO

Python进行PDF文件拆分的示例详解

《Python进行PDF文件拆分的示例详解》在日常生活中,我们常常会遇到大型的PDF文件,难以发送,将PDF拆分成多个小文件是一个实用的解决方案,下面我们就来看看如何使用Python实现PDF文件拆分... 目录使用工具将PDF按页数拆分将PDF的每一页拆分为单独的文件将PDF按指定页数拆分根据页码范围拆分

Java中的Cursor使用详解

《Java中的Cursor使用详解》本文介绍了Java中的Cursor接口及其在大数据集处理中的优势,包括逐行读取、分页处理、流控制、动态改变查询、并发控制和减少网络流量等,感兴趣的朋友一起看看吧... 最近看代码,有一段代码涉及到Cursor,感觉写法挺有意思的。注意是Cursor,而不是Consumer

linux打包解压命令方式

《linux打包解压命令方式》文章介绍了Linux系统中常用的打包和解压命令,包括tar和zip,使用tar命令可以创建和解压tar格式的归档文件,使用zip命令可以创建和解压zip格式的压缩文件,每... 目录Lijavascriptnux 打包和解压命令打包命令解压命令总结linux 打包和解压命令打

SpringBoot项目注入 traceId 追踪整个请求的日志链路(过程详解)

《SpringBoot项目注入traceId追踪整个请求的日志链路(过程详解)》本文介绍了如何在单体SpringBoot项目中通过手动实现过滤器或拦截器来注入traceId,以追踪整个请求的日志链... SpringBoot项目注入 traceId 来追踪整个请求的日志链路,有了 traceId, 我们在排

Python中常用的四种取整方式分享

《Python中常用的四种取整方式分享》在数据处理和数值计算中,取整操作是非常常见的需求,Python提供了多种取整方式,本文为大家整理了四种常用的方法,希望对大家有所帮助... 目录引言向零取整(Truncate)向下取整(Floor)向上取整(Ceil)四舍五入(Round)四种取整方式的对比综合示例应

HTML5中下拉框<select>标签的属性和样式详解

《HTML5中下拉框<select>标签的属性和样式详解》在HTML5中,下拉框(select标签)作为表单的重要组成部分,为用户提供了一个从预定义选项中选择值的方式,本文将深入探讨select标签的... 在html5中,下拉框(<select>标签)作为表单的重要组成部分,为用户提供了一个从预定义选项中

Rust格式化输出方式总结

《Rust格式化输出方式总结》Rust提供了强大的格式化输出功能,通过std::fmt模块和相关的宏来实现,主要的输出宏包括println!和format!,它们支持多种格式化占位符,如{}、{:?}... 目录Rust格式化输出方式基本的格式化输出格式化占位符Format 特性总结Rust格式化输出方式

Python中多线程和多进程的基本用法详解

《Python中多线程和多进程的基本用法详解》这篇文章介绍了Python中多线程和多进程的相关知识,包括并发编程的优势,多线程和多进程的概念、适用场景、示例代码,线程池和进程池的使用,以及如何选择合适... 目录引言一、并发编程的主要优势二、python的多线程(Threading)1. 什么是多线程?2.