【行空板 Python编程学习主控板】六轴加速度传感器可视化测试
<div class='showpostmsg'><h1>b18472ede3497b6294d0457d83abc245<br /> </h1>
<h1><b>前言</b></h1>
<p >开发板自带六轴加速度传感器可实时测量三轴加速度,三轴角速度。</p>
<p >通过这些数据可以进行姿态解算,知道开发板的姿态变化,进而可利用此进行交互。</p>
<p >参考</p>
<p ><a href="https://wiki.unihiker.com/pinpong_python_lib#target_9"><u>https://wiki.unihiker.com/pinpong_python_lib#target_9</u></a></p>
<p > </p>
<h1 ><b>传感器数据获取</b></h1>
<div class="parsedown-markdown">
<p># -*- coding: utf-8 -*-</p>
<p >import time</p>
<p >from pinpong.board import *</p>
<p >from pinpong.extension.unihiker import *</p>
<p > </p>
<p >while True:</p>
<p > ax = accelerometer.get_x() #读取加速度X的值</p>
<p > ay = accelerometer.get_y() #读取加速度Y的值</p>
<p > az = accelerometer.get_z() #读取加速度Z的值</p>
<p > a = accelerometer.get_strength() #读取加速度强度(x、y、z方向的合力)</p>
<p > gx = gyroscope.get_x() #读取陀螺仪X的值</p>
<p > gy = gyroscope.get_y() #读取陀螺仪Y的值</p>
<p > gz= gyroscope.get_z() #读取陀螺仪Z的值</p>
<p > time.sleep(0.1)</p>
</div>
<p > </p>
<p > </p>
<h1 ><b>姿态解算</b></h1>
<div class="parsedown-markdown">
<p>import math</p>
<p > </p>
<p >#IMU算法更新</p>
<p > </p>
<p >Kp = 100 #比例增益控制加速度计/磁强计的收敛速度</p>
<p >Ki = 0.002 #积分增益控制陀螺偏差的收敛速度</p>
<p >halfT = 0.001 #采样周期的一半</p>
<p > </p>
<p >#传感器框架相对于辅助框架的四元数(初始化四元数的值)</p>
<p >q0 = 1</p>
<p >q1 = 0</p>
<p >q2 = 0</p>
<p >q3 = 0</p>
<p > </p>
<p >#由Ki缩放的积分误差项(初始化)</p>
<p >exInt = 0</p>
<p >eyInt = 0</p>
<p >ezInt = 0</p>
<p > </p>
<p >def Update_IMU(ax,ay,az,gx,gy,gz):</p>
<p > global q0</p>
<p > global q1</p>
<p > global q2</p>
<p > global q3</p>
<p > global exInt</p>
<p > global eyInt</p>
<p > global ezInt</p>
<p > # print(q0)</p>
<p > </p>
<p > #测量正常化</p>
<p > norm = math.sqrt(ax*ax+ay*ay+az*az)</p>
<p > #单元化</p>
<p > ax = ax/norm</p>
<p > ay = ay/norm</p>
<p > az = az/norm</p>
<p > </p>
<p > #估计方向的重力</p>
<p > vx = 2*(q1*q3 - q0*q2)</p>
<p > vy = 2*(q0*q1 + q2*q3)</p>
<p > vz = q0*q0 - q1*q1 - q2*q2 + q3*q3</p>
<p > </p>
<p > #错误的领域和方向传感器测量参考方向之间的交叉乘积的总和</p>
<p > ex = (ay*vz - az*vy)</p>
<p > ey = (az*vx - ax*vz)</p>
<p > ez = (ax*vy - ay*vx)</p>
<p > </p>
<p > #积分误差比例积分增益</p>
<p > exInt += ex*Ki</p>
<p > eyInt += ey*Ki</p>
<p > ezInt += ez*Ki</p>
<p > </p>
<p > #调整后的陀螺仪测量</p>
<p > gx += Kp*ex + exInt</p>
<p > gy += Kp*ey + eyInt</p>
<p > gz += Kp*ez + ezInt</p>
<p > </p>
<p > #整合四元数</p>
<p > q0 += (-q1*gx - q2*gy - q3*gz)*halfT</p>
<p > q1 += (q0*gx + q2*gz - q3*gy)*halfT</p>
<p > q2 += (q0*gy - q1*gz + q3*gx)*halfT</p>
<p > q3 += (q0*gz + q1*gy - q2*gx)*halfT</p>
<p > </p>
<p > #正常化四元数</p>
<p > norm = math.sqrt(q0*q0 + q1*q1 + q2*q2 + q3*q3)</p>
<p > q0 /= norm</p>
<p > q1 /= norm</p>
<p > q2 /= norm</p>
<p > q3 /= norm</p>
<p > </p>
<p > #获取欧拉角 pitch、roll、yaw</p>
<p > pitch = math.asin(-2*q1*q3+2*q0*q2)*57.3</p>
<p > roll = math.atan2(2*q2*q3+2*q0*q1,-2*q1*q1-2*q2*q2+1)*57.3</p>
<p > yaw = math.atan2(2*(q1*q2 + q0*q3),q0*q0+q1*q1-q2*q2-q3*q3)*57.3</p>
<p >return pitch,roll,yaw</p>
</div>
<p > </p>
<p >分别旋转三个轴,可以看到三个分量值变化。</p>
<p >打印欧拉角如下</p>
<p > </p>
<h1 ><b>可视化</b></h1>
<p><b>将角度投影到平面,根据角度计算x,y坐标的分量,从原点画线,就可以形成一个圆形轨迹,角度变化就对应着在圆形轨迹移动</b></p>
<p >这里只体现了r,y两个轴的角度</p>
<div class="parsedown-markdown">
<p>def Draw_Pos(gui,p,r,y):</p>
<p > l = 100</p>
<p > LCDX=240</p>
<p > LCDY=320</p>
<p > px = l*math.sin(p)</p>
<p > py = l*math.cos(p)</p>
<p > gui.draw_line(x0=LCDX/2,y0=LCDY/2,x1=LCDX/2+px,y1=LCDY/2+py,width=4,color=(255,0,0),onclick=lambda:print("line clicked"))</p>
</div>
<p > </p>
<h1 ><b>测试</b></h1>
<p >综合以上得到测试程序如下</p>
<div class="parsedown-markdown">
<p># -*- coding: utf-8 -*-</p>
<p >import time</p>
<p >from pinpong.board import *</p>
<p >from pinpong.extension.unihiker import *</p>
<p >from unihiker import GUI #导入包</p>
<p >import math</p>
<p > </p>
<p >#IMU算法更新</p>
<p > </p>
<p >Kp = 100 #比例增益控制加速度计/磁强计的收敛速度</p>
<p >Ki = 0.002 #积分增益控制陀螺偏差的收敛速度</p>
<p >halfT = 0.001 #采样周期的一半</p>
<p > </p>
<p >#传感器框架相对于辅助框架的四元数(初始化四元数的值)</p>
<p >q0 = 1</p>
<p >q1 = 0</p>
<p >q2 = 0</p>
<p >q3 = 0</p>
<p > </p>
<p >#由Ki缩放的积分误差项(初始化)</p>
<p >exInt = 0</p>
<p >eyInt = 0</p>
<p >ezInt = 0</p>
<p > </p>
<p >def Update_IMU(ax,ay,az,gx,gy,gz):</p>
<p > global q0</p>
<p > global q1</p>
<p > global q2</p>
<p > global q3</p>
<p > global exInt</p>
<p > global eyInt</p>
<p > global ezInt</p>
<p > # print(q0)</p>
<p > </p>
<p > #测量正常化</p>
<p > norm = math.sqrt(ax*ax+ay*ay+az*az)</p>
<p > #单元化</p>
<p > ax = ax/norm</p>
<p > ay = ay/norm</p>
<p > az = az/norm</p>
<p > </p>
<p > #估计方向的重力</p>
<p > vx = 2*(q1*q3 - q0*q2)</p>
<p > vy = 2*(q0*q1 + q2*q3)</p>
<p > vz = q0*q0 - q1*q1 - q2*q2 + q3*q3</p>
<p > </p>
<p > #错误的领域和方向传感器测量参考方向之间的交叉乘积的总和</p>
<p > ex = (ay*vz - az*vy)</p>
<p > ey = (az*vx - ax*vz)</p>
<p > ez = (ax*vy - ay*vx)</p>
<p > </p>
<p > #积分误差比例积分增益</p>
<p > exInt += ex*Ki</p>
<p > eyInt += ey*Ki</p>
<p > ezInt += ez*Ki</p>
<p > </p>
<p > #调整后的陀螺仪测量</p>
<p > gx += Kp*ex + exInt</p>
<p > gy += Kp*ey + eyInt</p>
<p > gz += Kp*ez + ezInt</p>
<p > </p>
<p > #整合四元数</p>
<p > q0 += (-q1*gx - q2*gy - q3*gz)*halfT</p>
<p > q1 += (q0*gx + q2*gz - q3*gy)*halfT</p>
<p > q2 += (q0*gy - q1*gz + q3*gx)*halfT</p>
<p > q3 += (q0*gz + q1*gy - q2*gx)*halfT</p>
<p > </p>
<p > #正常化四元数</p>
<p > norm = math.sqrt(q0*q0 + q1*q1 + q2*q2 + q3*q3)</p>
<p > q0 /= norm</p>
<p > q1 /= norm</p>
<p > q2 /= norm</p>
<p > q3 /= norm</p>
<p > </p>
<p > #获取欧拉角 pitch、roll、yaw</p>
<p > pitch = math.asin(-2*q1*q3+2*q0*q2)*57.3</p>
<p > roll = math.atan2(2*q2*q3+2*q0*q1,-2*q1*q1-2*q2*q2+1)*57.3</p>
<p > yaw = math.atan2(2*(q1*q2 + q0*q3),q0*q0+q1*q1-q2*q2-q3*q3)*57.3</p>
<p > return pitch,roll,yaw</p>
<p > </p>
<p >def Draw_Pos(gui,p,r,y):</p>
<p > l = 100</p>
<p > LCDX=240</p>
<p > LCDY=320</p>
<p > px = l*math.sin(p)</p>
<p > py = l*math.cos(p)</p>
<p > gui.draw_line(x0=LCDX/2,y0=LCDY/2,x1=LCDX/2+px,y1=LCDY/2+py,width=4,color=(255,0,0),onclick=lambda:print("line clicked"))</p>
<p > </p>
<p >Board().begin() #初始化</p>
<p >gui=GUI()#实例化GUI类</p>
<p > </p>
<p >while True:</p>
<p > ax = accelerometer.get_x() #读取加速度X的值</p>
<p > ay = accelerometer.get_y() #读取加速度Y的值</p>
<p > az = accelerometer.get_z() #读取加速度Z的值</p>
<p > a = accelerometer.get_strength() #读取加速度强度(x、y、z方向的合力)</p>
<p > gx = gyroscope.get_x() #读取陀螺仪X的值</p>
<p > gy = gyroscope.get_y() #读取陀螺仪Y的值</p>
<p > gz= gyroscope.get_z() #读取陀螺仪Z的值</p>
<p > p,r,y = Update_IMU(ax,ay,az,gx,gy,gz)</p>
<p > print(p,y,y)</p>
<p > Draw_Pos(gui,p,r,y)</p>
<p > time.sleep(0.1)</p>
</div>
<p > </p>
<p > </p>
<h1 ><b>总结</b></h1>
<p >以上测试了六轴传感器的基本操作与姿态解算,基于完善的官方python库,能很快就完成基本的Demo。</p>
<p >基于此可以完成更多的有意义的项目,比如水平仪,角度仪,手势控制等。</p>
</div><script> var loginstr = '<div class="locked">查看本帖全部内容,请<a href="javascript:;" style="color:#e60000" class="loginf">登录</a>或者<a href="https://bbs.eeworld.com.cn/member.php?mod=register_eeworld.php&action=wechat" style="color:#e60000" target="_blank">注册</a></div>';
if(parseInt(discuz_uid)==0){
(function($){
var postHeight = getTextHeight(400);
$(".showpostmsg").html($(".showpostmsg").html());
$(".showpostmsg").after(loginstr);
$(".showpostmsg").css({height:postHeight,overflow:"hidden"});
})(jQuery);
} </script><script type="text/javascript">(function(d,c){var a=d.createElement("script"),m=d.getElementsByTagName("script"),eewurl="//counter.eeworld.com.cn/pv/count/";a.src=eewurl+c;m.parentNode.insertBefore(a,m)})(document,523)</script> <p>注释的不错,看得很清晰</p>
<p>学习了,非常感谢。</p>
页:
[1]