chinese直男口爆体育生外卖, 99久久er热在这里只有精品99, 又色又爽又黄18禁美女裸身无遮挡, gogogo高清免费观看日本电视,私密按摩师高清版在线,人妻视频毛茸茸,91论坛 兴趣闲谈,欧美 亚洲 精品 8区,国产精品久久久久精品免费

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

學(xué)會(huì)面向?qū)ο缶幊谭庋bIMU驅(qū)動(dòng)

CHANBAEK ? 來(lái)源:魚(yú)香ROS ? 作者:小魚(yú) ? 2023-07-13 14:55 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

上一節(jié)我們成功讀取到了IMU的數(shù)據(jù),其中角度用歐拉角的方式表示的,在我們機(jī)器人世界里姿態(tài)的表示往往使用四元數(shù)表示(如果不清楚他們之間的關(guān)系可以回看第六章機(jī)器人學(xué)篇),所以我們需要將歐拉角轉(zhuǎn)換成四元數(shù)。除此之外我們還需要將其坐標(biāo)系矯正到右手坐標(biāo)系。

所以本節(jié)我們將通過(guò)面向?qū)ο蟮姆绞綄MU驅(qū)動(dòng)進(jìn)行封裝,并為其添加坐標(biāo)系轉(zhuǎn)換以及四元數(shù)轉(zhuǎn)換函數(shù)。

教程所使用硬件平臺(tái)為MicroROS學(xué)習(xí)板V1.0.0,可點(diǎn)擊閱讀原文購(gòu)買(mǎi)及查看詳情

圖片

一、理論介紹

1.1.歐拉角轉(zhuǎn)四元數(shù)

歐拉角轉(zhuǎn)四元數(shù)的公式我們?cè)诘诹氯腴T(mén)篇第三節(jié)有介紹,這里回顧一下

圖片

根據(jù)公式我們可以寫(xiě)出代碼

typedef struct
{
    float w;
    float x;
    float y;
    float z;
} quaternion_t;

Euler2Quaternion(float roll, float pitch, float yaw, quaternion_t &q)
{
    double cr = cos(roll * 0.5);
    double sr = sin(roll * 0.5);
    double cy = cos(yaw * 0.5);
    double sy = sin(yaw * 0.5);
    double cp = cos(pitch * 0.5);
    double sp = sin(pitch * 0.5);
    q.w = cy * cp * cr + sy * sp * sr;
    q.x = cy * cp * sr - sy * sp * cr;
    q.y = sy * cp * sr + cy * sp * cr;
    q.z = sy * cp * cr - cy * sp * sr;
}

1.2 坐標(biāo)系校準(zhǔn)

我們采用右手坐標(biāo)系,接著我們依次來(lái)校準(zhǔn)角度數(shù)據(jù)的方向。

打開(kāi)終端,點(diǎn)擊RST,查看IMU數(shù)據(jù)。

首先是X軸,我們讓開(kāi)發(fā)板上愛(ài)神丘比特的劍頭指向自己,然后從右側(cè)往左側(cè)傾斜。

可以看到此時(shí)X軸為正值,符合右手坐標(biāo)系法則。

接著是Y軸,平放,將箭頭朝向自己的胸口,接著抬高板子,讓箭頭指向自己的頭部,觀察Y軸的變化。

Y軸為負(fù)值,不符合右手坐標(biāo)系法則,所以Y的值應(yīng)該取一次負(fù),使其為正。

接著是Z軸,平放,將箭頭朝向自己的胸口,然后逆時(shí)針旋轉(zhuǎn)板子,觀察數(shù)值變化。

圖片

值為正,表示符合右手坐標(biāo)系法則。

你可能會(huì)問(wèn)小魚(yú)怎么確認(rèn)怎樣旋轉(zhuǎn)是正,怎樣旋轉(zhuǎn)是負(fù),首先要確認(rèn)軸向,我們開(kāi)發(fā)板的Z軸朝上,X軸朝前,此時(shí)Y軸應(yīng)該朝左。接著攤開(kāi)右手手掌,用大拇指朝向軸的方向,比如朝向X軸,然后握起手掌,那么你握的方向就是正方向。

二、開(kāi)始寫(xiě)代碼

新建工程example07_mpu6050_oop

圖片

接著為其添加依賴(lài)

修改platformio.ini

[env:featheresp32]
platform = espressif32
board = featheresp32
framework = arduino
lib_deps = 
    https://ghproxy.com/https://github.com/rfetick/MPU6050_light.git

接著在lib下新建IMU文件夾,并在文件夾下新建IMU.hIMU.cpp

圖片

IMU.h

#ifndef __IMU_H__
#define __IMU_H__
#include "Wire.h"
#include "MPU6050_light.h"

typedef struct
{
    float w;
    float x;
    float y;
    float z;
} quaternion_t; // 四元數(shù)結(jié)構(gòu)體

typedef struct
{
    float x;
    float y;
    float z;
} vector_3d_t; // 通用3D點(diǎn)結(jié)構(gòu)體

typedef struct
{
    quaternion_t orientation;
    vector_3d_t angle_euler;
    vector_3d_t angular_velocity;
    vector_3d_t linear_acceleration;
} imu_t; // IMU數(shù)據(jù)結(jié)構(gòu)體

class IMU
{
private:
    MPU6050 *mpu_; // mpu6050指針

public:
    /**
     * @brief 同u哦NPU6050構(gòu)造一個(gè)新的IMU對(duì)象
     *
     * @param mpu
     */
    IMU(MPU6050 &mpu);
    
    ~IMU() = default;
    /**
     * @brief 初始化函數(shù)
     *
     * @param sda 引腳編號(hào)
     * @param scl 引腳編號(hào)
     * @return true
     * @return false
     */
    bool begin(int sda, int scl);
    /**
     * @brief 歐拉角轉(zhuǎn)四元數(shù)
     *
     * @param roll 輸入X
     * @param pitch 輸入y
     * @param yaw 輸入Z
     * @param q  返回的四元數(shù)引用
     */
    static void Euler2Quaternion(float roll, float pitch, float yaw, quaternion_t &q);
    /**
     * @brief 獲取IMU數(shù)據(jù)函數(shù)
     *
     * @param imu
     */
    void getImuData(imu_t &imu);
    /**
     * @brief 更新IMU數(shù)據(jù),同上一節(jié)中的mou.update
     *
     */
    void update();
};

#endif // __IMU_H__

IMU.cpp

#include "IMU.h"

IMU::IMU(MPU6050 &mpu)
{
    mpu_ = &mpu;
};

bool IMU::begin(int sda, int scl)
{
    Wire.begin(sda, scl);
    byte status = mpu_- >begin();
    Serial.print(F("MPU6050 status: "));
    Serial.println(status);
    if (status != 0)
    {
        return false;
    } // stop everything if could not connect to MPU6050

    Serial.println(F("Calculating offsets, do not move MPU6050"));
    delay(1000);
    // mpu.upsideDownMounting = true; // uncomment this line if the MPU6050 is mounted upside-down
    mpu_- >calcOffsets(); // gyro and accelero
    Serial.println("Done!n");
    return true;
}

void IMU::Euler2Quaternion(float roll, float pitch, float yaw, quaternion_t &q)
{
    double cr = cos(roll * 0.5);
    double sr = sin(roll * 0.5);
    double cy = cos(yaw * 0.5);
    double sy = sin(yaw * 0.5);
    double cp = cos(pitch * 0.5);
    double sp = sin(pitch * 0.5);
    q.w = cy * cp * cr + sy * sp * sr;
    q.x = cy * cp * sr - sy * sp * cr;
    q.y = sy * cp * sr + cy * sp * cr;
    q.z = sy * cp * cr - cy * sp * sr;
}

void IMU::getImuData(imu_t &imu)
{
    imu.angle_euler.x = mpu_- >getAngleX();
    imu.angle_euler.y = -mpu_- >getAngleY();
    imu.angle_euler.z = mpu_- >getAngleZ();

    imu.angular_velocity.x = mpu_- >getAccAngleX();
    imu.angular_velocity.y = -mpu_- >getAccAngleY();
    imu.angular_velocity.z = mpu_- >getGyroZ();

    imu.linear_acceleration.x = mpu_- >getAccX();
    imu.linear_acceleration.y = mpu_- >getAccY();
    imu.linear_acceleration.z = mpu_- >getAccZ();

    IMU::Euler2Quaternion(imu.angle_euler.x, imu.angle_euler.y, imu.angle_euler.z,
                          imu.orientation);
}

void IMU::update()
{
    mpu_- >update();
}

main.cpp

#include < Arduino.h >
#include "IMU.h"

MPU6050 mpu(Wire); // 初始化MPU6050對(duì)象
IMU imu(mpu);      // 初始化IMU對(duì)象

imu_t imu_data;
unsigned long timer = 0;

void setup()
{
  Serial.begin(115200);
  imu.begin(18, 19); // 初始化IMU,使用18,19引腳
}

void loop()
{
  imu.update();
  if ((millis() - timer) > 100)
  {
    imu.getImuData(imu_data); // 獲取IMU數(shù)據(jù)結(jié)構(gòu)體
    Serial.printf("imu:teuler(%f,%f,%f)n",
                  imu_data.angle_euler.x, imu_data.angle_euler.y, imu_data.angle_euler.z);
    Serial.printf("imu:torientation(%f,%f,%f,%f)n",
                  imu_data.orientation.w, imu_data.orientation.x, imu_data.orientation.y, imu_data.orientation.z);
    timer = millis();
  }
}

對(duì)于代碼的解釋已經(jīng)放到了注釋之中。

編譯下載后,你將看到

圖片

三、總結(jié)

本節(jié)我們通過(guò)對(duì)MPU6050驅(qū)動(dòng)的封裝,學(xué)習(xí)了如何在嵌入式上使用面向?qū)ο?a href="http://www.brongaenegriffin.com/v/tag/1315/" target="_blank">編程的方法,下一節(jié)我們繼續(xù)嘗試使用開(kāi)源庫(kù)來(lái)驅(qū)動(dòng)OLED模塊,讓我們的顯示器亮起來(lái)。

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    Python的面向對(duì)象編程詳解

    一般編程可分為面向過(guò)程編程,和面向對(duì)象編程。Python的
    發(fā)表于 09-04 16:35 ?813次閱讀
    Python的<b class='flag-5'>面向</b><b class='flag-5'>對(duì)象</b><b class='flag-5'>編程</b>詳解

    labview面向對(duì)象編程

    點(diǎn)擊學(xué)習(xí)>>《龍哥手把手教你學(xué)LabVIEW視覺(jué)設(shè)計(jì)》視頻教程使用LabVIEW面向對(duì)象編程方法,對(duì)于大型測(cè)試應(yīng)用程序來(lái)講,面向對(duì)象相對(duì)于
    發(fā)表于 11-24 11:01

    labview面向對(duì)象編程

    有沒(méi)有大神在labview中用面向對(duì)象編程的?請(qǐng)教一下怎樣做?書(shū)上的對(duì)這方面的知識(shí)很少,無(wú)從下手,急急急急急急!
    發(fā)表于 08-08 14:26

    如何用C語(yǔ)言實(shí)現(xiàn)面向對(duì)象編程

    1 用C語(yǔ)言實(shí)現(xiàn)面向對(duì)象編程GOF的《設(shè)計(jì)模式》一書(shū)的副標(biāo)題叫做“可復(fù)用面向對(duì)象軟件的基礎(chǔ)”,從標(biāo)題就能看出
    發(fā)表于 07-12 07:24

    面向對(duì)象編程及其三大特性 精選資料分享

    Oriented)是一種以過(guò)程為中心的編程思想。這些都是以什么正在發(fā)生為 目標(biāo)進(jìn)行編程,不同于面向對(duì)象的是誰(shuí)在受影響。與面向
    發(fā)表于 07-21 08:38

    基于面向對(duì)象的LabVIEW編程有哪些優(yōu)勢(shì)

    基于面向對(duì)象的LabVIEW編程有哪些優(yōu)勢(shì)?如何去學(xué)習(xí)基于面向對(duì)象的LabVIEW編程?
    發(fā)表于 08-24 07:22

    談?wù)?b class='flag-5'>面向對(duì)象編程

    在工業(yè)自動(dòng)化領(lǐng)域,梯形圖邏輯仍然是最常用的編程語(yǔ)言之一,但對(duì)于更加復(fù)雜的控制對(duì)象面向對(duì)象編程不失為一種高效率的方式。下面先來(lái)談?wù)?/div>
    發(fā)表于 09-08 07:47

    面向對(duì)象編程語(yǔ)言的特點(diǎn)

    在工業(yè)自動(dòng)化領(lǐng)域,梯形圖邏輯仍然是最常用的編程語(yǔ)言之一,但對(duì)于更加復(fù)雜的控制對(duì)象,面向對(duì)象編程不失為一種高效率的方式。下面先來(lái)談?wù)?/div>
    發(fā)表于 09-08 07:44

    面向對(duì)象編程介紹

    目錄一、面向對(duì)象編程介紹1.面向過(guò)程編程2.函數(shù)式編程3.
    發(fā)表于 12-13 07:22

    如何在嵌入式上使用面向對(duì)象編程呢?

    代碼的解釋已經(jīng)放到了注釋之中?! 【幾g下載后,你將看到  三、總結(jié)  本節(jié)我們通過(guò)對(duì)MPU6050驅(qū)動(dòng)封裝,學(xué)習(xí)了如何在嵌入式上使用面向對(duì)象編程
    發(fā)表于 03-28 14:55

    面向對(duì)象編程練習(xí)

    實(shí)驗(yàn) 3 面向對(duì)象編程練習(xí) 一、實(shí)驗(yàn)?zāi)康?    通過(guò)編程和上機(jī)實(shí)驗(yàn)理解 Java 語(yǔ)言是如何體現(xiàn)面向
    發(fā)表于 09-23 18:57 ?3154次閱讀

    plc面向對(duì)象編程架構(gòu)與實(shí)現(xiàn)

    面向對(duì)象編程是計(jì)算機(jī)高級(jí)語(yǔ)言的一種先進(jìn)的編程模式,在工業(yè)控制系統(tǒng)的PLC程序中也可以采用這種設(shè)計(jì)思想,雖然我們無(wú)法實(shí)現(xiàn)面向
    發(fā)表于 01-31 15:00 ?4519次閱讀
    plc<b class='flag-5'>面向</b><b class='flag-5'>對(duì)象</b><b class='flag-5'>編程</b>架構(gòu)與實(shí)現(xiàn)

    面向對(duì)象方法實(shí)現(xiàn)IIC驅(qū)動(dòng)封裝以及AT24CXX存儲(chǔ)器的封裝

    使用面向對(duì)象編程思想封裝IIC驅(qū)動(dòng),將IIC的屬性和操作封裝成一個(gè)庫(kù),在需要?jiǎng)?chuàng)建一個(gè)IIC設(shè)備
    的頭像 發(fā)表于 09-16 09:22 ?1788次閱讀

    西門(mén)子PLC面向對(duì)象編程

    面向對(duì)象編程是計(jì)算機(jī)高級(jí)語(yǔ)言的一種高級(jí)編程模式,這種設(shè)計(jì)思想也可以應(yīng)用于工業(yè)控制系統(tǒng)的plc程序中。雖然我們 無(wú)法實(shí)現(xiàn)面向
    發(fā)表于 04-17 11:41 ?7次下載
    西門(mén)子PLC<b class='flag-5'>面向</b><b class='flag-5'>對(duì)象</b><b class='flag-5'>編程</b>

    什么是面向對(duì)象編程(OOP)?面向對(duì)象的程序設(shè)計(jì)

    編程領(lǐng)域,面向對(duì)象編程 (OOP) 是一種強(qiáng)大的范例,使開(kāi)發(fā)人員能夠構(gòu)建復(fù)雜且可擴(kuò)展的應(yīng)用程序。
    的頭像 發(fā)表于 07-19 14:57 ?1608次閱讀