結課作業01. 用戶空間 MPU6050 體感鼠標驅動程序

目錄

一.?qt界面實現

二.?虛擬設備模擬模擬鼠標實現體感鼠標

2.1 函數聲明

2.2 虛擬鼠標實現

2.2.1 虛擬鼠標創建函數

2.2.2?鼠標移動函數

2.2.3 鼠標點擊函數

2.3 mpu6050相關函數實現

2.3.1 i2c設備初始化

2.3.2 mpu6050寄存器寫入

2.3.3 mpu6050寄存器讀取

2.3.4 mpu6050初始化

2.3.5 read_accel 加速度數據獲取及處理函數

2.4 按鍵模擬鼠標點擊功能實現

2.4.1?導出export按鍵對應的gpio

2.4.2?將gpio方向direction設置為輸入

2.4.3 讀取按鍵gpio狀態,來控制鼠標按鍵

2.5 資源清理函數

2.6?主函數實現(偽代碼)

2.7 源代碼及執行步驟


????????使用uinput虛擬設備實現體感鼠標,通過用戶空間 input 設備測試程序讀取/dev/event*文件獲取鼠標狀態,鼠標移動數據能隨開發板傾角運動改變。

????????鼠標按鍵可以使用 Key_DOWN、Key_RIGHT、Key_LEFT、Key_UP 四個按鍵中任選兩個 實現,四個按鍵的 GPIO 編號為 960 – 963.(本實驗使用Key_RIGHT、Key_LEFT分別實現鼠標的右鍵和左鍵)

一.?qt界面實現

????????為了測試虛擬鼠標的功能,使用qt軟件畫了一個窗口,通過以下指令將 .ui文件 轉換成python可執行文件。

pyuic5 -x windows_mouse.ui -o windows_mouse.py

? ? ? ? ?qt完整python代碼如下

# -*- coding: utf-8 -*-# Form implementation generated from reading ui file 'windows_mouse.ui'
#
# Created by: PyQt5 UI code generator 5.10.1
#
# WARNING! All changes made in this file will be lost!
# windows_mouse.pyfrom PyQt5 import QtCore, QtGui, QtWidgetsclass Ui_Form(object):def setupUi(self, Form):Form.setObjectName("Form")Form.resize(480, 272)  # 調整窗口高度以容納新控件self.verticalLayout = QtWidgets.QVBoxLayout(Form)self.verticalLayout.setObjectName("verticalLayout")# 原有的 right 按鈕和進度條self.right = QtWidgets.QPushButton(Form)self.right.setObjectName("right")self.verticalLayout.addWidget(self.right)self.progressBarRight = QtWidgets.QProgressBar(Form)self.progressBarRight.setProperty("value", 0)  # 初始值設為 0self.progressBarRight.setObjectName("progressBarRight")self.verticalLayout.addWidget(self.progressBarRight)# 新增的 left 按鈕和進度條self.left = QtWidgets.QPushButton(Form)self.left.setObjectName("left")self.verticalLayout.addWidget(self.left)self.progressBarLeft = QtWidgets.QProgressBar(Form)self.progressBarLeft.setProperty("value", 0)  # 初始值設為 0self.progressBarLeft.setObjectName("progressBarLeft")self.verticalLayout.addWidget(self.progressBarLeft)self.Exit = QtWidgets.QPushButton(Form)self.Exit.setObjectName("Exit")self.verticalLayout.addWidget(self.Exit)self.retranslateUi(Form)self.Exit.clicked.connect(Form.close)# 設置 right 按鈕右鍵菜單self.right.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)self.right.customContextMenuRequested.connect(self.right_button_clicked)# 設置 left 按鈕左鍵點擊事件self.left.clicked.connect(self.left_button_clicked)QtCore.QMetaObject.connectSlotsByName(Form)def retranslateUi(self, Form):_translate = QtCore.QCoreApplication.translateForm.setWindowTitle(_translate("Form", "Form"))self.right.setText(_translate("Form", "right"))self.left.setText(_translate("Form", "left"))self.Exit.setText(_translate("Form", "left - Exit"))def right_button_clicked(self, pos):# right 按鈕右鍵點擊事件處理if self.progressBarRight.value() == 0:self.progressBarRight.setValue(100)  # 進度條加滿else:self.progressBarRight.setValue(0)  # 進度條變為 0def left_button_clicked(self):# left 按鈕左鍵點擊事件處理if self.progressBarLeft.value() == 0:self.progressBarLeft.setValue(100)  # 進度條加滿else:self.progressBarLeft.setValue(0)  # 進度條變為 0if __name__ == "__main__":import sysapp = QtWidgets.QApplication(sys.argv)Form = QtWidgets.QWidget()ui = Ui_Form()ui.setupUi(Form)Form.show()sys.exit(app.exec_())

? ? ? ? 運行python windows_mouse.py出現以下界面。其中right按鍵只能鼠標右鍵點擊,left按鍵只能鼠標左鍵點擊,left-Exit為鼠標左鍵點擊的退出按鍵。

二.?虛擬設備模擬模擬鼠標實現體感鼠標

2.1 函數聲明

????????總共分為四個部分,分別是mpu6050設備初始化及信息獲取、虛擬鼠標實現、gpio設備初始化及按鍵gpio信息獲取、資源清理clean。

/* 函數聲明 */
// mpu6050和i2c的初始化和功能函數
int i2c_init(const char* i2c_dev);
void mpu6050_write(int fd, uint8_t reg, uint8_t val);
void mpu6050_read(int fd, uint8_t reg, uint8_t* buf, int len);
void mpu6050_init(int fd);
void read_accel(int fd, float* accel);
// 清理
void cleanup_handler(int sig);
// 虛擬鼠標創建及移動、點擊
int create_virtual_mouse(const char* dev_name);
void send_mouse_move(int fd, int dx, int dy);
int send_mouse_click(int fd, int button_code);// 按鍵對應鼠標點擊
void set_gpio_direction(int gpio, const char *direction);
char read_gpio_value(int gpio);
void export_gpio(int gpio);
void unexport_gpio(int gpio);

2.2 虛擬鼠標實現

2.2.1 虛擬鼠標創建函數

????????1. 創建虛擬鼠標需要:配置鼠標移動按鍵事件、初始化設備信息、提交設備配置 三個步驟。

int create_virtual_mouse(const char* dev_name) {struct uinput_user_dev uidev;int fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);/* 配置基礎事件類型 */    // 此處沒有錯誤處理,代碼里有// 鼠標移動事件ioctl(fd, UI_SET_EVBIT, EV_REL);ioctl(fd, UI_SET_RELBIT, REL_X);ioctl(fd, UI_SET_RELBIT, REL_Y);// 鼠標按鍵事件ioctl(fd, UI_SET_EVBIT, EV_KEY);ioctl(fd, UI_SET_KEYBIT, BTN_LEFT);ioctl(fd, UI_SET_KEYBIT, BTN_RIGHT);/* 初始化設備信息 */memset(&uidev, 0, sizeof(uidev));snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "%s", dev_name);uidev.id.bustype = BUS_USB;uidev.id.version = 4;/* 提交設備配置 */ioctl(fd, UI_DEV_SETUP, &uidev);    // 提交設備配置ioctl(fd, UI_DEV_CREATE);           // 創建設備
}

2.2.2?鼠標移動函數

void send_mouse_move(int fd, int dx, int dy) {struct input_event ev[3];struct timeval tv;gettimeofday(&tv, NULL);    // 此函數是獲取時間戳// X軸移動memset(&ev[0], 0, sizeof(ev[0]));	// 初始化ev[0]的所有成員為0ev[0].type = EV_REL;ev[0].code = REL_X;ev[0].value = dx;ev[0].time = tv;// Y軸移動memset(&ev[1], 0, sizeof(ev[1]));ev[1].type = EV_REL;ev[1].code = REL_Y;ev[1].value = dy;ev[1].time = tv;// 同步事件memset(&ev[2], 0, sizeof(ev[2]));ev[2].type = EV_SYN;ev[2].code = SYN_REPORT;ev[2].value = 0;ev[2].time = tv;
}

? ? ? ? 1.?使用到的結構體?input_event 結構體介紹

#include <linux/input.h>struct input_event {struct timeval time;  // 時間戳__u16 type;           // 事件類型__u16 code;           // 事件代碼__s32 value;          // 事件值
};
變量名類型功能
timestruct timeval記錄輸入事件發生的時間戳,包含秒(tv_sec)和微秒(tv_usec),通常用于事件排序或性能分析
type__u16

表示輸入事件的類型,如按鍵事件(EV_KEY)、相對位置事件(EV_REL)

、(EV_SYN)同步事件(標記批次結束)

code__u16

與 type 結合,具體化事件含義,如具體按鍵、軸或輸入元素

EV_KEY 類型

BTN_LEFT? // 鼠標左鍵(0x110)、

BTN_RIGHT // 鼠標右鍵(0x111)、

KEY_ENTER ?// 回車鍵(0x1c)

EV_REL 類型

REL_X? // X軸相對移動、

(0x00)REL_Y ?// Y軸相對移動(0x01)、

REL_WHEEL? // 滾輪滾動(0x08)

EV_ABS 類型

ABS_X ?// X軸絕對坐標、(

0x00)ABS_Y? // Y軸絕對坐標(0x01)

value__s32

表示與事件相關的具體值,含義取決于 event 的 type 和 code

EV_KEY 事件:

value = 1:按鍵按下

value = 0:按鍵釋放

value = 2:按鍵長按(部分設備支持)

EV_REL 事件:

value = 10:X軸向右移動10像素

value = -5:Y軸向下移動5像素

EV_ABS 事件:

value = 500:觸摸屏X軸坐標為500

? ? ? ? ?2. 注意:每次事件完成都要調用同步事件,將鼠標位置和按鍵狀態更新。

2.2.3 鼠標點擊函數

? ? ? ? 和鼠標移動函數類似,只是將鼠標移動函數中的input_event結構體的參數值給鼠標按鍵相關的參數即可。

2.3 mpu6050相關函數實現

2.3.1 i2c設備初始化

/* I2C設備初始化 */
int i2c_init(const char* i2c_dev) {int fd = open(i2c_dev, O_RDWR);if (fd < 0) {perror("Failed to open I2C device");return -1;}// 因為ioctl的數據結構體有“從機地址”參數,所以不用單獨設置從機地址return fd;
}

2.3.2 mpu6050寄存器寫入

/* MPU6050寄存器寫操作 */
void mpu6050_write(int fd, uint8_t reg, uint8_t val) {struct i2c_msg msg;uint8_t buf[2] = {reg, val};msg.addr  = MPU6050_ADDR;	// 設備地址msg.flags = 0;		// 寫操作msg.len   = 2;		// 數據長度(寄存器地址 + 值)msg.buf   = buf;		// 數據緩沖區struct i2c_rdwr_ioctl_data ioctl_data;ioctl_data.msgs = &msg;	// 消息數組ioctl_data.nmsgs = 1;	// 消息數量if (ioctl(fd, I2C_RDWR, &ioctl_data) < 0)perror("MPU6050 write failed");
}

? ? ? ? 1. struct i2c_rdwr_ioctl_data結構體詳解

struct i2c_rdwr_ioctl_data {struct i2c_msg* msgs;  /* I2C 消息數組的指針 */int nmsgs;             /* 消息數組的元素個數 */
};
參數名類型功能
msgsstruct i2c_msg*指向一個?i2c_msg?結構體數組的指針,每個數組元素描述了一次 I2C 傳輸操作(消息)。
nmsgsint表示?msgs?數組中元素的個數,即要執行的 I2C 消息傳輸操作的次數。

? ? ? ? 2.??struct i2c_msg結構體詳解

struct i2c_msg {__u16 addr;        /* I2C從設備地址 */__u16 flags;       /* 消息標志 */__u16 len;         /* 數據緩沖區長度 */__u8 *buf;         /* 數據緩沖區指針 */
};
參數名類型功能說明
addr__u16I2C從設備地址,用于指定要通信的從設備的7位或10位地址
flags__u16消息標志,用于指定傳輸方向等信息,如I2C_M_RD(讀取操作),flags=0(寫入操作)等
len__u16要傳輸的數據長度,即buf數組中數據的字節數
buf__u8 *指向數據緩沖區的指針,用于存儲要發送的數據或接收到的數據

2.3.3 mpu6050寄存器讀取

? ? ? ? 將 i2c_msg 的flags標志換成讀取操作即可。

? ? ? ? 注意:在讀取數據之前,主設備(linux開發板)需要先指定要讀取的從設備(mpu6050)寄存器地址。所以在讀取數據之前需要先進行一次寫入。這個寫入操作的作用是將寄存器地址發送給 MPU6050,告訴它接下來要從哪個寄存器開始讀取數據。

2.3.4 mpu6050初始化

/* MPU6050初始化 (關閉睡眠模式)*/
void mpu6050_init(int fd) {mpu6050_write(fd, ACCEL_CONFIG, 0x00); // ±2g量程mpu6050_write(fd, PWR_MGMT_1, 0x00);   // 退出睡眠模式usleep(100000); // 等待穩定100ms
}

2.3.5 read_accel 加速度數據獲取及處理函數

? ? ? ? 調用mpu6050_read函數讀取加速度數據,并進行處理,轉換為m/s2的加速度。

/* 讀取加速度數據 (XYZ 三軸)*/
void read_accel(int fd, float* accel) {uint8_t buf[6];mpu6050_read(fd, ACCEL_XOUT_H, buf, 6);// 合并原始數據并轉換單位int16_t raw_x = (int16_t)((buf[0] << 8) | buf[1]);	// X 軸int16_t raw_y = (int16_t)((buf[2] << 8) | buf[3]);	// Y 軸int16_t raw_z = (int16_t)((buf[4] << 8) | buf[5]);	// Z 軸// 轉換為 m/s2accel[0] = (raw_x / ACCEL_SCALE_2G) * GRAVITY_CM_S2;accel[1] = (raw_y / ACCEL_SCALE_2G) * GRAVITY_CM_S2;accel[2] = (raw_z / ACCEL_SCALE_2G) * GRAVITY_CM_S2;
}

2.4 按鍵模擬鼠標點擊功能實現

2.4.1?導出export按鍵對應的gpio

????????還有對應的撤銷導出unexport函數同理。

// 導出gpio
void export_gpio(int gpio) {FILE *fp = fopen(GPIO_EXPORT, "w");if (fp == NULL) {perror("Failed to open export file");fprintf(stderr, "Error code: %d\n", errno);exit(EXIT_FAILURE);}fprintf(fp, "%d", gpio);fclose(fp);
}

2.4.2?將gpio方向direction設置為輸入

// 設置gpio方向為輸入
void set_gpio_direction(int gpio, const char *direction) {char path[64];snprintf(path, sizeof(path), GPIO_DIRECTION, gpio);FILE *fp = fopen(path, "w");if (fp == NULL) {perror("Failed to open direction file");fprintf(stderr, "Error code: %d\n", errno);exit(EXIT_FAILURE);}fprintf(fp, "%s", direction);fclose(fp);
}

2.4.3 讀取按鍵gpio狀態,來控制鼠標按鍵

char read_gpio_value(int gpio) {char path[64];snprintf(path, sizeof(path), GPIO_VALUE, gpio);FILE *fp = fopen(path, "r");if (fp == NULL) {perror("Failed to open value file");fprintf(stderr, "Error code: %d\n", errno);exit(EXIT_FAILURE);}char value[2];fgets(value, sizeof(value), fp);fclose(fp);return value[0] == '1' ? '1' : '0';
}

2.5 資源清理函數

? ? ? ? 銷毀虛擬設備、關閉i2c、撤銷導出按鍵gpio。

void cleanup_handler(int sig) {if (uinput_fd >= 0) {// 銷毀虛擬設備ioctl(uinput_fd, UI_DEV_DESTROY);close(uinput_fd);printf("\n[Cleanup] Virtual mouse device destroyed\n");}if (i2c_fd >= 0) {  // 新增:關閉I2C設備close(i2c_fd);printf("[Cleanup] I2C device closed\n");i2c_fd = -1;     // 重置描述符}int gpios[] = {960, 961, 962, 963, 964};int num_gpios = sizeof(gpios) / sizeof(gpios[0]);for (int i = 0; i < num_gpios; i++) {unexport_gpio(gpios[i]);}printf("all gpio unexported\n");fflush(stdout); // 強制刷新標準輸出exit(EXIT_SUCCESS);
}

2.6?主函數實現(偽代碼)

int main() {// 1. 注冊信號處理(Ctrl+C)/* 2. 創建虛擬鼠標 *//* 3. 初始化MPU6050 */// 4. 導出五個按鍵的gpio,并設置方向為輸入while (1) {// 調整方向// 發送給虛擬鼠標使其移動// 讀取當前按鈕狀態// 鍵盤左鍵對應鼠標左鍵// 鍵盤右鍵對應鼠標右鍵// 按鍵消抖}//資源清理
}

2.7 源代碼及執行步驟

? ? ? ? 源代碼:用戶空間MPU6050體感虛擬鼠標驅動程序資源-CSDN文庫

# 代碼編譯 -lm 是因為使用了數學公式
gcc mpu_mouse.c -o mpu_mouse.out -lm# 功能實現1:添加需要的環境變量,屏幕和鼠標# Qt-embedded需要的環境變量
# ? 指定顯示設備
export QT_QPA_PLATFORM=linuxfb
# ? 指定輸入設備(觸摸屏)
export QT_QPA_GENERIC_PLUGINS=evdevtouch:/dev/input/event0
export QWS_MOUSE_PROTO=evdevtouch:/dev/input/event0
# ? 指定輸入設備(鼠標)
export QT_QPA_GENERIC_PLUGINS=evdevmouse:/dev/input/event0
export QWS_MOUSE_PROTO=evdevmouse:/dev/input/event0# 功能實現2 # "&"符號是因為要放在后臺運行,然后運行鼠標控制程序
python windows_mouse.py &
./mpu_mouse.c

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/84529.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/84529.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/84529.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

深入淺出 Python Testcontainers:用容器優雅地編寫集成測試

在現代軟件開發中&#xff0c;自動化測試已成為敏捷開發與持續集成中的關鍵環節。單元測試可以快速驗證函數或類的行為是否符合預期&#xff0c;而集成測試則確保多個模塊協同工作時依然正確。問題是&#xff1a;如何讓集成測試可靠、可重復且易于維護&#xff1f; 這時&#…

JVM 的垃圾回收器

新生代回收器 通性 會觸發StW&#xff0c;暫停所有應用線程復制算法 Serial 單線程回收適合單線程系統 ParNew 多線程回收優先保證響應速度&#xff0c;降低 STW&#xff08;STW 越大&#xff0c;執行垃圾回收的時間越長&#xff0c;回收的垃圾越多&#xff0c;減少垃圾回…

【筆記】排查并解決Error in LLM call after 3 attempts: (status code: 502)

#工作記錄 一、問題描述 在部署運行部署對沖基金分析工具 ai-hedge-fund 時&#xff0c;不斷出現以下報錯&#xff0c;導致項目運行異常&#xff1a; Error in LLM call after 3 attempts: (status code: 502) Error in LLM call after 3 attempts: [WinError 10054] 遠程主…

GO 語言進階之 Template 模板使用

更多個人筆記見&#xff1a; github個人筆記倉庫 gitee 個人筆記倉庫 個人學習&#xff0c;學習過程中還會不斷補充&#xff5e; &#xff08;后續會更新在github上&#xff09; 文章目錄 Template 模板基本示例語法1. 基本輸出語法2. 控制結構3. 空白字符控制4. Must函數 Temp…

origin繪圖之【如何將多條重疊、高度重疊的點線圖、折線圖分開】

在日常的數據可視化工作中&#xff0c;Origin 作為一款功能強大的科研繪圖軟件&#xff0c;廣泛應用于實驗數據處理、結果展示與論文圖表制作等領域。然而&#xff0c;在處理多組數據、特別是繪制多條曲線的折線圖或點線圖時&#xff0c;常常會遇到這樣一個困擾&#xff1a;多條…

Java基礎 Day19

一、泛型&#xff08;JDK5引入&#xff09; 1、基本概念 在編譯階段約束操作的數據類型&#xff0c;并進行檢查 好處&#xff1a;統一數據類型&#xff0c;將運行期的錯誤提升到了編譯期 泛型的默認類型是 Object 2、泛型類 在創建類的時候寫上泛型 在創建具體對象的時候…

Gitlab-Runner安裝

文章目錄 helm方式安裝在K8S上參考gitlab CI/CD 文件變量緩存服務器K8S部署 docker鏡像mavendocker安裝docker buildx minionodehelmkubectlsonar-scanner-cli 問題清除cachehelm執行時無權限 下載鏡像失敗下載gitlab-runner鏡像失敗 Gitlab-ci中使用java前端 helm方式安裝在K8…

在 Ubuntu linux系統中設置時區的方案

查看時區 在 Ubuntu 系統中&#xff0c;可以通過以下方法查看當前時區設置&#xff1a; 1. 使用 timedatectl 命令&#xff08;推薦&#xff09; 在終端運行以下命令&#xff1a; timedatectl輸出示例&#xff1a; Local time: Sun 2025-05-25 10:30:00 CST Universal t…

YOLOv8模型剪枝筆記(DepGraph和Network Slimming網絡瘦身)

文章目錄 一、DepGraph剪枝(1)項目準備1)剪枝基礎知識2)DepGraph剪枝論文解讀12)DepGraph剪枝論文解讀23)YOLO目標檢測系列發展史4)YOLO網絡架構(2)項目實戰(YOLOv8應用DepGraph剪枝+finetune)1)安裝軟件環境(基礎環境、Pytorch、YOLOv8)Windows1)安裝軟件環境(…

MySQL:11_事務

事務 一.CURD不加控制&#xff0c;會有什么問題&#xff1f; 二.什么是事務&#xff1f; 事務就是一組DML語句組成&#xff0c;這些語句在邏輯上存在相關性&#xff0c;這一組DML語句要么全部成功&#xff0c;要么全部失敗&#xff0c;是一個整體。MySQL提供一種機制&#xf…

【notepad++如何設置成中文界面呢?】

“Notepad”是一款非常強大的文本編輯軟件&#xff0c;將其界面設置成中文的方法如下&#xff1a; 一、工具&#xff0f;原料&#xff1a; 華為 Matebook 15、Windows 10、Notepad 8.4.6。 二 、具體步驟&#xff1a; 1、找到任意一個文本文件&#xff0c;比如 txt 格式的文…

職坐標嵌入式MCU/DSP與RTOS開發精講

嵌入式系統開發作為現代智能設備與工業控制的核心技術領域&#xff0c;其架構設計與實現邏輯直接影響系統性能與可靠性。本課程以嵌入式系統架構為切入點&#xff0c;系統化梳理從硬件選型到軟件調度的全鏈路知識體系&#xff0c;重點聚焦微控制器&#xff08;MCU&#xff09;與…

雙深度Q網絡(Double DQN)基礎解析與python實例:訓練穩定倒立擺

目錄 1. 前言 2. Double DQN的核心思想 3. Double DQN 實例&#xff1a;倒立擺 4. Double DQN的關鍵改進點 5. 雙重網絡更新策略 6. 總結 1. 前言 在強化學習領域&#xff0c;深度Q網絡&#xff08;DQN&#xff09;開啟了利用深度學習解決復雜決策問題的新篇章。然而&am…

使用KubeKey快速部署k8s v1.31.8集群

實戰環境涉及軟件版本信息&#xff1a; 使用kubekey部署k8s 1. 操作系統基礎配置 設置主機名、DNS解析、時鐘同步、防火墻關閉、ssh免密登錄等等系統基本設置 dnf install -y curl socat conntrack ebtables ipset ipvsadm 2. 安裝部署 K8s 2.1 下載 KubeKey ###地址 https…

SQL:窗口函數(Window Functions)

目錄 什么是窗口函數&#xff1f; 基本語法結構 為什么要用窗口函數&#xff1f; 常見的窗口函數分類 1?? 排名類函數 2?? 聚合類函數&#xff08;不影響原始行&#xff09; 3?? 值訪問函數 窗口范圍說明&#xff08;ROWS / RANGE&#xff09; 什么是窗口函數&a…

相機內參 opencv

視場角定相機內參 import numpy as np import cv2 import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3Ddef calculate_camera_intrinsics(image_width640, image_height480, fov55, is_horizontalTrue):"""計算相機內參矩陣參數:image_w…

MATLAB 各個工具箱 功能說明

? 想必大家在安裝MATLAB時&#xff0c;或多或少會疑惑應該安裝哪些工具箱。筆者遇到了兩種情況——只安裝了MATLAB主程序&#xff0c;老師讓用MATLAB的時候卻發現沒有安裝對應安裝包&#xff1b;第二次安裝學聰明了&#xff0c;全選安裝&#xff0c;嗯……占用了20多個G。 ?…

學習日記-day14-5.23

完成目標&#xff1a; 學習java下半段課程 知識點&#xff1a; 1.多態轉型 知識點 核心內容 重點 多態轉型 向上轉型&#xff08;父類引用指向子類對象&#xff09; 與向下轉型&#xff08;強制類型轉換&#xff09;的機制與區別 向上轉型自動完成&#xff0c;向下轉型需…

【編程語言】【Java】一篇文章學習java,復習完善知識體系

第一章 Java基礎 1.1 變量與數據類型 1.1.1 基本數據類型 1.1.1.1 整數類型&#xff08;byte、short、int、long&#xff09; 在 Java 中&#xff0c;整數類型用于表示沒有小數部分的數字&#xff0c;不同的整數類型有不同的取值范圍和占用的存儲空間&#xff1a; byte&am…

匯量科技前端面試題及參考答案

數組去重的方法有哪些&#xff1f; 在 JavaScript 中&#xff0c;數組去重是一個常見的操作&#xff0c;有多種方法可以實現這一目標。每種方法都有其適用場景和性能特點&#xff0c;下面將詳細介紹幾種主要的去重方法。 使用 Set 數據結構 Set 是 ES6 引入的一種新數據結構&a…