PX4 中fw_att_control程序解讀

應用程序的入口,“extern "C" __EXPORT int fw_att_control_main(int argc, char *argv[])”,在這個函數裏就實現了,這個程序是否已近啓動,如果沒有啓動就會註冊函數來啓動。

聲明FixedwingAttitudeControl是主函數

int fw_att_control_main(int argc, char *argv[])
{
    return FixedwingAttitudeControl::main(argc, argv);
}

一,剛開始就是一些初始化設置和消息訂閱

FixedwingAttitudeControl::FixedwingAttitudeControl() :

導入參數

_parameter_handles.XXXX=param_find("XXXX")

消息的訂閱:

    _att_sub = orb_subscribe(ORB_ID(vehicle_attitude));//姿態
    _att_sp_sub = orb_subscribe(ORB_ID(vehicle_attitude_setpoint));//姿態設定點
    _vcontrol_mode_sub = orb_subscribe(ORB_ID(vehicle_control_mode));//控制模式
    _params_sub = orb_subscribe(ORB_ID(parameter_update));//參數更新
    _manual_sub = orb_subscribe(ORB_ID(manual_control_setpoint));//手動控制的設定
    _global_pos_sub = orb_subscribe(ORB_ID(vehicle_global_position));//車輛全球位置
    _vehicle_status_sub = orb_subscribe(ORB_ID(vehicle_status));//飛機狀態
    _vehicle_land_detected_sub = orb_subscribe(ORB_ID(vehicle_land_detected));//着陸深測
    _battery_status_sub = orb_subscribe(ORB_ID(battery_status));//電池模式
    _rates_sp_sub = orb_subscribe(ORB_ID(vehicle_rates_setpoint));//速度設定

聲明瞭取消訂閱的方法

FixedwingAttitudeControl::~FixedwingAttitudeControl()//取消訂閱

參數更新:

FixedwingAttitudeControl::parameters_update()

 二.接下來就是以check的方式獲取訂閱消息的值:

FixedwingAttitudeControl::vehicle_control_mode_poll()//控制模式判定
FixedwingAttitudeControl::vehicle_manual_poll()//彈體手動判定
FixedwingAttitudeControl::vehicle_attitude_setpoint_poll()//彈體姿態設定判定
FixedwingAttitudeControl::vehicle_rates_setpoint_poll()//彈體速度設定判定
FixedwingAttitudeControl::global_pos_poll()//彈體位置設定判定
FixedwingAttitudeControl::vehicle_status_poll()//彈體狀態設置判定
FixedwingAttitudeControl::vehicle_land_detected_poll()//彈體着陸狀態判定
FixedwingAttitudeControl::get_airspeed_and_scaling// 更新空速

 //獲取所有傳感器和狀態數據的初始更新
    //_poll()函數是輪詢,內部的代碼是檢測是否更新,若更新了數據,就copy

orb_check(_vehicle_xxxx_sub, &vehicle_xxxx_updated)

然後if判定vehicle_xxxx_updated真僞

以阻塞等待方式檢查參數是否更新,以及當前的飛機狀態。阻塞等待這種獲取訂閱消息的方式

三.姿態控制

FixedwingAttitudeControl::run()

fds[0.fd]爲輪詢的姿態數據,其events是爲了檢測姿態是否發生改變

* wakeup source */

    px4_pollfd_struct_t fds[1];

    /* Setup of loop */

    fds[0].fd = _att_sub;

    fds[0].events = POLLIN;//fds[0.fd]爲

 

這個if函數就是姿態控制運行的開始,如果姿態發生了改變,就運行這個if:

/* only run controller if attitude changed只有在姿態改變時才運行控制器 */
if (fds[0].revents & POLLIN) {
			
  1. 那麼要知道姿態是否發生改變,那麼就需要知道當前的姿態,這通過獲取當前姿態的消息,然後得到四元數,轉化爲旋轉矩陣,進而求得姿態角:
orb_copy(ORB_ID(vehicle_attitude), _att_sub, &_att);

/* get current rotation matrix and euler angles from control state quaternions
			
matrix::Dcmf R = matrix::Quatf(_att.q);

if (_vehicle_status.is_vtol && _parameters.vtol_type == vtol_type::TAILSITTER) {
				
	matrix::Dcmf R_adapted = R;		//modified rotation matrix修正旋轉矩陣

	/* move z to x */
	R_adapted(0, 0) = R(0, 2);
	R_adapted(1, 0) = R(1, 2);
	R_adapted(2, 0) = R(2, 2);

        /* move x to z */
	R_adapted(0, 2) = R(0, 0);
        R_adapted(1, 2) = R(1, 0);
	R_adapted(2, 2) = R(2, 0);

	/* change direction of pitch (convert to right handed system) */
	R_adapted(0, 0) = -R_adapted(0, 0);
	R_adapted(1, 0) = -R_adapted(1, 0);
	R_adapted(2, 0) = -R_adapted(2, 0);

	/* fill in new attitude data */
	R = R_adapted;

	/* lastly, roll- and yawspeed have to be swaped */
	float helper = _att.rollspeed;
	_att.rollspeed = -_att.yawspeed;
	_att.yawspeed = helper;
			}

	matrix::Eulerf euler_angles(R);//矩陣:歐拉-歐拉角(r);

2.由於姿態控制算法在一些模式下面是不會估算姿態設定點的,所以要確認這些標誌。

_att_sp.fw_control_yaw = _att_sp.fw_control_yaw && _vcontrol_mode.flag_control_auto_enabled;//判斷垂尾,用於自主起飛。

3./* lock integrator until control is started 鎖定積分器直到控制啓動*/

bool lock_integrator = !(_vcontrol_mode.flag_control_rates_enabled && !_vehicle_status.is_rotary_wing);

4./故障保護的簡單處理:如果故障保護開啓,則展開降落傘。*/

5.接下來是襟翼的設定,

control_flaps(deltaT)

在姿態運行的開始已經聲明瞭float deltaT = (hrt_absolute_time() - last_run) / 1000000.0f; 當前時間減去上次運行的時間

 if (deltaT > 1.0f) {//防止太大增量

deltaT = 0.01f;

}

襟翼分爲手動控制和自動控制


	/* default flaps to center 默認襟翼到中心*/
	float flap_control = 0.0f;

	/* map flaps by default to manual if valid 如果有效,默認地圖襟翼爲手動*/
	if (PX4_ISFINITE(_manual.flaps) && _vcontrol_mode.flag_control_manual_enabled
	    && fabsf(_parameters.flaps_scale) > 0.01f) {
		flap_control = 0.5f * (_manual.flaps + 1.0f) * _parameters.flaps_scale;

	} else if (_vcontrol_mode.flag_control_auto_enabled
		   && fabsf(_parameters.flaps_scale) > 0.01f) {
		switch (_att_sp.apply_flaps) {
		case vehicle_attitude_setpoint_s::FLAPS_OFF : flap_control = 0.0f; // no flaps無襟翼 
			break;

		case vehicle_attitude_setpoint_s::FLAPS_LAND : flap_control = 1.0f * _parameters.flaps_scale *
					_parameters.flaps_land_scale; // 着陸襟翼landing flaps
			break;

		case vehicle_attitude_setpoint_s::FLAPS_TAKEOFF : flap_control = 1.0f * _parameters.flaps_scale *
					_parameters.flaps_takeoff_scale; // take-off flaps起飛襟翼
			break;
		}
	}
       // move the actual control value continuous with time, full flap travel in 1sec隨時間連續移動實際控制值,1秒內全襟翼行程
	if (fabsf(_flaps_applied - flap_control) > 0.01f) {
		_flaps_applied += (_flaps_applied - flap_control) < 0 ? dt : -dt;

	} else {
		_flaps_applied = flap_control;
	}

接着襟副翼的設定

        /* default flaperon to center 默認襟副翼到中心*/
	float flaperon_control = 0.0f;
       /* map flaperons by default to manual if valid 如果有效,默認將Flaperons映射爲手動*/
	if (PX4_ISFINITE(_manual.aux2) && _vcontrol_mode.flag_control_manual_enabled
	    && fabsf(_parameters.flaperon_scale) > 0.01f) {
		flaperon_control = 0.5f * (_manual.aux2 + 1.0f) * _parameters.flaperon_scale;

	} else if (_vcontrol_mode.flag_control_auto_enabled
		   && fabsf(_parameters.flaperon_scale) > 0.01f) {
		flaperon_control = (_att_sp.apply_flaps == vehicle_attitude_setpoint_s::FLAPS_LAND) ? 1.0f *
				   _parameters.flaperon_scale : 0.0f;
	}

	// move the actual control value continuous with time, full flap travel in 1sec
	//隨時間連續移動實際控制值,1秒內全襟翼行程
	if (fabsf(_flaperons_applied - flaperon_control) > 0.01f) {
		_flaperons_applied += (_flaperons_applied - flaperon_control) < 0 ? dt : -dt;

	} else {
		_flaperons_applied = flaperon_control;
	}

6.決定姿態是自穩還是完全手動控制

if (_vcontrol_mode.flag_control_rates_enabled) {

在這個if語句裏面執行的主要有判斷空速是否有效,如果無效設定空速爲參數設定,如果有效設定空速爲測量或者計算的空速。

通過vehicle_global_position來計算飛機的地面速度。

如果自穩模式下面,我們需要通過遙控器來產生姿態設定點;

計算機體座標系下飛機的速度;

如果飛機在地面或是多旋翼飛機(但不轉換vtol),重置積分器。

旋轉矩陣進而求得姿態角 */;

struct ECL_ControlData control_input = {};

準備姿態控制器運行需要的參數:

        control_input.roll = euler_angles.phi();
	control_input.pitch = euler_angles.theta();
	control_input.yaw = euler_angles.psi();
	control_input.body_x_rate = _att.rollspeed;
	control_input.body_y_rate = _att.pitchspeed;
	control_input.body_z_rate = _att.yawspeed;
	control_input.roll_setpoint = _att_sp.roll_body;
	control_input.pitch_setpoint = _att_sp.pitch_body;
	control_input.yaw_setpoint = _att_sp.yaw_body;
	control_input.airspeed_min = _parameters.airspeed_min;
	control_input.airspeed_max = _parameters.airspeed_max;
	control_input.airspeed = airspeed;
	control_input.scaler = airspeed_scaling;
	control_input.lock_integrator = lock_integrator;
	control_input.groundspeed = groundspeed;
	control_input.groundspeed_scaler = groundspeed_scaler;

reset body angular rate limits on mode change重置模式更改時的車身角速率限制

Run attitude controllers 運行姿態控制器*/

if (_vcontrol_mode.flag_control_attitude_enabled) {

 前面的判斷就是爲運行姿態控制器所準備的。

_roll_ctrl.control_attitude(control_input);
_pitch_ctrl.control_attitude(control_input);
_yaw_ctrl.control_attitude(control_input); //runs last, because is depending on output of roll and pitch attitude
_wheel_ctrl.control_attitude(control_input);

上面的代碼計算目標與當前姿態的角度誤差值,對於roll和pitch是計算角度誤差,然後算出角速率,對於yaw速率的計算是,假設在沒有側向力的情況下,通過計算可以得到相應的yaw速率

更新速率控制器的輸入數據

control_input.roll_rate_setpoint = _roll_ctrl.get_desired_rate();
control_input.pitch_rate_setpoint = _pitch_ctrl.get_desired_rate();
control_input.yaw_rate_setpoint = _yaw_ctrl.get_desired_rate();

           //運行姿態率控制器,需要從上面獲得所需姿態,增加配平

            手動模式下的附加手動方向舵控制

如果節氣門有限且未檢測到發動機故障,則節氣門通過

按電池狀態縮放作用力

延遲發佈速率設定值(分析時,執行器發佈如下)

* 只有一次可用

從橫搖控制輸出到橫擺控制輸出添加前饋

這可以用來抵消飛機滾動時的不利偏航效應。

actuators.control[actuator_controls_s::INDEX_YAW] += _parameters.roll_to_yaw_ff * math::constrain(
						_actuators.control[actuator_controls_s::INDEX_ROLL], -1.0f, 1.0f);

整個姿態控制流程主要這些,具體的算法還要繼續研究

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章