# 应用程序接口 (API)

我们为Kerloud Flying Rover系列提供用于开发的开源API，并有C++、Python或其他语言的版本可选用。详细内容会在本章节持续更新。

## 1. ROS API(C++)

ROS（Robot Operating System）中的API是基于PX4社区的官方MAVROS包来实现的。我们在维护的软件库链接为：

* mavros (dev\_flyingrover 分支): <https://github.com/cloudkernel-tech/mavros>
* mavlink (dev\_flyingrover 分支): <https://github.com/cloudkernel-tech/mavlink-gdp-release>
* 基于ROS C++ API的offboard控制案例 (dev\_flyingrover 分支): <https://github.com/cloudkernel-tech/offboard_demo>

更多的编程细节将在这里的教程章节进行说明，而此处介绍与我们的飞车案例特别相关的话题和服务。

### 1.1 Topics

#### (1) \~mavros/extended\_state

订阅该话题可获取飞车的当前状态，消息类型为从原始版本扩展而来的mavros\_msgs/ExtendedState，提供了用于指示飞车状态的flyingrover\_state额外字段，具体如下文所示。本字段的取值是使用前缀FLYINGROVER\_STATE\_\*定义的那些常量。

```
# Extended autopilot state
#
# https://mavlink.io/en/messages/common.html#EXTENDED_SYS_STATE

uint8 VTOL_STATE_UNDEFINED = 0
uint8 VTOL_STATE_TRANSITION_TO_FW = 1
uint8 VTOL_STATE_TRANSITION_TO_MC = 2
uint8 VTOL_STATE_MC = 3
uint8 VTOL_STATE_FW = 4

uint8 LANDED_STATE_UNDEFINED = 0
uint8 LANDED_STATE_ON_GROUND = 1
uint8 LANDED_STATE_IN_AIR = 2
uint8 LANDED_STATE_TAKEOFF = 3
uint8 LANDED_STATE_LANDING = 4

uint8 FLYINGROVER_STATE_UNDEFINED = 0
uint8 FLYINGROVER_STATE_ROVER = 1
uint8 FLYINGROVER_STATE_MC = 2
uint8 FLYINGROVER_STATE_TRANSITION_TO_MC = 3
uint8 FLYINGROVER_STATE_TRANSITION_TO_ROVER = 4

std_msgs/Header header
uint8 vtol_state
uint8 landed_state
uint8 flyingrover_state
```

为清晰起见，在此说明具体含义：

* flyingrover\_state=0: 飞车尚未初始化。
* flyingrover\_state=1: 飞车运行在陆地车模式下。
* flyingrover\_state=2: 飞车运行在多旋翼模式下。
* flyingrover\_state=3: 飞车正从陆地车模式向多旋翼模式转换。手动模式下，状态会立即切为多旋翼模式；offboard或其他自动模式下，当运动速度低于自驾仪固件中FR\_V\_TH\_MC参数的取值(默认为0.2m/s)时会完成切换。
* flyingrover\_state=4: 飞车正从多旋翼模式向陆地车模式转换，机器即将手动或自主着陆，着陆后状态将转为陆地车模式。

#### (2) \~mavros/setpoint\_position/local, \~mavros/setpoint\_position/global

本话题用于发布在本地或全局坐标系下的航点位置信息，陆地车、多旋翼模式下通用。需注意，ROS层使用的参考坐标系为ENU，而自驾仪使用的则是NED，消息类型分别为[geometry\_msgs/PoseStamped](http://docs.ros.org/en/api/geometry_msgs/html/msg/PoseStamped.html)和[mavros\_msgs/GlobalPositionTarget](http://docs.ros.org/en/api/mavros_msgs/html/msg/GlobalPositionTarget.html)。

#### (3) \~mavros/setpoint\_velocity/cmd\_vel\_unstamped, \~mavros/setpoint\_velocity/cmd\_vel

这两个话题用于发布飞车在本地坐标系中的速度设定值，陆地车、多旋翼模式下通用，两个话题的唯一区别是速度信息是否携带时间戳。消息类型为[geometry\_msgs/Twist](http://docs.ros.org/en/api/geometry_msgs/html/msg/Twist.html)。

#### (4) \~mavros/setpoint\_attitude/attitude, \~mavros/setpoint\_attitude/thrust

这两个话题可用于在陆地车、多旋翼模式设定姿态值，但建议只用于车模式。消息类型分别为[geometry\_msgs/PoseStamped](http://docs.ros.org/en/api/geometry_msgs/html/msg/PoseStamped.html) 和 [mavros\_msgs/Thrust](http://docs.ros.org/en/api/mavros_msgs/html/msg/Thrust.html)。姿态推力直接输入到主电机油门，通过偏航角跟踪误差来计算生成转向伺服舵机的控制输入。

### 1.2 Services

#### (1) \~mavros/cmd/command

本服务用于offboard控制模式下陆地车、多旋翼的状态切换，消息类型为[mavros\_msgs/CommandLong](http://docs.ros.org/en/api/mavros_msgs/html/srv/CommandLong.html)，对应于下文链接中的一个定制化mavlink消息 （mavlink::common::MAV\_CMD::DO\_FLYINGROVER\_TRANSITION），链接为<https://github.com/cloudkernel-tech/mavlink-gdp-release/blob/dev_flyingrover/message_definitions/v1.0/common.xml>。

例如，如果我们想切换到多旋翼模式，则需要通过如下设置调用该服务：

```
mavros_msgs::CommandLong switch_to_mc_cmd;//command to switch to multicopter
switch_to_mc_cmd.request.command = (uint16_t)mavlink::common::MAV_CMD::DO_FLYINGROVER_TRANSITION;
switch_to_mc_cmd.request.confirmation = 0;
switch_to_mc_cmd.request.param1 = (float)mavlink::common::MAV_FLYINGROVER_STATE::MC;
```

相反，若切换到陆地车模式，则：

```
mavros_msgs::CommandLong switch_to_rover_cmd;//command to switch to rover
switch_to_rover_cmd.request.command = (uint16_t)mavlink::common::MAV_CMD::DO_FLYINGROVER_TRANSITION;
switch_to_rover_cmd.request.confirmation = 0;
switch_to_rover_cmd.request.param1 = (float)mavlink::common::MAV_FLYINGROVER_STATE::ROVER;
```

请注意，mavlink::common::MAV\_FLYINGROVER\_STATE的枚举定义如下，参见[链接](https://github.com/cloudkernel-tech/mavlink-gdp-release/blob/dev_flyingrover/message_definitions/v1.0/common.xml)

```
typedef enum MAV_FLYINGROVER_STATE
{
   MAV_FLYINGROVER_STATE_UNDEFINED=0, /* MAV is not configured as flyingrover | */
   MAV_FLYINGROVER_STATE_ROVER=1, /* flyingrover is in rover state | */
   MAV_FLYINGROVER_STATE_MC=2, /* flyingrover is in multicopter state | */
   MAV_FLYINGROVER_STATE_TRANSITION_TO_MC=3,/* flyingrover is in transition from rover to multicopter | */
   MAV_FLYINGROVER_STATE_TRANSITION_TO_ROVER=4,/* flyingrover is in transition from multicopter to rover | */
   MAV_FLYINGROVER_STATE_ENUM_END=5, /*  | */
} MAV_FLYINGROVER_STATE;
```

## 2. ROS API (python)

与C++版本ROS API类似，ROS python API也是基于我们维护的mavros和 mavlink包实现，仅有的区别是上文提到的所有话题和服务需通过python来使用。

* mavros (dev\_flyingrover 分支): <https://github.com/cloudkernel-tech/mavros>
* mavlink (dev\_flyingrover 分支): <https://github.com/cloudkernel-tech/mavlink-gdp-release>
* 基于ROS python API的offboard控制案例 (dev\_flyingrover 分支): <https://github.com/cloudkernel-tech/offboard_demo_python>

代码将在这里的教程章节有做讲解。为简洁起见，底层消息通信在Px4Controller类中进行处理，而面向用户编程用的友好API接口封装于Commander类中，部分API列举如下：

* move(x,y,z, BODY\_FLU=False): 请求飞车移动到FLU或ENU坐标系下的指定位置，陆地车、多旋翼模式下通用。
* turn(yaw\_degree): 请求飞车偏航指定角度，仅多旋翼模式可用。
* land(): 多旋翼模式下，请求飞车着陆；
* hover(): 多旋翼模式下，请求飞车悬停在当前位置。
* arm(): 请求解锁飞车。
* disarm(): 请求锁定地面的飞车。
* transit\_to\_rover(): 请求飞车切换为陆地车模式。
* transit\_to\_mc(): 请求飞车切换为多旋翼模式。
* return\_home(height): 请求飞车返航，仅多旋翼模式可用。
