久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Ardupilot四元數(shù)姿態(tài)控制函數(shù)attitude_controller_run

 netouch 2023-10-03 發(fā)布于北京

在開始閱讀本文之前,,建議可以先看一下前面幾篇博文,當然你基礎(chǔ)好直接看也是沒事的~
詳解APM的開方控制器sqrt_controller
Ardupilot傾轉(zhuǎn)分離函數(shù)thrust_heading_rotation_angles
Ardupilot前饋及平滑函數(shù)input_euler_angle_roll_pitch_yaw解析

 

源碼解析

以n系簡稱NED坐標系,,b系簡稱機體坐標系,,tb表示期望姿態(tài),cb表示當前姿態(tài),。

// 根據(jù)姿態(tài)誤差計算得出期望角速率
void AC_AttitudeControl::attitude_controller_run_quat()
{
	// 檢索四元數(shù)車輛姿態(tài)
	// 獲取到當前姿態(tài)的四元數(shù)并保存到attitude_vehicle_quat
    Quaternion attitude_vehicle_quat;
    _ahrs.get_quat_body_to_ned(attitude_vehicle_quat);

	// 計算姿態(tài)誤差
	// _attitude_target_quat:輸入?yún)?shù),,在n系下期望姿態(tài)的四元數(shù),旋轉(zhuǎn)方向tb->n
	// attitude_vehicle_quat:輸入?yún)?shù),,在n系下當前姿態(tài)的四元數(shù),,旋轉(zhuǎn)方向cb->n
	// attitude_error_vector:傳入傳出參數(shù),姿態(tài)誤差向量
	// _thrust_error_angle:傳入傳出參數(shù),,期望z軸和當前z軸的誤差(詳見軸角分離),,即推力方向上的偏差角
	// 該函數(shù)通過前兩個輸入的四元數(shù)參數(shù)計算得到各軸的姿態(tài)偏差
	// 經(jīng)過此函數(shù)后得到的參數(shù)均在b系下
    Vector3f attitude_error_vector;
    thrust_heading_rotation_angles(_attitude_target_quat, attitude_vehicle_quat, attitude_error_vector, _thrust_error_angle);

	// P控制器,輸入為姿態(tài)誤差,,輸出為期望角速率
	// 函數(shù)內(nèi)部根據(jù)是否開啟了sqrt_controller來區(qū)分計算各通道的期望角速率_rate_target_ang_vel
	// 是,,則使用開方調(diào)整過的P控制器
	// 否,則使用常規(guī)的Kp*error
    _rate_target_ang_vel = update_ang_vel_target_from_att_error(attitude_error_vector);

	// 對P控制器輸出疊加前饋項,嘗試確保側(cè)傾和俯仰誤差隨車身框架而不是參考框架旋轉(zhuǎn)
	// x軸的前饋項 = y軸的姿態(tài)誤差(限幅后的)*陀螺儀獲取的z軸角速度
	// y軸的前饋項 = x軸的姿態(tài)誤差(限幅后的)*陀螺儀獲取的z軸角速度
	// 注意此處并沒有對z軸的期望角速率進行處理
    // todo: this should probably be a matrix that couples yaw as well.
    _rate_target_ang_vel.x += constrain_float(attitude_error_vector.y, -M_PI / 4, M_PI / 4) * _ahrs.get_gyro().z;
    _rate_target_ang_vel.y += -constrain_float(attitude_error_vector.x, -M_PI / 4, M_PI / 4) * _ahrs.get_gyro().z;

	// 期望角速率限幅
    ang_vel_limit(_rate_target_ang_vel, radians(_ang_vel_roll_max), radians(_ang_vel_pitch_max), radians(_ang_vel_yaw_max));

	// 角速度前饋旋轉(zhuǎn)到機體坐標中(對該處有疑問的詳見本文后面)
	// _attitude_target_ang_vel是一個全局變量,,表示期望姿態(tài)的期望角速率,,是由input_euler_angle_roll_pitch_yaw等類似函數(shù)獲取到的前饋速率
	// attitude_target_ang_vel_quat在此處表明是一個向量[0,v]
	Quaternion attitude_target_ang_vel_quat = Quaternion(0.0f, _attitude_target_ang_vel.x, _attitude_target_ang_vel.y, _attitude_target_ang_vel.z);
	// 運算過程注意四元數(shù)和旋轉(zhuǎn)矩陣一樣是可以上下標相互約去的,此處以Q(a)(b)形式表明上標為a,,下標為b,,表示b向a的旋轉(zhuǎn)過程
	// attitude_vehicle_quat前面說過是表示cb->n旋轉(zhuǎn)的單位四元數(shù),求逆后表示n->cb
	// to_to_from_quat = Q(cb)(n)*Q(n)(tb)=Q(cb)(tb)
	// 表明獲取的四元數(shù)to_to_from_quat表示tb->cb的旋轉(zhuǎn),,計算公式也可視作期望姿態(tài)與當前姿態(tài)的作差
	Quaternion to_to_from_quat = attitude_vehicle_quat.inverse() * _attitude_target_quat;
	// 將tb下的期望角速率旋轉(zhuǎn)至cb下獲取當前姿態(tài)的角速率期望前饋疊加量desired_ang_vel_quat
    Quaternion desired_ang_vel_quat = to_to_from_quat.inverse() * attitude_target_ang_vel_quat * to_to_from_quat;

	// 校正推力矢量并平穩(wěn)添加前饋和偏航輸入
	// 下述過程根據(jù)推力角誤差大小分配在Z軸YAW角上的數(shù)學(xué)計算結(jié)果和傳感器測量值之間的確信度來確定Z軸的期望角速度
	// 同時將前饋控制量添加到各軸
	// 當推力角誤差特別大的時候,,表明計算出來的期望值不可信,,此時z軸期望角速度取陀螺儀測量值
    if (_thrust_error_angle > AC_ATTITUDE_THRUST_ERROR_ANGLE * 2.0f) {
        _rate_target_ang_vel.z = _ahrs.get_gyro().z;
	} else if (_thrust_error_angle > AC_ATTITUDE_THRUST_ERROR_ANGLE) {
		// 當推力角誤差較大時,,根據(jù)之前計算出來的推力角誤差_thrust_error_angle計算出前饋因子
		// 對各軸的旋轉(zhuǎn)角速度各自疊加前饋控制量
        float feedforward_scalar = (1.0f - (_thrust_error_angle - AC_ATTITUDE_THRUST_ERROR_ANGLE) / AC_ATTITUDE_THRUST_ERROR_ANGLE);
        _rate_target_ang_vel.x += desired_ang_vel_quat.q2 * feedforward_scalar;
        _rate_target_ang_vel.y += desired_ang_vel_quat.q3 * feedforward_scalar;
        _rate_target_ang_vel.z += desired_ang_vel_quat.q4;
		// 校正推力矢量,feedforward_scalar表示對計算出的數(shù)學(xué)結(jié)果的確信度,,(1- feedforward_scalar)則表示對陀螺儀測得的角速度的確信度
		// 兩者綜合得到最后的期望角速率
        _rate_target_ang_vel.z = _ahrs.get_gyro().z * (1.0 - feedforward_scalar) + _rate_target_ang_vel.z * feedforward_scalar;
	} else {
		// 推力角誤差較小時,,表明當前數(shù)學(xué)計算得到的期望角速率可信度較高,直接進行前饋疊加
        _rate_target_ang_vel.x += desired_ang_vel_quat.q2;
        _rate_target_ang_vel.y += desired_ang_vel_quat.q3;
        _rate_target_ang_vel.z += desired_ang_vel_quat.q4;
    }

    if (_rate_bf_ff_enabled) {
        // 當開啟機體速率前饋時,,實時計算更新期望姿態(tài)四元數(shù),,每一次更新都需要將其單位化
        Quaternion attitude_target_update_quat;
        attitude_target_update_quat.from_axis_angle(Vector3f(_attitude_target_ang_vel.x * _dt, _attitude_target_ang_vel.y * _dt, _attitude_target_ang_vel.z * _dt));
        _attitude_target_quat = _attitude_target_quat * attitude_target_update_quat;
        _attitude_target_quat.normalize();
    }

    // 確保四元數(shù)已經(jīng)被單位化
    _attitude_target_quat.normalize();

	// 記錄姿態(tài)誤差以處理EKF重置
	// 等式相當于將_attitude_target_quat表示的期望姿態(tài)減去attitude_vehicle_quat表示的當前姿態(tài)
    _attitude_ang_error = attitude_vehicle_quat.inverse() * _attitude_target_quat;
}

總結(jié):attitude_controller_run_quat()函數(shù)在內(nèi)部通過調(diào)用thrust_heading_rotation_angles()函數(shù)計算出姿態(tài)誤差,然后根據(jù)姿態(tài)誤差調(diào)用了P控制器得到期望角速率,,并進行了前饋疊加及平滑操作,。

 

細節(jié)講解

thrust_heading_rotation_angles()

這個函數(shù)主要的作用就是根據(jù)輸入的期望姿態(tài)和當前姿態(tài)計算出姿態(tài)誤差,詳細介紹請看我之前的博文:Ardupilot傾轉(zhuǎn)分離函數(shù)thrust_heading_rotation_angles

update_ang_vel_target_from_att_error()

這個函數(shù)內(nèi)部代碼比較簡單,,但是還是說一下,。

主要就是P控制器的作用,將輸入的姿態(tài)誤差處理之后轉(zhuǎn)換為期望角速率輸出,。

可以很清楚看到內(nèi)部會根據(jù)是否啟用_use_sqrt_controller來進行不同的處理,,如果_use_sqrt_controller = 1,那么會調(diào)用整定后的P控制器sqrt_controller進行計算,;而如果_use_sqrt_controller = 0,,那么就會按照傳統(tǒng)計算方式 Kp*error 進行計算。

關(guān)于sqrt_controller詳見:詳解APM的開方控制器sqrt_controller

// Update rate_target_ang_vel using attitude_error_rot_vec_rad
Vector3f AC_AttitudeControl::update_ang_vel_target_from_att_error(const Vector3f &attitude_error_rot_vec_rad)
{
    Vector3f rate_target_ang_vel;
    // Compute the roll angular velocity demand from the roll angle error
    if (_use_sqrt_controller) {
        rate_target_ang_vel.x = sqrt_controller(attitude_error_rot_vec_rad.x, _p_angle_roll.kP(), constrain_float(get_accel_roll_max_radss() / 2.0f, AC_ATTITUDE_ACCEL_RP_CONTROLLER_MIN_RADSS, AC_ATTITUDE_ACCEL_RP_CONTROLLER_MAX_RADSS), _dt);
    } else {
        rate_target_ang_vel.x = _p_angle_roll.kP() * attitude_error_rot_vec_rad.x;
    }
    // todo: Add Angular Velocity Limit

    // Compute the pitch angular velocity demand from the pitch angle error
    if (_use_sqrt_controller) {
        rate_target_ang_vel.y = sqrt_controller(attitude_error_rot_vec_rad.y, _p_angle_pitch.kP(), constrain_float(get_accel_pitch_max_radss() / 2.0f, AC_ATTITUDE_ACCEL_RP_CONTROLLER_MIN_RADSS, AC_ATTITUDE_ACCEL_RP_CONTROLLER_MAX_RADSS), _dt);
    } else {
        rate_target_ang_vel.y = _p_angle_pitch.kP() * attitude_error_rot_vec_rad.y;
    }
    // todo: Add Angular Velocity Limit

    // Compute the yaw angular velocity demand from the yaw angle error
    if (_use_sqrt_controller) {
        rate_target_ang_vel.z = sqrt_controller(attitude_error_rot_vec_rad.z, _p_angle_yaw.kP(), constrain_float(get_accel_yaw_max_radss() / 2.0f, AC_ATTITUDE_ACCEL_Y_CONTROLLER_MIN_RADSS, AC_ATTITUDE_ACCEL_Y_CONTROLLER_MAX_RADSS), _dt);
    } else {
        rate_target_ang_vel.z = _p_angle_yaw.kP() * attitude_error_rot_vec_rad.z;
    }
    // todo: Add Angular Velocity Limit
    return rate_target_ang_vel;
}

角度前饋量旋轉(zhuǎn)解釋

有人可能會對這段代碼的旋轉(zhuǎn)過程有所疑惑,,然而實際上在我上一篇博文(Ardupilot前饋及平滑函數(shù)input_euler_angle_roll_pitch_yaw解析)已經(jīng)對這個問題進行了解釋,,這邊再細說一下。

	// 角速度前饋旋轉(zhuǎn)到機體坐標中(對該處有疑問的詳見本文后面)
	// _attitude_target_ang_vel是一個全局變量,,表示期望姿態(tài)的期望角速率,,是由input_euler_angle_roll_pitch_yaw等類似函數(shù)獲取到的前饋速率
	// attitude_target_ang_vel_quat在此處表明是一個向量[0,v]
	Quaternion attitude_target_ang_vel_quat = Quaternion(0.0f, _attitude_target_ang_vel.x, _attitude_target_ang_vel.y, _attitude_target_ang_vel.z);
	// 運算過程注意四元數(shù)和旋轉(zhuǎn)矩陣一樣是可以上下標相互約去的,此處以Q(a)(b)形式表明上標為a,,下標為b,,表示b向a的旋轉(zhuǎn)過程
	// attitude_vehicle_quat前面說過是表示cb->n旋轉(zhuǎn)的單位四元數(shù),求逆后表示n->cb
	// to_to_from_quat = Q(cb)(n)*Q(n)(tb)=Q(cb)(tb)
	// 表明獲取的四元數(shù)to_to_from_quat表示tb->cb的旋轉(zhuǎn),計算公式也可視作期望姿態(tài)與當前姿態(tài)的作差
	Quaternion to_to_from_quat = attitude_vehicle_quat.inverse() * _attitude_target_quat;
	// 將tb下的期望角速率旋轉(zhuǎn)至cb下獲取當前姿態(tài)的角速率期望前饋疊加量desired_ang_vel_quat
    Quaternion desired_ang_vel_quat = to_to_from_quat.inverse() * attitude_target_ang_vel_quat * to_to_from_quat;

可以看到這段代碼將前饋期望速度從期望姿態(tài)轉(zhuǎn)換到了當前姿態(tài)下,,那么問題就是,,為什么這個期望速度是在期望姿態(tài)下而不是原本就在當前姿態(tài)的呢?

因為在之前的input_euler_angle_roll_pitch_yaw()函數(shù)(其他類似)中,,通過對本次輸入的期望姿態(tài)和自駕儀中當前保存的未更新前的期望姿態(tài)作差求出姿態(tài)誤差,,然后再得到了_attitude_target_ang_vel這個期望角速率。

而在現(xiàn)在我們這個函數(shù)中,,我們是通過期望姿態(tài)與當前姿態(tài)作差得到的姿態(tài)誤差來求取期望角速率_rate_target_ang_vel,。

因此_attitude_target_ang_vel是在期望姿態(tài)tb下的期望角速率,而_rate_target_ang_vel則是在當前姿態(tài)cb下的期望角速率,,疊加前需要將_attitude_target_ang_vel從tb轉(zhuǎn)換到cb下,。

姿態(tài)更新部分

    if (_rate_bf_ff_enabled) {
        // 當開啟機體速率前饋時,實時計算更新期望姿態(tài)四元數(shù),,每一次更新都需要將其單位化
        Quaternion attitude_target_update_quat;
        attitude_target_update_quat.from_axis_angle(Vector3f(_attitude_target_ang_vel.x * _dt, _attitude_target_ang_vel.y * _dt, _attitude_target_ang_vel.z * _dt));
        _attitude_target_quat = _attitude_target_quat * attitude_target_update_quat;
        _attitude_target_quat.normalize();
    }

該部分仍然跟之前講解的input_euler_angle_roll_pitch_yaw()及類似函數(shù)有關(guān),,在input_euler_angle_roll_pitch_yaw()中如果開啟了前饋,那么會計算出前饋速率,,但是并沒有將本次輸入的期望姿態(tài)更新到當前保存的期望姿態(tài)中,;而如果沒有開啟前饋,則會將本次輸入的期望姿態(tài)更新到當前期望姿態(tài),,然后將前饋速率置0,。

因此,此處解決了我們之前說過的如果開啟前饋,,姿態(tài)更新將在attitude_controller_run_quat()中更新的疑惑,。

 

參考資料:

如何用四元數(shù)表示反向旋轉(zhuǎn),類似于旋轉(zhuǎn)矩陣的轉(zhuǎn)置表示反向旋轉(zhuǎn),?

[飛控]姿態(tài)誤差(三)-四元數(shù)和軸角求誤差

 

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,謹防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多