当前位置: 首页 > 知识库问答 >
问题:

DJI SDK路点任务-swift、IOS

韦睿
2023-03-14

我想编程一个系统,其中坐标可以传递给无人机作为航路点,无人机将执行行动。DJI API是用OBJ-c记录的,虽然概念是一样的,im很难理解一个任务是如何编程的。

如果有人能帮助我一个航路点任务的基本结构,并将其传递给无人机,这将是非常有帮助的。也许我没有很好地理解事情,但是DJI API似乎没有很好地描述事情是如何工作的。

我要求的不是填鸭式的,而是一个有洞察力的人,他能给我一个解释

共有1个答案

白驰
2023-03-14

看看GitHub上的dji示例应用程序:https://github.com/dji-sdk/mobile-sdk-ios/tree/master/sample%20code/objcsamplecode/djisdkdemo/demo/missionmanager

//
//  WaypointMissionViewController.m
//  DJISdkDemo
//
//  Copyright © 2015 DJI. All rights reserved.
//
/**
 *  This file demonstrates the process to start a waypoint mission. In this demo,
 *  the aircraft will go to four waypoints, shoot photos and record videos.
 *  The flight speed can be controlled by calling the class method
 *  setAutoFlightSpeed:withCompletion:. In this demo, when the aircraft will
 *  change the speed right after it reaches the second point (point with index 1).
 *
 *  CAUTION: it is highly recommended to run this sample using the simulator.
 */
#import <DJISDK/DJISDK.h>
#import "DemoUtility.h"
#import "WaypointMissionViewController.h"

#define ONE_METER_OFFSET (0.00000901315)

@interface WaypointMissionViewController ()

@property (nonatomic) DJIWaypointMissionOperator *wpOperator;
@property (nonatomic) DJIWaypointMission *downloadMission;

@end

@implementation WaypointMissionViewController

-(void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    self.wpOperator = [[DJISDKManager missionControl] waypointMissionOperator];
}

-(void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [self.wpOperator removeListenerOfExecutionEvents:self];
}

/**
 *  Because waypoint mission is refactored and uses a different interface design
 *  from the other missions, we need to override the UI actions.
 */
-(void)onPrepareButtonClicked:(id)sender {
    DJIWaypointMission *wp = (DJIWaypointMission *)[self initializeMission];

    NSError *error = [self.wpOperator loadMission:wp];
    if (error) {
        ShowResult(@"Prepare Mission Failed:%@", error);
        return;
    }
    
    WeakRef(target);
    [self.wpOperator addListenerToUploadEvent:self withQueue:nil andBlock:^(DJIWaypointMissionUploadEvent * _Nonnull event) {
        WeakReturn(target);
        [target onUploadEvent:event];
    }];
    
    [self.wpOperator uploadMissionWithCompletion:^(NSError * _Nullable error) {
        WeakReturn(target);
        if (error) {
            ShowResult(@"ERROR: uploadMission:withCompletion:. %@", error.description);
        }
        else {
            ShowResult(@"SUCCESS: uploadMission:withCompletion:.");
        }
    }];
}

- (IBAction)onStartButtonClicked:(id)sender {
    
    WeakRef(target);
    [self.wpOperator addListenerToExecutionEvent:self withQueue:nil andBlock:^(DJIWaypointMissionExecutionEvent * _Nonnull event) {
        [target showWaypointMissionProgress:event];
    }];
    
    [self.wpOperator startMissionWithCompletion:^(NSError * _Nullable error) {
        if (error) {
            ShowResult(@"ERROR: startMissionWithCompletion:. %@", error.description);
        }
        else {
            ShowResult(@"SUCCESS: startMissionWithCompletion:. ");
        }
        [self missionDidStart:error];
    }];
}

-(void)onStopButtonClicked:(id)sender {
    WeakRef(target);
    [self.wpOperator stopMissionWithCompletion:^(NSError * _Nullable error) {
        WeakReturn(target);
        if (error) {
            ShowResult(@"ERROR: stopMissionExecutionWithCompletion:. %@", error.description);
        }
        else {
            ShowResult(@"SUCCESS: stopMissionExecutionWithCompletion:. ");
        }
        [target missionDidStop:error];
    }];
}

-(void)onDownloadButtonClicked:(id)sender {
    
    self.downloadMission = nil;
    WeakRef(target);
    [self.wpOperator addListenerToDownloadEvent:self
                                      withQueue:nil
                                       andBlock:^(DJIWaypointMissionDownloadEvent * _Nonnull event)
     {

         if (event.progress.downloadedWaypointIndex == event.progress.totalWaypointCount) {
             ShowResult(@"SUCCESS: the waypoint mission is downloaded. ");
             target.downloadMission = target.wpOperator.loadedMission;
             [target.wpOperator removeListenerOfDownloadEvents:target];
             [target.progressBar setHidden:YES];
             [target mission:target.downloadMission didDownload:event.error];
         }
         else if (event.error) {
             ShowResult(@"Download Mission Failed:%@", event.error);
             [target.progressBar setHidden:YES];
             [target mission:target.downloadMission didDownload:event.error];
             [target.wpOperator removeListenerOfDownloadEvents:target];
         } else {
             [target.progressBar setHidden:NO];
             float progress = ((float)event.progress.downloadedWaypointIndex + 1) / (float)event.progress.totalWaypointCount;
             NSLog(@"Download Progress:%d%%", (int)(progress*100));
             [target.progressBar setProgress:progress];
         }
     }];
    
    [self.wpOperator downloadMissionWithCompletion:^(NSError * _Nullable error) {
        WeakReturn(target);
        if (error) {
            ShowResult(@"ERROR: downloadMissionWithCompletion:withCompletion:. %@", error.description);
        }
        else {
            ShowResult(@"SUCCESS: downloadMissionWithCompletion:withCompletion:.");
        }
    }];
}

-(void)onPauseButtonClicked:(id)sender {
    [self missionWillPause];
    [self.wpOperator pauseMissionWithCompletion:^(NSError * _Nullable error) {
        if (error) {
            ShowResult(@"ERROR: pauseMissionWithCompletion:. %@", error.description);
        }
        else {
            ShowResult(@"SUCCESS: pauseMissionWithCompletion:. ");
        }
    }];
}

-(void)onResumeButtonClicked:(id)sender {
    WeakRef(target);
    [self.wpOperator resumeMissionWithCompletion:^(NSError * _Nullable error) {
        WeakReturn(target);
        if (error) {
            ShowResult(@"ERROR: resumeMissionWithCompletion:. %@", error.description);
        }
        else {
            ShowResult(@"SUCCESS: resumeMissionWithCompletion:. ");
        }
        [target missionDidResume:error];
    }];
}

/**
 *  Prepare the waypoint mission. The basic workflow is:
 *  1. Create an instance of DJIWaypointMission.
 *  2. Create coordinates.
 *  3. Use the coordinate to create an instance of DJIWaypoint.
 *  4. Add actions for each waypoint.
 *  5. Add the waypoints into the mission.
 */
-(DJIMission*) initializeMission {
    // Step 1: create mission
    DJIMutableWaypointMission* mission = [[DJIMutableWaypointMission alloc] init];
    mission.maxFlightSpeed = 15.0;
    mission.autoFlightSpeed = 4.0;


    // Step 2: prepare coordinates
    CLLocationCoordinate2D northPoint;
    CLLocationCoordinate2D eastPoint;
    CLLocationCoordinate2D southPoint;
    CLLocationCoordinate2D westPoint;
    northPoint = CLLocationCoordinate2DMake(self.homeLocation.latitude + 10 * ONE_METER_OFFSET, self.homeLocation.longitude);
    eastPoint = CLLocationCoordinate2DMake(self.homeLocation.latitude, self.homeLocation.longitude + 10 * ONE_METER_OFFSET);
    southPoint = CLLocationCoordinate2DMake(self.homeLocation.latitude - 10 * ONE_METER_OFFSET, self.homeLocation.longitude);
    westPoint = CLLocationCoordinate2DMake(self.homeLocation.latitude, self.homeLocation.longitude - 10 * ONE_METER_OFFSET);

    // Step 3: create waypoints
    DJIWaypoint* northWP = [[DJIWaypoint alloc] initWithCoordinate:northPoint];
    northWP.altitude = 10.0;
    DJIWaypoint* eastWP = [[DJIWaypoint alloc] initWithCoordinate:eastPoint];
    eastWP.altitude = 20.0;
    DJIWaypoint* southWP = [[DJIWaypoint alloc] initWithCoordinate:southPoint];
    southWP.altitude = 30.0;
    DJIWaypoint* westWP = [[DJIWaypoint alloc] initWithCoordinate:westPoint];
    westWP.altitude = 40.0;
    
    // Step 4: add actions
    [northWP addAction:[[DJIWaypointAction alloc] initWithActionType:DJIWaypointActionTypeRotateGimbalPitch param:-60]];
    [northWP addAction:[[DJIWaypointAction alloc] initWithActionType:DJIWaypointActionTypeShootPhoto param:0]];
    [eastWP addAction:[[DJIWaypointAction alloc] initWithActionType:DJIWaypointActionTypeShootPhoto param:0]];
    [southWP addAction:[[DJIWaypointAction alloc] initWithActionType:DJIWaypointActionTypeRotateAircraft param:60]];
    [southWP addAction:[[DJIWaypointAction alloc] initWithActionType:DJIWaypointActionTypeStartRecord param:0]];
    [westWP addAction:[[DJIWaypointAction alloc] initWithActionType:DJIWaypointActionTypeStopRecord param:0]];

    // Step 5: add waypoints into the mission
    [mission addWaypoint:northWP];
    [mission addWaypoint:eastWP];
    [mission addWaypoint:southWP];
    [mission addWaypoint:westWP]; 
    
    return mission; 
}


- (void)onUploadEvent:(DJIWaypointMissionUploadEvent *) event
{
    
    if (event.currentState == DJIWaypointMissionStateReadyToExecute) {
        ShowResult(@"SUCCESS: the whole waypoint mission is uploaded.");
        [self.progressBar setHidden:YES];
        [self.wpOperator removeListenerOfUploadEvents:self];
    }
    else if (event.error) {
        ShowResult(@"ERROR: waypoint mission uploading failed. %@", event.error.description);
        [self.progressBar setHidden:YES];
        [self.wpOperator removeListenerOfUploadEvents:self];
    }
    else if (event.currentState == DJIWaypointMissionStateReadyToUpload ||
             event.currentState == DJIWaypointMissionStateNotSupported ||
             event.currentState == DJIWaypointMissionStateDisconnected) {
        ShowResult(@"ERROR: waypoint mission uploading failed. %@", event.error.description);
        [self.progressBar setHidden:YES];
        [self.wpOperator removeListenerOfUploadEvents:self];
    } else if (event.currentState == DJIWaypointMissionStateUploading) {
        [self.progressBar setHidden:NO];
        DJIWaypointUploadProgress *progress = event.progress;
        float progressInPercent = progress.uploadedWaypointIndex / progress.totalWaypointCount;
        [self.progressBar setProgress:progressInPercent];
    }
}

-(void) showWaypointMissionProgress:(DJIWaypointMissionExecutionEvent *)event {
    NSMutableString* statusStr = [NSMutableString new];
    [statusStr appendFormat:@"previousState:%@\n", [[self class] descriptionForMissionState:event.previousState]];
    [statusStr appendFormat:@"currentState:%@\n", [[self class] descriptionForMissionState:event.currentState]];
    
    [statusStr appendFormat:@"Target Waypoint Index: %zd\n", (long)event.progress.targetWaypointIndex];
    [statusStr appendString:[NSString stringWithFormat:@"Is Waypoint Reached: %@\n",
                             event.progress.isWaypointReached ? @"YES" : @"NO"]];
    [statusStr appendString:[NSString stringWithFormat:@"Execute State: %@\n", [[self class] descriptionForExecuteState:event.progress.execState]]];
    if (event.error) {
        [statusStr appendString:[NSString stringWithFormat:@"Execute Error: %@", event.error.description]];
        [self.wpOperator removeListenerOfExecutionEvents:self];
    }
    
    [self.statusLabel setText:statusStr];
}

/**
 *  Display the information of the mission if it is downloaded successfully.
 */
-(void)mission:(DJIMission *)mission didDownload:(NSError *)error {
    if (error) return;
    
    if ([mission isKindOfClass:[DJIWaypointMission class]]) {
        // Display information of waypoint mission.
        [self showWaypointMission:(DJIWaypointMission*)mission];
    }
}

-(void) showWaypointMission:(DJIWaypointMission*)wpMission {
    NSMutableString* missionInfo = [NSMutableString stringWithString:@"The waypoint mission is downloaded successfully: \n"];
    [missionInfo appendString:[NSString stringWithFormat:@"RepeatTimes: %zd\n", wpMission.repeatTimes]];
    [missionInfo appendString:[NSString stringWithFormat:@"HeadingMode: %u\n", (unsigned int)wpMission.headingMode]];
    [missionInfo appendString:[NSString stringWithFormat:@"FinishedAction: %u\n", (unsigned int)wpMission.finishedAction]];
    [missionInfo appendString:[NSString stringWithFormat:@"FlightPathMode: %u\n", (unsigned int)wpMission.flightPathMode]];
    [missionInfo appendString:[NSString stringWithFormat:@"MaxFlightSpeed: %f\n", wpMission.maxFlightSpeed]];
    [missionInfo appendString:[NSString stringWithFormat:@"AutoFlightSpeed: %f\n", wpMission.autoFlightSpeed]];
    [missionInfo appendString:[NSString stringWithFormat:@"There are %zd waypoint(s). ", wpMission.waypointCount]];
    [self.statusLabel setText:missionInfo];
}

+(NSString *)descriptionForMissionState:(DJIWaypointMissionState)state {
    switch (state) {
        case DJIWaypointMissionStateUnknown:
            return @"Unknown";
        case DJIWaypointMissionStateExecuting:
            return @"Executing";
        case DJIWaypointMissionStateUploading:
            return @"Uploading";
        case DJIWaypointMissionStateRecovering:
            return @"Recovering";
        case DJIWaypointMissionStateDisconnected:
            return @"Disconnected";
        case DJIWaypointMissionStateNotSupported:
            return @"NotSupported";
        case DJIWaypointMissionStateReadyToUpload:
            return @"ReadyToUpload";
        case DJIWaypointMissionStateReadyToExecute:
            return @"ReadyToExecute";
        case DJIWaypointMissionStateExecutionPaused:
            return @"ExecutionPaused";
    }
    
    return @"Unknown";
}

+(NSString *)descriptionForExecuteState:(DJIWaypointMissionExecuteState)state {
    switch (state) {
        case DJIWaypointMissionExecuteStateInitializing:
            return @"Initializing";
            break;
        case DJIWaypointMissionExecuteStateMoving:
            return @"Moving";
        case DJIWaypointMissionExecuteStatePaused:
            return @"Paused";
        case DJIWaypointMissionExecuteStateBeginAction:
            return @"BeginAction";
        case DJIWaypointMissionExecuteStateDoingAction:
            return @"Doing Action";
        case DJIWaypointMissionExecuteStateFinishedAction:
            return @"Finished Action";
        case DJIWaypointMissionExecuteStateCurveModeMoving:
            return @"CurveModeMoving";
        case DJIWaypointMissionExecuteStateCurveModeTurning:
            return @"CurveModeTurning";
        case DJIWaypointMissionExecuteStateReturnToFirstWaypoint:
            return @"Return To first Point";
        default:
            break;
    }
    return @"Unknown";
}

@end
 类似资料:
  • 这仍然只在前景工作。 我在这里漏掉了什么?

  • 任务列表 下面表格记录了还没有实现的功能特性,欢迎大家认领任务,参与贡献。 类型 任务 困难度 认领人及时间 计划完成时间 进度 相关 Issue 文档 SOFADashboard 配置参数文档 简单 代码 支持 SOFARegistry 中 代码 支持 Docker 中 代码 支持 Kubernetes 中 代码 支持 Apollo 中 代码 优化前端 中

  • 我们有一个Spring+JPA web应用程序。我们使用两个tomcat服务器,它们运行两个应用程序并使用相同的数据库。 我们的应用程序requirmemnt之一是预形成cron调度任务。 谢了!

  • 3.3.3 Android 任务 Android plugin 使用了同样的约定规则以和其他插件保持兼容,并且又添加了一些额外的引导任务: assemble 这个任务会汇集工程的所有输出。 check 这个任务会执行所有校验检查 connectedCheck 运行 checks 需要一个连接的设备或者模拟器,这些checks将会同时运行在所有连接的设备上。 deviceCheck 通过 API 连

  • 本书的任务是让你熟悉在命令行界面下工作。 熟悉在命令行界面下工作,可以作为你成为一名开发者要做的第一个任务。 在命令行界面下完成一些简单的日常工作,比如进入到某个目录的下面,查看目录里的东西,在目录里创建新的目录,文件,重命名文件或目录,移动文件的位置,编辑文件里的内容。这些任务在图形界面下操作就是点点鼠标的事儿。在命令行界面下,你需要了解内容的路径,绝对路径与相对路径的区别,使用什么样的命令,要

  • 为开发工作去准备一些工具,注意安装的顺序很重要。