PX4-7-飛控參數
參數是PX4飛控中掉電保存的變量,用于存儲飛控的設置、校準系數等數據。
PX4有一套完善的參數框架,對于用戶而言只需要非常簡單的幾個語句就可以完成參數的添加、讀取和寫入操作。
這一篇我們簡單聊一下PX4的參數機制,這部分內容不是所有同學都會用的到,不過有一個框架性的認識對于熟悉PX4的框架也有一定的幫助。
我們以1.11.3版本為例,簡單的描述一下PX4的參數操作流程:
代碼構建
在編譯構建時PX4執行src/lib/parameters/CMakeLists.txt 中腳本文件 px_process_params.py ,這個腳本會歷遍所有的源碼目錄,找到xxx_params.c文件,根據這個文件生成parameters.xml文件。這個文件自動創建在build/xxx/parameters.xml中。
然后執行 px_generate_params.py 腳本,根據parameters.xml文件生成參數頭文件和c文件,生成的文件在build/xxx/src/lib/parameters目錄下。
稍微閱讀這幾個文件,里面主要定義了所有參數的名稱、數據類型和默認值。
載入參數文件
在PX4啟動腳本(ROMFS/px4fmu_common/init.d/rcS)中執行參數載入操作從存儲器中讀取參數
# Set the parameter file if mtd starts successfully.
if mtd start
then
set PARAM_FILE /fs/mtd_params
fi
# Load parameters.
param select $PARAM_FILE
if ! param load
then
param reset
fi
加載參數文件后,會更新build/xxx/src/lib/parameters/px4_parameters.c文件在中px4_parameters結構體的數據,這就是PX4所有參數的參數表了,在文件尾部顯示了參數總數,有近千個參數。
應用加載參數
應用中使用參數比較簡單,添加幾條語句就可以,我們以代碼比較簡單的src/drivers/heater/heater.cpp模塊為例。
參數變量定義
在頭文件中通過參數宏結構進行參數變量的定義
DEFINE_PARAMETERS(
(ParamFloat<px4::params::SENS_IMU_TEMP_I>) _param_sens_imu_temp_i,
(ParamFloat<px4::params::SENS_IMU_TEMP_P>) _param_sens_imu_temp_p,
(ParamInt<px4::params::SENS_TEMP_ID>) _param_sens_temp_id,
(ParamFloat<px4::params::SENS_IMU_TEMP>) _param_sens_imu_temp
)更新參數
在源文件中添加變量更新函數,檢測變量是否發生變化,更新變量
void Heater::update_params(const bool force)
{
// check for parameter updates
if (_parameter_update_sub.updated() || force) {
// clear update
parameter_update_s pupdate;
_parameter_update_sub.copy(&pupdate);
// update parameters from storage
ModuleParams::updateParams();
}
}
應用加載與更新參數的機制
在應用的頭文件中,通過 DEFINE_PARAMETERS 宏完成參數變量類的定義,我們可以看一下這個宏的內容:
#define _DEFINE_SINGLE_PARAMETER(x) \
do_not_explicitly_use_this_namespace::PAIR(x);
#define _CALL_UPDATE(x) \
STRIP(x).update();
#define _DEFINE_PARAMETER_UPDATE_METHOD(...) \
protected: \
void updateParamsImpl() final { \
APPLY_ALL(_CALL_UPDATE, __VA_ARGS__) \
} \
private:
#define DEFINE_PARAMETERS(...) \
APPLY_ALL(_DEFINE_SINGLE_PARAMETER, __VA_ARGS__) \
_DEFINE_PARAMETER_UPDATE_METHOD(__VA_ARGS__)
從內容我們可以大致了解,這里使用命名空間 do_not_explicitly_use_this_namespace中參數類定義參數變量,并且定義了應用中所有參數的更新類updateParamsImpl,這個函數在上一部分的ModuleParams::updateParams()中調用,里面的實現為
class ModuleParams
{
virtual void updateParams()
{
for (const auto &child : _children) {
child->updateParams();
}
updateParamsImpl();
}
}
在參數更新時,使用STRIP(x).update() 方法更新應用中每個使用到的參數,這個方法定義在do_not_explicitly_use_this_namespace中:
bool update()
{
int32_t value_int;
int ret = param_get(handle(), &value_int);
if (ret == 0) {
_val = value_int != 0;
return true;
}
return false;
}
這些宏定義中值得注意的是APPLY_ALL()方法,這個宏定義使代碼中展開復雜的結構,為應用的頭文件中定義的所有變量展開變量定義和update()方法,其目的是使代碼更加簡潔。
這樣的宏定義方式大家感興趣也可以參考一下,減少重復性代碼可以使自己的代碼結構更加簡潔清晰。
參數更新消息
可以發現PX4使用了uORB機制向所有使用參數的應用廣播參數的變化,每個使用參數的應用都會訂閱 uORB::Subscription _parameter_update_sub{ORB_ID(parameter_update)}; 消息。在檢測到參數更新時去更新應用使用到的參數值。
這樣的設計有好處是處理方式統一,結構簡潔。
當然它的代價是在一個參數發生更新時,所有的應用都會收到更新通知去檢查更新自己使用的參數。
總結
以上是PX4的參數系統的大致機制,當然還有很多非常有意思的細節信息沒有展開。這些信息對于使用而言沒有作用不大,對于希望磨礪自己代碼能力的同學卻是不錯的參考,里面使用到的宏定義、模板類、代碼生成等等都是不錯的學習參考。
源自: AcmeUavs
工程師必備
- 項目客服
- 培訓客服
- 平臺客服
TOP




















