当前位置: 首页 > news >正文

ICM20948 DMP代码详解(13)

接前一篇文章:ICM20948 DMP代码详解(12)

上一回完成了对inv_icm20948_set_chip_to_body_axis_quaternion函数第2步即inv_rotation_to_quaternion函数的解析。回到inv_icm20948_set_chip_to_body_axis_quaternion中来,继续往下进行解析。为了便于理解和回顾,再次贴出该函数源码:

void inv_icm20948_set_chip_to_body_axis_quaternion(struct inv_icm20948 *s, signed char *accel_gyro_matrix, float angle)
{int i;float rot[9];long qcb[4];long q_all[4];long q_adjust[4];for (i=0; i<9; i++)rot[i] = (float)accel_gyro_matrix[i];//convert Chip to Body transformation matrix to quaternion//inv_icm20948_convert_matrix_to_quat_fxp(rot, qcb);inv_rotation_to_quaternion(rot, qcb);//The quaterion generated is the inverse, take the inverse again.qcb[1] = -qcb[1];qcb[2] = -qcb[2];qcb[3] = -qcb[3];//now rotate by angle, negate angle to rotate other wayq_adjust[0] = (long)((1L<<30) * cosf(-angle*(float)M_PI/180.f/2.f));q_adjust[1] = 0;q_adjust[2] = (long)((1L<<30) * sinf(-angle*(float)M_PI/180.f/2.f));q_adjust[3] = 0;invn_convert_quat_mult_fxp(q_adjust, qcb, q_all);inv_icm20948_set_chip_to_body(s, q_all);
}

接下来是第3段代码:

    //The quaterion generated is the inverse, take the inverse again.qcb[1] = -qcb[1];qcb[2] = -qcb[2];qcb[3] = -qcb[3];

在第2步中由旋转矩阵(数组rot[9])得到了四元数,在这里还需要进一步对于qcb[1]~qcb[3]做乘以-1操作。

接下来是第4段代码:

    //now rotate by angle, negate angle to rotate other wayq_adjust[0] = (long)((1L<<30) * cosf(-angle*(float)M_PI/180.f/2.f));q_adjust[1] = 0;q_adjust[2] = (long)((1L<<30) * sinf(-angle*(float)M_PI/180.f/2.f));q_adjust[3] = 0;invn_convert_quat_mult_fxp(q_adjust, qcb, q_all);inv_icm20948_set_chip_to_body(s, q_all);

代码中的angle来自inv_icm20948_set_chip_to_body_axis_quaternion函数的第3个参数float angle,其对应的实参在inv_icm20948_init_matrix函数中传入,为0.0。

由于这里传入的值为0.0,因此以上代码片段

    //now rotate by angle, negate angle to rotate other wayq_adjust[0] = (long)((1L<<30) * cosf(-angle*(float)M_PI/180.f/2.f));q_adjust[1] = 0;q_adjust[2] = (long)((1L<<30) * sinf(-angle*(float)M_PI/180.f/2.f));q_adjust[3] = 0;

实际上是:

    //now rotate by angle, negate angle to rotate other wayq_adjust[0] = (long)((1L<<30);q_adjust[1] = 0;q_adjust[2] = 0;q_adjust[3] = 0;

接下来是invn_convert_quat_mult_fxp函数。

    invn_convert_quat_mult_fxp(q_adjust, qcb, q_all);

其在EMD-Core\sources\Invn\Devices\Drivers\ICM20948\Icm20948DataConverter.c中,代码如下:

static void invn_convert_quat_mult_fxp(const long *quat1_q30, const long *quat2_q30, long *quatProd_q30)
{quatProd_q30[0] = inv_icm20948_convert_mult_q30_fxp(quat1_q30[0], quat2_q30[0]) - inv_icm20948_convert_mult_q30_fxp(quat1_q30[1], quat2_q30[1]) -inv_icm20948_convert_mult_q30_fxp(quat1_q30[2], quat2_q30[2]) - inv_icm20948_convert_mult_q30_fxp(quat1_q30[3], quat2_q30[3]);quatProd_q30[1] = inv_icm20948_convert_mult_q30_fxp(quat1_q30[0], quat2_q30[1]) + inv_icm20948_convert_mult_q30_fxp(quat1_q30[1], quat2_q30[0]) +inv_icm20948_convert_mult_q30_fxp(quat1_q30[2], quat2_q30[3]) - inv_icm20948_convert_mult_q30_fxp(quat1_q30[3], quat2_q30[2]);quatProd_q30[2] = inv_icm20948_convert_mult_q30_fxp(quat1_q30[0], quat2_q30[2]) - inv_icm20948_convert_mult_q30_fxp(quat1_q30[1], quat2_q30[3]) +inv_icm20948_convert_mult_q30_fxp(quat1_q30[2], quat2_q30[0]) + inv_icm20948_convert_mult_q30_fxp(quat1_q30[3], quat2_q30[1]);quatProd_q30[3] = inv_icm20948_convert_mult_q30_fxp(quat1_q30[0], quat2_q30[3]) + inv_icm20948_convert_mult_q30_fxp(quat1_q30[1], quat2_q30[2]) -inv_icm20948_convert_mult_q30_fxp(quat1_q30[2], quat2_q30[1]) + inv_icm20948_convert_mult_q30_fxp(quat1_q30[3], quat2_q30[0]);
}

这个函数中最主要就是调用了inv_icm20948_convert_mult_q30_fxp函数进行计算。inv_icm20948_convert_mult_q30_fxp函数在同文件中,代码如下:

long inv_icm20948_convert_mult_q30_fxp(long a_q30, long b_q30)
{long long temp;long result;temp = (long long)a_q30 * b_q30;result = (long)(temp >> 30);return result;
}

其实就是简单的乘法,之后再右移30位。

那么invn_convert_quat_mult_fxp函数的作用实际上就是计算两个四元数相乘的结果。

参考:四元数乘法计算-CSDN博客

回到inv_icm20948_set_chip_to_body_axis_quaternion函数中,接下来是inv_icm20948_set_chip_to_body函数。

    invn_convert_quat_mult_fxp(q_adjust, qcb, q_all);inv_icm20948_set_chip_to_body(s, q_all);

其也在EMD-Core\sources\Invn\Devices\Drivers\ICM20948\Icm20948DataConverter.c中,代码如下:

/** Set the transformation used for chip to body frame
*/
void inv_icm20948_set_chip_to_body(struct inv_icm20948 * s, long *quat)
{memcpy(s->s_quat_chip_to_body, quat, sizeof(s->s_quat_chip_to_body));
}

这个函数很简单、也很好理解,就是把上一步计算好的q_all[4],赋给s->s_quat_chip_to_body。s_quat_chip_to_body是struct inv_icm20948的成员,相关定义如下:

typedef struct inv_icm20948 {struct inv_icm20948_serif serif;……/* data converter */long s_quat_chip_to_body[4];……
} inv_icm20948_t;

s->s_quat_chip_to_body在前文书解析inv_icm20948_init_matrix函数的时候讲到过,相关代码如下:

和上边的q_adjust数组类似。

    //now rotate by angle, negate angle to rotate other wayq_adjust[0] = (long)((1L<<30);q_adjust[1] = 0;q_adjust[2] = 0;q_adjust[3] = 0;

至此,inv_icm20948_set_chip_to_body_axis_quaternion函数就解析完了。inv_icm20948_init_matrix函数也就解析完了。

回到icm20948_sensor_setup函数中,当前完成了第2段代码的解析,

	/* Setup accel and gyro mounting matrix and associated angle for current board */inv_icm20948_init_matrix(&icm_device);

对于接下来步骤的解析请看下回。

相关文章:

ICM20948 DMP代码详解(13)

接前一篇文章&#xff1a;ICM20948 DMP代码详解&#xff08;12&#xff09; 上一回完成了对inv_icm20948_set_chip_to_body_axis_quaternion函数第2步即inv_rotation_to_quaternion函数的解析。回到inv_icm20948_set_chip_to_body_axis_quaternion中来&#xff0c;继续往下进行…...

【论软件需求获取方法及其应用】

摘要 2023 年 3 月&#xff0c;我所在的公司承接了某油企智慧加油站平台的建设工作。该项目旨在帮助加油站提升运营效率、降低运营成本和提高销售额。我在该项目中担任系统架构设计师&#xff0c;负责整个项目的架构设计工作。 本文以该项目为例&#xff0c;详细论述软件需求获…...

使用ESP8266和OLED屏幕实现一个小型电脑性能监控

前言 最近大扫除&#xff0c;发现自己还有几个ESP8266MCU和一个0.96寸的oled小屏幕。又想起最近一直想要买一个屏幕作为性能监控&#xff0c;随机开始自己diy。 硬件&#xff1a; ESP8266 MUColed小屏幕杜邦线可以传输数据的数据线 环境 Windows系统Qt6Arduino Arduino 库…...

Nexpose v6.6.266 for Linux Windows - 漏洞扫描

Nexpose v6.6.266 for Linux & Windows - 漏洞扫描 Rapid7 Vulnerability Management, release Aug 21, 2024 请访问原文链接&#xff1a;https://sysin.org/blog/nexpose-6/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.o…...

ess6新特性

1、let、const 块级作用域声明变量和常量 2、箭头函数 不能构建函数 不能new 没.prototype属性 没有this指向 this指向是根据上下文的 往上层查找 没有arguments(参数) 3、模板字符串 ${} 字符串中嵌入表达式 4、解构赋值 5、Promise 处理异步操作的标准机制 6、for of 遍历…...

C语言蓝桥杯:语言基础

竞赛常用库函数 最值查询 min_element和max_element在vector(迭代器的使用) nth_element函数的使用 例题lanqiao OJ 497成绩分析 第一种用min_element和max_element函数的写法 第二种用min和max的写法 二分查找 二分查找只能对数组操作 binary_search函数&#xff0c;用于查找…...

axure之变量

一、设置我们的第一个变量 1、点击axure上方设置一个全局变量a 3 2、加入按钮、文本框元件点击按钮文档框展示变量值。 交互选择【单击时】【设置文本】再点击函数。 点击插入变量和函数直接选择刚刚定义的全局变量&#xff0c;也可以直接手动写入函数(注意写入格式。) 这…...

vue缓存用法

Store 临时缓存 特点&#xff1a;需要定义&#xff0c;有初始值、响应式、全局使用、刷新重置 Pinia官方文档 https://pinia.vuejs.org 创建 store 缓存 示例代码 import {defineStore} from pinia import {store} from //storeexport const useMyStore defineStore({// 定义…...

栈入门,括号匹配问题

利用栈这道题应该很轻松可以解决&#xff0c;下面给出常用的代码&#xff1a; public static boolean isValid(String s) {// 创建一个栈来保存左括号Stack<Character> stack new Stack<>();// 遍历字符串中的每个字符for (char c : s.toCharArray()) {// 如果是…...

Vue入门学习笔记-表单

可以使用v-model 指令在表单控件元素上创建双向数据绑定。 引言&#xff1a; Vue采用了MVVM&#xff08;Model-View-ViewModel&#xff09;架构模式&#xff0c;通过指令可以快速实现数据和视图的双向绑定 修改视图层时&#xff0c;模型层也会改变&#xff1b;修改模型层&#…...

TCP通信三次握手、四次挥手

目录 前言 一、三次握手 TCP三次握手的详细过程 二、四次挥手 四次挥手的详细过程 前言 前面我说到了&#xff0c;UDP通信的实现&#xff0c;但我们经常说UDP通信不可靠&#xff0c;是因为他只会接收和发送&#xff0c;并不会去验证对方收到没有&#xff0c;那么我们说TCP通…...

【实施文档】软件项目实施方案(Doc原件2024实际项目)

软件实施方案 二、 项目介绍 三、 项目实施 四、 项目实施计划 五、 人员培训 六、 项目验收 七、 售后服务 八、 项目保障措施软件开发管理全套资料包清单&#xff1a; 工作安排任务书&#xff0c;可行性分析报告&#xff0c;立项申请审批表&#xff0c;产品需求规格说明书&am…...

BeanFactory vs. ApplicationContext

在Spring框架中&#xff0c;BeanFactory和ApplicationContext都是用于管理Spring容器中的bean的接口&#xff0c;但它们在功能和应用场景上有所不同。下面是它们的主要区别&#xff1a; 1. 基础功能 vs. 扩展功能 BeanFactory: 是Spring框架的最基础的IoC容器&#xff0c;提供…...

JDBC客户端连接Starrocks 2.5

<?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.0 http://ma…...

004——双向链表和循环链表

目录 双向链表 双向链表的初始化&#xff08;与单链表类似&#xff09; 增&#xff1a; Ⅰ&#xff09;头插法 Ⅱ&#xff09;尾插法 Ⅲ&#xff09;中间插入 删 改 查 整体代码示例&#xff1a; 循环链表 循环单链表 ​编辑 循环双链表 双向链表 不同于单链表&…...

framebuffer帧缓存

framebuffer:帧缓冲&#xff0c;帧缓存 Linux内核为显示提供的一套应用程序接口。&#xff08;驱动内核支持&#xff09; framebuffer本质上是一块显示缓存&#xff0c;往显示缓存中写入特定格式的数据就意味着向屏幕输出内容。framebuffer驱动程序控制LCD显示设备&#xff0…...

24_竞赛中的高效并查集

菜鸟&#xff1a;老鸟&#xff0c;我最近在做一个与社交网络相关的项目&#xff0c;需要频繁地检查两个用户是否属于同一个群组。但我发现每次检查都很耗时&#xff0c;性能很差。你有什么建议吗&#xff1f; 老鸟&#xff1a;你可以试试使用并查集&#xff08;Union-Find&…...

新手c语言讲解及题目分享(十七)--运算符与表达式专项练习

本文主要讲解c语言的基础部分&#xff0c;运算符与表达式的学习&#xff0c;在这一部分中&#xff0c;往往有许多细节的东西需要去记住。当各种运算符一起用时&#xff0c;就会存在优先级的关系&#xff0c;本文末尾有各种运算符的优先级顺序表。 参考书目和推荐学习书目&#…...

香帅的金融学讲义:深入剖析与解读

香帅的金融学讲义&#xff1a;深入剖析与解读 金融学&#xff0c;这个看似高深复杂的学科&#xff0c;实则与我们的生活息息相关。从个人理财到国家宏观经济政策&#xff0c;金融学无处不在。那么&#xff0c;如何更好地理解金融学呢&#xff1f;今天&#xff0c;我们就来借助…...

java基础-IO(6)转换流InputStreamReader、OutputStreamWriter

引入&#xff1a; 从第一节可知&#xff0c;流分为两类&#xff1a;字节流和字符流&#xff0c;转换流就是在两者之间进行转换。 字节流转换为字符流&#xff1b; 字符流转换为字节流。 字符集 字符集&#xff1a;定义了可用字符及其对应的数字编码的集合。常见的字符集有UT…...

使用Azure Devops Pipeline将Docker应用部署到你的Raspberry Pi上

文章目录 1. 添加树莓派到 Agent Pool1.1 添加pool1.2 添加agent 2. 将树莓派添加到 Deployment Pool2.1 添加pool2.2 添加target 3. 添加编译流水线3.1 添加编译命令3.2 配置触发器 4. 添加发布流水线4.1 添加命令行4.2 配置artifact和触发器 5. 完成 1. 添加树莓派到 Agent P…...

91、K8s之ingress上集

一、Ingress service模式&#xff1a; loadbalance NodePort&#xff1a;每个节点都会有一个指定的端口 30000-32767 内网 clusterip&#xff1a;默认模式&#xff0c;只能pod内部访问 externalName&#xff1a;需要dns提供域名 1.1、对外提供服务的ingress service&…...

NISP 一级 | 2.1 密码学

关注这个证书的其他相关笔记&#xff1a;NISP 一级 —— 考证笔记合集-CSDN博客 通过上一章的学习&#xff0c;我们知道了&#xff0c;网络安全的 CIA 模型&#xff0c;而本期学习的“密码学”&#xff0c;则能为 CIA 模型提供很好的技术支持&#xff1a; 面临的攻击威胁所破坏…...

深度学习速通系列:混淆矩阵是什么

混淆矩阵&#xff08;Confusion Matrix&#xff09;是一种评估分类模型性能的工具&#xff0c;尤其在监督学习中用于分析分类结果。它通过一个矩阵的形式&#xff0c;将模型的预测结果与实际标签进行比较&#xff0c;从而可以清晰地看到模型在各个类别上的表现。以下是混淆矩阵…...

综合评价 | 基于熵权-变异系数-博弈组合法的综合评价模型(Matlab)

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 根据信息熵的定义&#xff0c;对于某项指标&#xff0c;可以用熵值来判断某个指标的离散程度&#xff0c;其信息熵值越小&#xff0c;指标的离散程度越大&#xff0c; 该指标对综合评价的影响&#xff08;即权重&…...

模板与泛型编程笔记(一)

1. 推荐书籍 《C新经典 模板与泛型编程》难得的很容易看得懂的好书&#xff0c;作者讲技术不跳跃&#xff0c;娓娓道来&#xff0c;只要花点时间就能看懂。 2. 笔记 模板为什么要用尖括号&#xff1f;因为便于编译器解析&#xff0c;可以将模板和普通函数声明分开。其实尖括…...

ubuntu 和windows用samba服务器实现数据传输

1&#xff0c;linux安装samba服务器 sudo apt-get install samba samba-common 2&#xff0c;linux 配置权限&#xff0c;修改目录权限&#xff0c;linux下共享的文件权限设置。 sudo chmod 777 /home/lark -R 3. 添加samba用户 sudo smbpasswd -a lark 4&#xff0c;配置共享…...

NISP 一级 | 3.2 网络安全威胁

关注这个证书的其他相关笔记&#xff1a;NISP 一级 —— 考证笔记合集-CSDN博客 网络安全威胁主要来自攻击者对网络及信息系统的攻击&#xff0c;攻击者可以通过网络嗅探、网络钓鱼、拒绝服务、远程控制、社会工程学等网络攻击手段&#xff0c;获得目标计算机的控制权&#xff…...

【技术实践】MySQL分表分库全解析:从理论到实战

文章目录 【技术实践】MySQL分表分库全解析&#xff1a;从理论到实战1. 引言1.1 MySQL数据库面临的挑战1.2 分表分库的概念与优势 2. MySQL分表分库的基本原理2.1 水平分表2.2 垂直分表2.3 水平分库2.4 分表分库的选择标准 3. 实现分表分库的技术方案3.1 中间件解决方案3.2 自定…...

动手学深度学习(一)简介+预备知识+基础知识(上)

一、简介 1、机器学习 机器学习研究如何使用经验改善计算机系统的性能。 2、表征学习 表征学习是机器学习的一类&#xff0c;研究的是&#xff0c;如何自动学习出数据合适的表示方式&#xff0c;更好地由输入得到正确的输出。 3、深度学习 深度学习是具有多级表示的表征学…...