IMU 姿态解算
IMU 通过加速度计解算姿态角
通过三角函数可以将加速度计三个轴的角速度解算为姿态角,其中
其中重力加速度
将 g 的值带入上式可以得到:
其中 α 为俯仰角 pitch,β 为滚转角 roll,其中航向角 yaw 是没有办法通过加速度计来计算的。
通过三角函数可以将加速度计三个轴的角速度解算为姿态角,其中
其中重力加速度
将 g 的值带入上式可以得到:
其中 α 为俯仰角 pitch,β 为滚转角 roll,其中航向角 yaw 是没有办法通过加速度计来计算的。
you should not run configure as root (set FORCE_UNSAFE_CONFIGURE=1 in environment to bypass this check)
解决方法:
1 | export FORCE_UNSAFE_CONFIGURE=1 |
Buildroot 为交叉编译工具链提供两种解决方案:
Toolchain
中选择已有的 profile 即可Toolchain
中选择 profile
后,反选掉 Download toolchain automatically
并在 Toolchain path
中填写已有工具链路径即可Toolchain
列表中的 Custom toolchain
,然后填写 Toolchain path
, Toolchain prefix
, External toolchain C librrary
选项。若外部工具链使用
glibc 库,只需要选择工具链是否支持 C++ 以及是否内建 RPC
支持即可。如果使用 uClibc 库,则还有宽字符、本地化、程序
invocation、线程支持等选项Buildroot 不支持由 OpenEmbedded、Yocto 支持的工具链,因为这些工具生成的工具链并不是单纯的工具链——它们除了编译器、binutils、C/C++ 库之外还加了一大堆预编译的库和程序。因此 Buildroot 并没有办法导入它们的 sysroot 。Buildroot 也不支持发行版提供的工具链,这些工具链包含的东西也比较复杂,所以无法加载到构建环境中。
RTOS 的实时性该怎么理解呢?快速?确定性?
我们知道一般都是 Cortex-M 跑 RTOS,Cortex-A 很少跑 RTOS,一般都是跑 Linux、Android 这些非实时系统。如果单纯从速度来看 A 核在高主频加持下一定会具有更快的速度才对呀,那 M 核的竞争力在哪里呢?实际上这就是 A 核和 M 核在设计上的两个不同方向的取舍。
首先我们看 NVIC 中断控制器的设计:
NVIC 中断控制器在实时性上是满足要求的,快速和确定性都满足,但是他不适合处理大量中断,假如每秒要处理成千上万(这个中断数量对于 A 核来讲是很常见的 UAC、UVC,DSP 等一个模块每秒可能就有几千个中断)个中断,那么对 NVIC 来讲这是灾难性的,各种嵌套设计各种性能评估,除此之外对于多核系统 NVIC 也没有一套将中断分配给各个 CPU 核的机制,那么就无法充分利用多核的优势提高中断处理能力。而 A 核的 GIC 控制器就是为解决这些问题而设计的。
Cortex-A 核的 GIC 中断控制器设计很复杂,但是不支持中断嵌套,由 Distributor、CPU interface、Redistributor、ITS 组成,Distributor 具有仲裁和分发的作用,会将中断发送给 Redistributor,Redistributor 将中断发送给 CPU interface。这样第一解决了多核问题,其次 GIC 没有中断嵌套,当中断发生后跳转到一个固定地址,然后判断中断源进行下一步跳转,在 Linux 中接下来就会分为中断上半部和下半部机制,上半部在硬中断上下文快速响应然后返回,以更快处理其他中断兼顾实时性。中断下半部为了不同的应用需求设计了 softirq、tasklet、workqueue、thread 等机制来实现大量的中断任务,兼顾高性能。GIC 中断控制器解决了 NVIC 的问题但是却丢了硬实时性。
从中断控制器视角看实时性是快速+确定的 latency。
1 | #include <linux/timekeeping32.h> |
ktime accessors — The Linux Kernel documentation
可以使用 ktime_get_ns() 替代。 如果要获取 us 时间会涉及到 64bit 除法问题,会遇到如下问题:
1 | ERROR: modpost: "__aeabi_uldivmod" [common_drivers/drivers/usb/dwc_otg.ko] undefined! |
调用 div_u64() 函数,需要 include <linux/math64.h>
1 | u64 tm = div_u64(ktime_get_raw_ns(),1000); |
1 | int* f(); //f 为一个函数,函数返回值为指向整形的指针 |
设置官方镜像源(包括 core, extra, community, multilib )
1 | sudo pacman-mirrors -i -c China -m rank |
然后勾选你需要的镜像源,确认即可。
1 | sudo pacman -Syy //更新数据源 |
1 | class Circle |
Fatal assertion | Nonfatal assertion | Verifies |
---|---|---|
ASSERT_TRUE(condition); | EXPECT_TRUE(condition); | condition is true |
ASSERT_FALSE(condition); | EXPECT_FALSE(condition); | condition is false |
Fatal assertion | Nonfatal assertion | Verifies |
---|---|---|
ASSERT_EQ(val1, val2); | EXPECT_EQ(val1, val2); | val1 == val2 |
ASSERT_NE(val1, val2); | EXPECT_NE(val1, val2); | val1 != val2 |
ASSERT_LT(val1, val2); | EXPECT_LT(val1, val2); | val1 < val2 |
ASSERT_LE(val1, val2); | EXPECT_LE(val1, val2); | val1 <= val2 |
ASSERT_GT(val1, val2); | EXPECT_GT(val1, val2); | val1 > val2 |
ASSERT_GE(val1, val2); | EXPECT_GE(val1, val2); | val1 >= val2 |
Fatal assertion | Nonfatal assertion | Verifies |
---|---|---|
ASSERT_STREQ(str1,str2); | EXPECT_STREQ(str1,str2); | the two C strings have the same content |
ASSERT_STRNE(str1,str2); | EXPECT_STRNE(str1,str2); | the two C strings have different contents |
ASSERT_STRCASEEQ(str1,str2); | EXPECT_STRCASEEQ(str1,str2); | the two C strings have the same content, ignoring case |
ASSERT_STRCASENE(str1,str2); | EXPECT_STRCASENE(str1,str2); | the two C strings have different contents, ignoring case |
注意:“CASE”表明忽略大小写,一个 NULL 指针和空字符串不一样