我想编程一个系统,其中坐标可以传递给无人机作为航路点,无人机将执行行动。DJI API是用OBJ-c记录的,虽然概念是一样的,im很难理解一个任务是如何编程的。
如果有人能帮助我一个航路点任务的基本结构,并将其传递给无人机,这将是非常有帮助的。也许我没有很好地理解事情,但是DJI API似乎没有很好地描述事情是如何工作的。
我要求的不是填鸭式的,而是一个有洞察力的人,他能给我一个解释
看看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 连
本书的任务是让你熟悉在命令行界面下工作。 熟悉在命令行界面下工作,可以作为你成为一名开发者要做的第一个任务。 在命令行界面下完成一些简单的日常工作,比如进入到某个目录的下面,查看目录里的东西,在目录里创建新的目录,文件,重命名文件或目录,移动文件的位置,编辑文件里的内容。这些任务在图形界面下操作就是点点鼠标的事儿。在命令行界面下,你需要了解内容的路径,绝对路径与相对路径的区别,使用什么样的命令,要
为开发工作去准备一些工具,注意安装的顺序很重要。