无人机《iGCS》学习

项目《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文件中 只有一个声明文件 在其遵守协议控制器中实现其方法

MavLinkPacketHandler
  • 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, &currentWaypoint);
            [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;
    }
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,580评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,376评论 25 707
  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 1,678评论 0 9
  • 1,NSObject中description属性的意义,它可以重写吗?答案:每当 NSLog(@"")函数中出现 ...
    eightzg阅读 4,131评论 2 19
  • “In me the tiger sniffs the rose.”心有猛虎,细嗅蔷薇。英国诗人西格夫里·萨...
    Miss伊柚阅读 383评论 0 0