当前位置: 首页 > 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…...

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站&#xff0c;会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后&#xff0c;网站没有变化的情况。 不熟悉siteground主机的新手&#xff0c;遇到这个问题&#xff0c;就很抓狂&#xff0c;明明是哪都没操作错误&#x…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度​

一、引言&#xff1a;多云环境的技术复杂性本质​​ 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时&#xff0c;​​基础设施的技术债呈现指数级积累​​。网络连接、身份认证、成本管理这三大核心挑战相互嵌套&#xff1a;跨云网络构建数据…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄

文&#xff5c;魏琳华 编&#xff5c;王一粟 一场大会&#xff0c;聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中&#xff0c;汇集了学界、创业公司和大厂等三方的热门选手&#xff0c;关于多模态的集中讨论达到了前所未有的热度。其中&#xff0c;…...

椭圆曲线密码学(ECC)

一、ECC算法概述 椭圆曲线密码学&#xff08;Elliptic Curve Cryptography&#xff09;是基于椭圆曲线数学理论的公钥密码系统&#xff0c;由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA&#xff0c;ECC在相同安全强度下密钥更短&#xff08;256位ECC ≈ 3072位RSA…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎&#xff08;Physics Engine&#xff09; 物理引擎 是一种通过计算机模拟物理规律&#xff08;如力学、碰撞、重力、流体动力学等&#xff09;的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互&#xff0c;广泛应用于 游戏开发、动画制作、虚…...

【Linux】C语言执行shell指令

在C语言中执行Shell指令 在C语言中&#xff0c;有几种方法可以执行Shell指令&#xff1a; 1. 使用system()函数 这是最简单的方法&#xff0c;包含在stdlib.h头文件中&#xff1a; #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件

今天呢&#xff0c;博主的学习进度也是步入了Java Mybatis 框架&#xff0c;目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学&#xff0c;希望能对大家有所帮助&#xff0c;也特别欢迎大家指点不足之处&#xff0c;小生很乐意接受正确的建议&…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版​分享

平时用 iPhone 的时候&#xff0c;难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵&#xff0c;或者买了二手 iPhone 却被原来的 iCloud 账号锁住&#xff0c;这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...

1688商品列表API与其他数据源的对接思路

将1688商品列表API与其他数据源对接时&#xff0c;需结合业务场景设计数据流转链路&#xff0c;重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点&#xff1a; 一、核心对接场景与目标 商品数据同步 场景&#xff1a;将1688商品信息…...

Razor编程中@Html的方法使用大全

文章目录 1. 基础HTML辅助方法1.1 Html.ActionLink()1.2 Html.RouteLink()1.3 Html.Display() / Html.DisplayFor()1.4 Html.Editor() / Html.EditorFor()1.5 Html.Label() / Html.LabelFor()1.6 Html.TextBox() / Html.TextBoxFor() 2. 表单相关辅助方法2.1 Html.BeginForm() …...