项目《iGCS》
项目架构
主控制器 MainViewController
- 继承自
UITabBarController
,有三个子控制器
SWRevealViewController
是第三方库 侧滑效果
WaypointsViewController
---飞行路线设置
CommsViewController
---飞机状态
-
SWRevealViewController
有两个自控制器
GCSMapViewController
----主界面
GCSSidebarController
---侧滑界面
-
MainViewController.m
中两个重要方法
// 处理消息
- (void) handlePacket:(mavlink_message_t*)msg {
[self.gcsMapVC handlePacket:msg];
[self.gcsSidebarVC handlePacket:msg];
[self.waypointVC handlePacket:msg];
#ifdef DEBUG
[self.commsVC handlePacket:msg];
#endif
}
- (void) replaceMission:(WaypointsHolder*)mission {
[self.gcsMapVC replaceMission:mission];
[self.waypointVC replaceMission:mission];
}
MainViewController
遵守了MavLinkPacketHandler
协议
其代理方法
- (void) handlePacket:(mavlink_message_t*)msg;
MavLinkPacketHandler
定义在 MavLinkPacketHandler.h
文件中 只有一个声明文件 在其遵守协议控制器中实现其方法
- 在
MainViewController
的- (void) handlePacket:(mavlink_message_t*)msg
方法中其子控制器都遵守MavLinkPacketHandler
协议,分别执行其代理方法
一个个来看
-
[self.gcsMapVC handlePacket:msg];
是GCSMapViewController
实现
/**
处理消息
此控制器事主界面 根据接收到的消息 判断消息的msgid 来判断消息类型 根据不同的类型 更新相应信息
消息的处理 第三方库里已经封装好了
判断出相应类型的消息 只需调用相应消息的decode方法
传入 msg 和 消息结构体指针,就会返回相应解析的消息
@param msg 消息
*/
- (void) handlePacket:(mavlink_message_t*)msg {
switch (msg->msgid) {
/*
// Temporarily disabled in favour of MAVLINK_MSG_ID_GPS_RAW_INT
// GPS定位信息
case MAVLINK_MSG_ID_GLOBAL_POSITION_INT: {
mavlink_global_position_int_t gpsPosIntPkt;
mavlink_msg_global_position_int_decode(msg, &gpsPosIntPkt);
CLLocationCoordinate2D pos = CLLocationCoordinate2DMake(gpsPosIntPkt.lat/10000000.0, gpsPosIntPkt.lon/10000000.0);
[uavPos setCoordinate:pos];
[self addToTrack:pos];
}
break;
*/
// 消息类型
/*
The global position, as returned by the Global PositioningSystem (GPS). This is NOT the global position estimate of the system, butrather a RAW sensor value. See message GLOBAL_POSITION for the global positionestimate. Coordinate frame is right-handed, Z-axis up (GPS frame)
全球定位,并非系统估计位置,而是RAW传感器值。(Raw Sensor 原始传感器?)——右手坐标系,Z轴向上。
time_usec:时间戳,单位为microseconds微秒。
Lat:Latitude (WGS84), in degrees * 1E7,纬度,单位为度数*10的7次方。
Lon:Longitude (WGS84), in degrees * 1E7,经度,单位为度数*10的7次方。
alt:Altitude (AMSL, NOT WGS84), in meters * 1000 (positive for up).Note that virtually all GPS modules provide the AMSL altitude in addition to the WGS84 altitude.高度,单位为km,向上为正。注意所有GPS模块除了WGS84高度以外,均提供AMSL(平均海平面以上)高 度。
Eph:GPS HDOP (horizontal dilution of position) in cm (m*100). If unknown, set to: UINT16_MAX,GPS水平精度因子,单位为厘米。
Epv: GPS VDOP vertical dilution of position in cm (m*100). Ifunknown, set to: UINT16_MAX,GPS垂直精度因子,单位为厘米。
Vel: GPS ground speed (m/s * 100). If unknown, set to: UINT16_MAX,全球定位系统地速度,单位为百米每秒。
Cog:Course over ground (NOT heading, but direction of movement) indegrees * 100, 0.0..359.99 degrees. If unknown, set to: UINT16_MAX
实际航迹向,单位为百分之一度。
fix_type:0-1: no fix, 2: 2D fix, 3: 3D fix, 4: DGPS, 5: RTK.GPS修正类型。
satellites_visible:卫星可见数,未知则填写255。
*/
case MAVLINK_MSG_ID_GPS_RAW_INT: {
mavlink_gps_raw_int_t gpsRawIntPkt;
mavlink_msg_gps_raw_int_decode(msg, &gpsRawIntPkt);
CLLocationCoordinate2D pos = CLLocationCoordinate2DMake(gpsRawIntPkt.lat/10000000.0, gpsRawIntPkt.lon/10000000.0);
[self.uavPos setCoordinate:pos];
[self addToTrack:pos];
}
break;
// 姿态 Attitude状态报告,包括滚转角、偏航角、俯仰角(及其速度)等信息。
case MAVLINK_MSG_ID_ATTITUDE: {
mavlink_attitude_t attitudePkt;
mavlink_msg_attitude_decode(msg, &attitudePkt);
[self.ahIndicatorView setRoll:-attitudePkt.roll pitch:attitudePkt.pitch];
[self.ahIndicatorView requestRedraw];
}
break;
// 平视显示器数据 Head Up Display
case MAVLINK_MSG_ID_VFR_HUD: {
mavlink_vfr_hud_t vfrHudPkt;
mavlink_msg_vfr_hud_decode(msg, &vfrHudPkt);
self.uavView.image = [GCSMapViewController uavIconForCraft:[GCSDataManager sharedInstance].craft
withYaw:vfrHudPkt.heading * DEG2RAD];
[self.compassView setHeading:vfrHudPkt.heading];
[self.airspeedView setValue:vfrHudPkt.airspeed]; // m/s
[self.altitudeView setValue:vfrHudPkt.alt]; // m
[self.compassView requestRedraw];
[self.airspeedView requestRedraw];
[self.altitudeView requestRedraw];
}
break;
/*
Outputs of the APM navigation controller. The primary use ofthis message is to check the response and signs of the controller before actualflight and to assist with tuning controller parameters.
APM导航控制器的输出,该信息主要功能为检查实飞前控制器的回复和信号,辅助调整控制参数。
nav_roll:当前所需的滚转角
……
alt_error:高度误差
aspd_error:当前空速误差 m/s
xtrack_erro:Current crosstrack error on x-y plane in meters.当前x-y平面横向轨迹误差 单位m
nav_bearing:Current desired heading in degrees.当前任务/目标方位单位度
target_bearing:Bearing to current MISSION/target in degrees.当前任务/目标方位单位度
wp_dist:Distance to active MISSION in meters就,至当前任务点的距离,单位为m
共有 147 字节
*/
case MAVLINK_MSG_ID_NAV_CONTROLLER_OUTPUT: {
mavlink_nav_controller_output_t navCtrlOutPkt;
mavlink_msg_nav_controller_output_decode(msg, &navCtrlOutPkt);
[self.compassView setNavBearing:navCtrlOutPkt.nav_bearing];
[self.airspeedView setTargetDelta:navCtrlOutPkt.aspd_error]; // m/s
[self.altitudeView setTargetDelta:navCtrlOutPkt.alt_error]; // m
}
break;
// 声明当前活动任务项的序列号
case MAVLINK_MSG_ID_MISSION_CURRENT: {
mavlink_mission_current_t currentWaypoint;
mavlink_msg_mission_current_decode(msg, ¤tWaypoint);
[self maybeUpdateCurrentWaypoint:currentWaypoint.seq];
}
break;
/*
常规系统状态信息
onboard_control_sensors_present:以位掩码表示控制器及传感器的存在状态,16776207(十进制)= 111111111111110000001111(二进制)
onboard_control_sensors_enabled:以位掩码表示控制器及传感器的启用状态,16751631(十进制)= 111111111001110000001111(二进制)
onboard_control_sensors_health:以位掩码表示控制器及传感器处于可用状态还是存在错误。转换为二进制同上。
以上掩码信息中,第一位表示gyro陀螺仪,第二位表示accelerometer加速度计,第六位表示GPS……详情见MAV_SYS_STATUS文件。
Load: Maximum usage in percent of the mainloop time,主循环内时间的最大使用比例,1000表示100%,该值应保持小于1000。
voltage_battery:电池电压,单位毫伏特。
current_battery:当前电池(电流),单位毫安。-1表示飞控未测量。
drop_rate_comm:通信丢失百分比,1000表示100%。
errors_comm:通信错误 (UART, I2C, SPI, CAN),丢包。
Errors_countX:Autopilot-specific errors,飞控特定错误,未知含义。
battery_remaining:剩余电量,1表示1%,-1:autopilot estimate the remainingbattery,飞控估计电量
*/
case MAVLINK_MSG_ID_SYS_STATUS: {
mavlink_sys_status_t sysStatus;
mavlink_msg_sys_status_decode(msg, &sysStatus);
[self.voltageLabel setText:[NSString stringWithFormat:@"%0.1fV", sysStatus.voltage_battery/1000.0f]];
[self.currentLabel setText:[NSString stringWithFormat:@"%0.1fA", sysStatus.current_battery/100.0f]];
}
break;
case MAVLINK_MSG_ID_WIND: {
mavlink_wind_t wind;
mavlink_msg_wind_decode(msg, &wind);
_windIconView.transform = CGAffineTransformMakeRotation(((360 + (NSInteger)wind.direction + WIND_ICON_OFFSET_ANG) % 360) * M_PI/180.0f);
}
break;
case MAVLINK_MSG_ID_HEARTBEAT: {
mavlink_heartbeat_t heartbeat;
mavlink_msg_heartbeat_decode(msg, &heartbeat);
// We got a heartbeat, so...
[self rescheduleHeartbeatLossCheck];
// Mutate existing craft, or replace if required (e.g. type has changed)
[GCSDataManager sharedInstance].craft = [GCSCraftModelGenerator updateOrReplaceModel:[GCSDataManager sharedInstance].craft
withCurrent:heartbeat];
// Update segmented control
NSInteger idx = CONTROL_MODE_RC;
if ([GCSDataManager sharedInstance].craft.isInAutoMode) {
idx = CONTROL_MODE_AUTO;
} else if ([GCSDataManager sharedInstance].craft.isInGuidedMode) {
idx = CONTROL_MODE_GUIDED;
}
// Change the segmented control to reflect the heartbeat
if (idx != self.controlModeSegment.selectedSegmentIndex) {
self.controlModeSegment.selectedSegmentIndex = idx;
}
// If the current mode is not a GUIDED mode, and has just changed
// - unconditionally switch out of Follow Me mode
// - clear the guided position annotation markers
if (![GCSDataManager sharedInstance].craft.isInGuidedMode && heartbeat.custom_mode != _lastCustomMode) {
[self deactivateFollowMe];
[self clearGuidedPositions];
}
_lastCustomMode = heartbeat.custom_mode;
}
break;
}
}