我們還是先來瀏覽一下比賽規則:

無人機的高階狀態機

無人機的高階狀態機

無人機的高階狀態機

無人機的高階狀態機

無人機的高階狀態機

無人機的高階狀態機

1、規劃問題初步方案

1.1、數量配置

初步確定數量配置為:旋翼飛機數量為1架,固定翼飛機為9架。旋翼飛機的作用為搜尋目標、毀傷評估、引導固定翼飛機及補充打擊,固定翼飛機的作用為搜尋靶標位置及打擊目標。

1.2、邏輯流程

無人機的高階狀態機

旋翼飛機在引導固定翼飛機實行打擊時,首先需要解算出目標相對於世界座標系的位置,然後將位置資訊和起飛訊號傳遞給固定翼無人機,固定翼無人機按照給定航跡飛行並擊打目標,隨後返回起飛區。

2、系統框架

(PS:非常感謝師弟堅持要摒棄if-else的低階狀態機,所以我們才能開發出這套邏輯更加嚴密,使用更加方便的高階狀態機)

參考文獻:

【1】狀態機程式設計

【2】將ros變數寫入類中

簡單介紹一下程式碼中類名及主要成員作用:

MainFlight--飛機類,即被控制的物件

資料成員:

全部ros 變數(包括DJIDrone*、NodeHandle、Publisher及Subscriber等),定義在類內,但在建構函式中進行初始化。

六個抽象基類指標,分別對應六個狀態派生類(重點:定義資料成員時要定義為基類指標,但在建構函式中初始化為派生類指標,以此與六個狀態派生類繫結),目的是使一個飛機類的物件同時擁有六種狀態,並從中切換。

recent_state——飛機當前狀態,recent_state指標所對應的狀態派生類即為飛機當前指標,之後透過給recent_state賦值實現狀態切換。

成員函式(方法):

最重要的是setState函式,接受一個新狀態的指標,並賦值給recent_state,然後執行一次派生類狀態對應的excute 函式。除此之外,還有一些介面函式,用於能使外界訪問飛機類中的資料成員(主要是ros變數和大疆DJIDrone)

此外如果以後還用這種框架的話,MainFlight 的建構函式和解構函式很重要,建構函式中要將六個基類指標初始化賦值為六個派生狀態類指標,以及將六個指標都和飛機類的物件繫結,因為切換狀態是在excute函式中進行,此函式是狀態類的成員函式,因此我們在此函式中無法直接訪問到飛機類物件的recent_state成員,因此需要在狀態類中儲存一個指向飛機類的指標my_mainflight,此時就可以在狀態類的函式中透過my_mainflight呼叫飛機類的setState方法來修改飛機類物件recent_state的值達到切換狀態的目的,這也是這個狀態機框架最重要的一點。

StateBase--狀態基類(抽象基類,不可例項化為物件)

資料成員:

只有一個數據成員:my_mainflight,是一個指向飛機類物件的指標,用法上文中已經詳細說明。

成員函式:

set_MainFlight,用於在飛機類的建構函式中將每個狀態類指標與飛機物件繫結。

純虛擬函式:excute,執行函式,將在每個派生類中進行覆蓋以實現不同狀態的執行不同的動作。

StateBase 的派生類,共6個,分別為TakeoffState(起飛)、SearchState(搜尋)、watchTFState(識別TF)、sendState(發指令給僚機)、GoHomeState(回家)、LandingState(降落)

資料成員直接從基類中繼承,沒有多加其他資料成員。

成員函式:excute,各個狀態不同的執行函式,也就是原來狀態機中每個case 中的內容。

如需修改狀態:修改每個狀態類中的excute 函式,狀態切換邏輯不受影響;同樣,修改狀態切換邏輯,執行動作不受影響。

如需新增或刪除狀態直接照著已有派生類的樣式寫類的定義即可,不需做什麼修改,只需重寫此類的excute 函式即可。

3、程式碼

(PS:為了簡單說明,我將程式碼中很多變數的定義都刪除了,大家只要能看懂整個框架就好~)

3.1、main.cpp

#include

#include

“。。/include/Drone。h”

#include

using

namespace

std

int

main

int

argc

char

**

argv

{

ros

::

init

argc

argv

“StateMachineNode”

);

double

KP

=

atof

argv

1

]);

double

height

=

atof

argv

2

]);

double

leader_x_avoid

=

atof

argv

3

]);

double

leader_y_avoid

=

atof

argv

4

]);

double

leader_x_avoid2

=

atof

argv

5

]);

double

leader_y_avoid2

=

atof

argv

6

]);

auto

M100

=

new

Drone

KP

height

leader_x_avoid

leader_y_avoid

leader_x_avoid2

leader_y_avoid2

);

M100

->

getDrone

())

->

request_sdk_permission_control

();

cout

<<

“Ctrl State = ”

<<

M100

->

getDrone

()

->

request_sdk_permission_control

()

<<

endl

cout

<<

“Mission Start”

<<

endl

M100

->

mission

();

cout

<<

“Mission Success!,release control。。。”

<<

endl

M100

->

getDrone

())

->

release_sdk_permission_control

();

return

0

}

3.2、Drone.h

#ifndef DRONE_H

#define DRONE_H

#include

“。。/include/State。h”

#include

“。。/include/Function。h”

#include

#include

using

namespace

std

class

StateBase

class

Drone

{

public

Drone

double

K

double

H

double

Leader_x_Avoid

double

Leader_y_Avoid

double

Leader_x_Avoid2

double

Leader_y_Avoid2

);

~

Drone

();

//switch state and do acions

void

setState

StateBase

*

new_state

);

//Flight logic for mission

void

mission

();

//all states that a drone has

StateBase

*

takeoff_state

StateBase

*

search_state

StateBase

*

watchTF_state

StateBase

*

send_state

StateBase

*

gohome_state

StateBase

*

landing_state

//access to private member variable

DJIDrone

*

getDrone

();

//flight parameters

double

K_track

double

height

double

leader_x_Avoid

double

leader_y_Avoid

double

leader_x_Avoid2

double

leader_y_Avoid2

//ROS variable

ros

::

NodeHandle

n

ros

::

Publisher

tkpub

ros

::

Publisher

goonpub

ros

::

Publisher

UAV1_position_pub

private

//save recent state

StateBase

*

recent_state

=

nullptr

//DJIDrone variable

DJIDrone

*

drone

ros

::

Subscriber

message_subscriber

};

#endif

// DRONE_H

3.3、State.h

#ifndef STATES_H

#define STATES_H

#include

“。。/include/Drone。h”

#include

“。。/include/Function。h”

#include

#include

“。。/。。/Guidance-SDK-ROS/include/DJI_guidance。h”

class

Drone

class

StateBase

{

public

virtual

~

StateBase

()

{}

virtual

void

excute

Drone

*

=

0

void

setDrone

Drone

*

new_drone

);

protected

Drone

*

recent_drone

};

class

TakeoffState

public

StateBase

{

public

TakeoffState

();

~

TakeoffState

()

=

default

void

excute

Drone

*

override

private

time_t

start_time

};

class

SearchState

public

StateBase

{

public

SearchState

();

~

SearchState

()

=

default

void

excute

Drone

*

override

};

class

watchTFState

public

StateBase

{

public

watchTFState

();

~

watchTFState

()

=

default

void

excute

Drone

*

override

private

time_t

start_time_watchTF

time_t

end_time_watchTF

time_t

time_watchTF

};

class

sendState

public

StateBase

{

public

sendState

();

~

sendState

()

=

default

void

excute

Drone

*

override

};

class

GoHomeState

public

StateBase

{

public

GoHomeState

();

~

GoHomeState

()

=

default

void

excute

Drone

*

override

};

class

LandingState

public

StateBase

{

public

LandingState

();

~

LandingState

()

=

default

void

excute

Drone

*

override

};

#endif

// STATES_H

3.4、functions.cpp

#include

#include

#include

#include

“math。h”

#include

#include

#include

“。。/include/Drone。h”

#include

“。。/include/Function。h”

using

namespace

std

using

namespace

DJI

::

onboardSDK

using

namespace

Eigen

double

x_guidance

double

y_guidance

double

z_guidance

void

ZigZag_path_planning

double

a

double

b

double

distance

{

//more。。。

}

//Defination of member functions in class “StateBase”

void

StateBase

::

setDrone

Drone

*

new_drone

{

recent_drone

=

new_drone

}

TakeoffState

::

TakeoffState

()

{

TakeoffState

::

recent_drone

=

nullptr

}

void

TakeoffState

::

excute

Drone

*

mydrone

{

//more。。。

}

SearchState

::

SearchState

()

{

SearchState

::

recent_drone

=

nullptr

}

void

SearchState

::

excute

Drone

*

mydrone

{

//more。。。

}

watchTFState

::

watchTFState

()

{

watchTFState

::

recent_drone

=

nullptr

}

void

watchTFState

::

excute

Drone

*

mydrone

{

//more。。。

}

sendState

::

sendState

()

{

sendState

::

recent_drone

=

nullptr

}

void

sendState

::

excute

Drone

*

mydrone

{

//more。。。

}

GoHomeState

::

GoHomeState

()

{

GoHomeState

::

recent_drone

=

nullptr

}

void

GoHomeState

::

excute

Drone

*

mydrone

{

//more。。。

}

LandingState

::

LandingState

()

{

LandingState

::

recent_drone

=

nullptr

}

void

LandingState

::

excute

Drone

*

mydrone

{

//more。。。

}

Drone

::

Drone

double

K

double

H

double

Leader_x_Avoid

double

Leader_y_Avoid

double

Leader_x_Avoid2

double

Leader_y_Avoid2

{

//initialize parameters

K_track

=

K

height

=

H

leader_x_Avoid

=

Leader_x_Avoid

leader_y_Avoid

=

Leader_y_Avoid

leader_x_Avoid2

=

Leader_x_Avoid2

leader_y_Avoid2

=

Leader_y_Avoid2

//create ros node and a new DJIDrone

ros

::

NodeHandle

n

drone

=

new

DJIDrone

n

);

//initialize ROS::subscriber

message_subscriber

=

n

subscribe

“monodata”

1000

&

messageCallback

);

global_position_sub

=

n

subscribe

“guidance/followN1_position”

1000

&

position_callback

);

ultrasonic_sub

=

n

subscribe

“guidance/followultrasonic”

1000

&

ultrasonic_callback

);

uav2takeback

=

n

subscribe

“/uavtakeoffback”

1

&

uav2back_callback

);

uav2landback

=

n

subscribe

“/uavlandback”

1

&

uav2landback_callback

);

//initialize ROS::Publisher

tkpub

=

n

advertise

<

statemachine

::

Takeoff

>

“/uavtakeoff”

1

);

//initialize states of drone

takeoff_state

=

new

TakeoffState

();

search_state

=

new

SearchState

();

watchTF_state

=

new

watchTFState

();

send_state

=

new

sendState

();

gohome_state

=

new

GoHomeState

();

landing_state

=

new

LandingState

();

//Bind state to drone

takeoff_state

->

setDrone

this

);

search_state

->

setDrone

this

);

watchTF_state

->

setDrone

this

);

send_state

->

setDrone

this

);

gohome_state

->

setDrone

this

);

landing_state

->

setDrone

this

);

}

Drone

::~

Drone

()

{

//delete dynamic pointer

delete

drone

delete

takeoff_state

delete

search_state

delete

watchTF_state

delete

gohome_state

e

delete

gohome_state

delete

landing_state

}

void

Drone

::

setState

StateBase

*

new_state

{

recent_state

=

new_state

new_state

->

excute

this

);

}

//Flight logic for mission

void

Drone

::

mission

()

{

ZigZag_path_planning

a_plane

b_plane

distance_raw

);

this

->

setState

takeoff_state

);

this

->

setState

search_state

);

this

->

setState

watchTF_state

);

if

TARGET

==

true

{

this

->

setState

send_state

);

}

this

->

setState

search_state

);

this

->

setState

gohome_state

);

this

->

setState

landing_state

);

}

//access to member variable in Drone

DJIDrone

*

Drone

::

getDrone

()

{

return

this

->

drone

}

請大家批評指正~