第四章:相機模塊與雲台模塊
在第三章:任務管理器與航點任務/熱點任務中,我們學會了如何為無人機規劃複雜的自動化飛行路徑
既然無人機已經能夠自主飛行,那麼它的"視覺"系統呢?如何讓它拍照、錄像或將相機指向特定方向?
這就是**相機模塊(CameraModule)和雲台模塊(GimbalModule)**的用武之地!它們是無人機的"眼睛"和"頸部",讓你能夠通過編程控制相機及其穩定雲台。
什麼是"相機模塊"和"雲台模塊"?(無人機的視覺與指向控制系統)
想象你的無人機配備了一個連接在可移動頭部(雲台)上的高品質相機。你有一個相機控制面板,上面有"拍照"、“開始錄像”、"調整曝光"等按鈕,以及變焦旋鈕。
你還有另一個雲台控制面板,可以俯仰、平移或復位雲台位置。
在Onboard-SDK中,CameraModule和GimbalModule對象正是這些專屬控制面板。
CameraModule:代表無人機上的單個相機,提供所有相機專屬功能的控制權,例如:
- 拍照(單張、連拍、間隔拍攝)
- 錄像
- 調整曝光參數(ISO、快門速度、光圈、EV值)
- 控制變焦
- 設置對焦
GimbalModule:代表單個雲台(固定相機的機械穩定器),可精確控制相機朝向,例如:
- 旋轉相機(俯仰、橫滾、偏航)
- 將雲台復位到默認位置
為什麼需要這些模塊?
現代大疆無人機可能配備多個相機和雲台(例如主相機、熱成像相機或上視相機,各帶獨立雲台)。CameraModule和GimbalModule為每個設備提供了清晰獨立的接口。
這些模塊由兩個更高級的組件管理:
CameraManager:統管所有CameraModule實例GimbalManager:統管所有GimbalModule實例
可以把CameraManager想象成主攝影部門,GimbalManager是主攝像部門。每個部門都有隨時待命的專家(即各個CameraModule和GimbalModule對象)來執行具體指令。
第一個視覺任務:拍照並下視相機
讓我們為無人機佈置一個簡單的視覺任務:用主相機拍攝單張照片,然後將相機向下傾斜
首先確保已準備好Vehicle對象(如第一章:飛行器所示)。本示例不需要飛行控制權限,因為相機/雲台操作通常無需飛行權限(但如需邊飛行邊拍照則需獲取權限)。
#include <dji_vehicle.hpp>
#include <dji_linux_helpers.hpp>
#include <dji_camera_manager.hpp> // CameraManager
#include <dji_gimbal_manager.hpp> // GimbalManager
#include <iostream>
// ... 在主函數中 ...
LinuxSetup linuxEnvironment(argc, argv);
DJI::OSDK::Vehicle* vehicle = linuxEnvironment.getVehicle();
if (vehicle == NULL) {
std::cout << "飛行器未初始化,退出。\n";
return -1;
}
// 假設已完成激活(如第一章所示)
// DJI::OSDK::ACK::ErrorCode activateAck = vehicle->activate(...);
// ... 錯誤檢查 ...
int functionTimeout = 1; // SDK函數通用超時時間
// 主相機/雲台通常位於PAYLOAD_INDEX_0
const DJI::OSDK::PayloadIndexType mainPayloadIndex = DJI::OSDK::PAYLOAD_INDEX_0;
第一步:初始化相機和雲台模塊
使用相機或雲台前,需要通過各自的管理器初始化其模塊。這告訴SDK你要控制的具體設備。
// ... 飛行器初始化後 ...
// 從Vehicle獲取CameraManager和GimbalManager
DJI::OSDK::CameraManager* cameraManager = vehicle->cameraManager;
DJI::OSDK::GimbalManager* gimbalManager = vehicle->gimbalManager;
// 初始化主相機模塊
std::cout << "初始化主相機模塊...\n";
DJI::OSDK::ErrorCode::ErrorCodeType cameraInitRet =
cameraManager->initCameraModule(mainPayloadIndex, "MyMainCamera");
if (cameraInitRet != DJI::OSDK::ErrorCode::SysCommonErr::Success) {
std::cout << "初始化相機模塊失敗!錯誤: " << std::hex << cameraInitRet << std::endl;
return -1;
}
std::cout << "主相機模塊初始化完成。\n";
// 初始化主雲台模塊
std::cout << "初始化主雲台模塊...\n";
DJI::OSDK::ErrorCode::ErrorCodeType gimbalInitRet =
gimbalManager->initGimbalModule(mainPayloadIndex, "MyMainGimbal");
if (gimbalInitRet != DJI::OSDK::ErrorCode::SysCommonErr::Success) {
std::cout << "初始化雲台模塊失敗!錯誤: " << std::hex << gimbalInitRet << std::endl;
return -1;
}
std::cout << "主雲台模塊初始化完成。\n";
第二步:設置相機為拍照模式並拍攝單張照片
相機通常有"拍照"、"錄像"或"回放"等模式。要拍照,我們需先確保相機處於SHOOT_PHOTO模式,然後發出SINGLE拍照指令。
// ... 模塊初始化後 ...
// 設置相機工作模式為拍照
std::cout << "設置相機模式為拍照...\n";
DJI::OSDK::ErrorCode::ErrorCodeType setModeRet =
cameraManager->setModeSync(mainPayloadIndex, DJI::OSDK::CameraModule::WorkMode::SHOOT_PHOTO, functionTimeout);
if (setModeRet != DJI::OSDK::ErrorCode::SysCommonErr::Success) {
std::cout << "設置相機模式失敗!錯誤: " << std::hex << setModeRet << std::endl;
return -1;
}
std::cout << "相機模式已設為拍照。\n";
sleep(1); // 給相機切換模式的時間
// 開始拍攝單張照片
std::cout << "拍攝單張照片...\n";
DJI::OSDK::ErrorCode::ErrorCodeType shootPhotoRet =
cameraManager->startShootPhotoSync(mainPayloadIndex, DJI::OSDK::CameraModule::ShootPhotoMode::SINGLE, functionTimeout);
if (shootPhotoRet != DJI::OSDK::ErrorCode::SysCommonErr::Success) {
std::cout << "拍照失敗!錯誤: " << std::hex << shootPhotoRet << std::endl;
return -1;
}
std::cout << "照片已拍攝!請檢查無人機SD卡。\n";
sleep(2); // 給無人機處理照片的時間
第三步:旋轉雲台使相機向下
現在讓我們控制雲台使相機垂直向下。通常這是-90度的俯仰角。
內部機制:相機/雲台模塊如何通信
與其他核心SDK組件一樣,CameraManager、GimbalManager及其各自的Module對象都由Vehicle對象精心協調,並依賴底層的連接器(Linker)與無人機硬件通信。
初始化流程
從第一章:飛行器可知,Vehicle::init()是主初始化器。它會創建相機和雲台的管理器。
(層層封裝調用 架構設計)
結論
CameraModule和GimbalModule是無人機實現視覺與指向控制的專業工具
- 通過與各自的管理器交互,可以精確控制拍照、錄像、曝光參數、變焦和雲台朝向。
- 這種模塊化設計讓你能輕鬆控制特定設備,實現高級成像與檢測任務。
現在我們已經能夠控制無人機飛行及其相機,接下來讓我們探索如何獲取超越基礎遙測的高級感知能力
下一章:高級感知