ArDrone SDK 1.8 added
[mardrone] / mardrone / ARDrone_SDK_Version_1_8_20110726 / ControlEngine / iPhone / Classes / Controllers / MainViewController.m
1 //
2 //  MainViewController.m
3 //  ARDroneEngine
4 //
5 //  Created by Mykonos on 17/12/09.
6 //  Copyright 2009 Parrot SA. All rights reserved.
7 //
8 #import "MainViewController.h"
9 #import "OpenGLVideo.h"
10
11 extern navdata_unpacked_t ctrlnavdata;
12
13 @interface MainViewController ()
14 ARDroneNavigationData navigationData;
15 ARDroneEnemiesData humanEnemiesData;    
16 ARDroneDetectionCamera detectionCamera;
17 ARDroneCamera droneCamera;
18
19 id<NavdataProtocol>navdata_delegate;
20 CGRect screenFrame;
21 BOOL screenOrientationRight;
22 BOOL bContinue;
23 ARDroneHUDConfiguration hudconfig; 
24 ControlData *controlData;
25
26 -(void)TimerHandler;
27 -(void)update;
28 @end
29
30 @implementation MainViewController
31 - (id) initWithFrame:(CGRect)frame withState:(BOOL)inGame withDelegate:(id<ARDroneProtocolOut>)delegate withNavdataDelegate:(id<NavdataProtocol>)_navdata_delegate withControlData:(ControlData*)_controlData withHUDConfiguration:(ARDroneHUDConfiguration*)hudconfiguration
32 {
33         NSLog(@"Main View Controller Frame : %@", NSStringFromCGRect(frame));
34         if(self = [super init])
35         {
36                 bContinue = TRUE;
37                 screenOrientationRight = YES;
38                 screenFrame = frame;
39                 gameEngine = delegate;
40                 navdata_delegate = _navdata_delegate;
41                 controlData = _controlData;
42
43                 vp_os_memset(&navigationData, 0x0, sizeof(ARDroneNavigationData)); 
44                 vp_os_memset(&detectionCamera, 0x0, sizeof(ARDroneCamera));
45                 vp_os_memset(&droneCamera, 0x0, sizeof(ARDroneCamera)); 
46                 humanEnemiesData.count = 0;
47                 
48                 for(int i = 0 ; i < ARDRONE_MAX_ENEMIES ; i++)
49                 {
50                         vp_os_memset(&humanEnemiesData.data[i], 0x0, sizeof(ARDroneEnemyData));
51                         humanEnemiesData.data[i].width = 1.0;
52                         humanEnemiesData.data[i].height = 1.0;
53                 }
54
55                 if(hudconfiguration == nil)
56                 {
57                         hudconfig.enableBackToMainMenu = NO;
58                         hudconfig.enableSwitchScreen = YES;
59                         hudconfig.enableBatteryPercentage = YES;
60                 }
61                 else
62                 {
63                         vp_os_memcpy(&hudconfig, hudconfiguration, sizeof(ARDroneHUDConfiguration));
64                 }
65                 
66                 hud = [[HUD alloc] initWithFrame:screenFrame withState:inGame withHUDConfiguration:hudconfig withControlData:controlData];
67                 [self.view addSubview:hud.view];
68                 hud.view.multipleTouchEnabled = YES;
69                 
70                 menuSettings = [[SettingsMenu alloc] initWithFrame:screenFrame AndHUDConfiguration:hudconfig withDelegate:hud withControlData:controlData];
71                 menuSettings.view.hidden = YES;
72                 menuSettings.view.multipleTouchEnabled = YES;
73                 [self.view addSubview:menuSettings.view];
74                 self.view.multipleTouchEnabled = YES;
75                 
76                 [self changeState:inGame];
77                 
78                 [NSThread detachNewThreadSelector:@selector(TimerHandler) toTarget:self withObject:nil];
79         }
80         
81         return self;
82 }
83
84 - (void)setWifiReachabled:(BOOL)reachabled
85 {
86         controlData->wifiReachabled = reachabled;
87 }
88
89 -(void)setScreenOrientationRight:(BOOL)right
90 {
91         screenOrientationRight = right;
92 }
93
94 - (void) update
95 {
96         static CONFIG_STATE prev_config_state = CONFIG_STATE_IDLE;
97         static bool_t prev_navdata_connected = FALSE;
98         
99         if(prev_config_state != controlData->configurationState)
100         {
101                 if(controlData->configurationState == CONFIG_STATE_IDLE)
102                         [menuSettings configChanged];
103                 prev_config_state = controlData->configurationState;
104         }               
105                 
106         if(prev_navdata_connected != controlData->navdata_connected)
107         {
108                 [menuSettings configChanged];
109                 prev_navdata_connected = controlData->navdata_connected;
110         }
111         
112         if(hud.firePressed == YES) 
113         {
114                 [gameEngine executeCommandOut:ARDRONE_COMMAND_FIRE withParameter:nil fromSender:self.view];
115         }
116         else if(hud.mainMenuPressed == YES)
117         {
118                 hud.mainMenuPressed = NO;
119                 [gameEngine executeCommandOut:ARDRONE_COMMAND_PAUSE withParameter:nil fromSender:self.view];
120         }
121         else if(hud.settingsPressed == YES)
122         {
123                 hud.settingsPressed = NO;
124                 [menuSettings performSelectorOnMainThread:@selector(switchDisplay) withObject:nil waitUntilDone:YES];
125         }
126         
127         // Set velocities       
128         navigationData.linearVelocity.x = -ctrlnavdata.navdata_demo.vy;
129         navigationData.linearVelocity.y = ctrlnavdata.navdata_demo.vz;
130         navigationData.linearVelocity.z = ctrlnavdata.navdata_demo.vx;
131         navigationData.angularPosition.x = -ctrlnavdata.navdata_demo.theta / 1000;
132         navigationData.angularPosition.y = ctrlnavdata.navdata_demo.psi / 1000;
133         navigationData.angularPosition.z = ctrlnavdata.navdata_demo.phi / 1000;
134         navigationData.navVideoNumFrames = ctrlnavdata.navdata_demo.num_frames;
135         navigationData.videoNumFrames    = get_video_current_numframes();
136
137         // Set flying state.
138         ARDRONE_FLYING_STATE tmp_state = ardrone_navdata_get_flying_state(ctrlnavdata); 
139         if(navigationData.flyingState != tmp_state)
140         {
141                 NSLog(@"Flying state switch to %d", tmp_state);
142                 if(hudconfig.enableBackToMainMenu)
143                         [hud showBackToMainMenu:(tmp_state == ARDRONE_FLYING_STATE_LANDED)];
144         }
145         
146         navigationData.flyingState = tmp_state;
147         navigationData.emergencyState = ctrlnavdata.ardrone_state & ARDRONE_EMERGENCY_MASK;
148         navigationData.detection_type = (ARDRONE_CAMERA_DETECTION_TYPE)ctrlnavdata.navdata_demo.detection_camera_type;
149         navigationData.finishLineCount = ctrlnavdata.navdata_games.finish_line_counter;
150         navigationData.doubleTapCount = ctrlnavdata.navdata_games.double_tap_counter;
151     navigationData.isInit = (ctrlnavdata.ardrone_state & ARDRONE_NAVDATA_BOOTSTRAP) ? 0 : 1;
152
153         // Set detected ARDRONE_ENEMY_HUMAN enemies if detected.
154         humanEnemiesData.count = MIN(ctrlnavdata.navdata_vision_detect.nb_detected, ARDRONE_MAX_ENEMIES);
155         
156         //printf("enemies count : %d\n", humanEnemiesData.count);
157         for(int i = 0 ; i < humanEnemiesData.count ; i++)
158         {
159                 humanEnemiesData.data[i].width = 2 * ctrlnavdata.navdata_vision_detect.width[i] / 1000.0;
160                 humanEnemiesData.data[i].height = 2 * ctrlnavdata.navdata_vision_detect.height[i] / 1000.0;             
161                 humanEnemiesData.data[i].position.x = (2 * ctrlnavdata.navdata_vision_detect.xc[i] / 1000.0) - 1.0;
162                 humanEnemiesData.data[i].position.y = -(2 * ctrlnavdata.navdata_vision_detect.yc[i] / 1000.0) + 1.0;
163                 humanEnemiesData.data[i].position.z = ctrlnavdata.navdata_vision_detect.dist[i];
164                 humanEnemiesData.data[i].orientation_angle = ctrlnavdata.navdata_vision_detect.orientation_angle[i];
165         }
166         
167         // Set Detection Camera
168         vp_os_memcpy(detectionCamera.rotation, &ctrlnavdata.navdata_demo.detection_camera_rot, sizeof(float) * 9);
169         vp_os_memcpy(detectionCamera.translation, &ctrlnavdata.navdata_demo.detection_camera_trans, sizeof(float) * 3);
170         detectionCamera.tag_index = ctrlnavdata.navdata_demo.detection_tag_index;
171         
172         // Set Drone Camera rotation
173         vp_os_memcpy(droneCamera.rotation, &ctrlnavdata.navdata_demo.drone_camera_rot, sizeof(float) * 9);
174         
175         // Set Drone Camera translation
176         // Get enemies data
177         if ([gameEngine respondsToSelector:@selector(AIEnemiesData:)])
178         {
179                 ARDroneEnemiesData AIEnemiesData;
180                 vp_os_memset(&AIEnemiesData, 0x0, sizeof(ARDroneEnemiesData));
181                 [gameEngine AIEnemiesData:&AIEnemiesData];              
182         }
183         
184         vp_os_memcpy(&droneCamera.translation[0], &ctrlnavdata.navdata_demo.drone_camera_trans, sizeof(float) * 3);
185         
186         // Set battery level in hud view
187         [hud setBattery:(int)ctrlnavdata.navdata_demo.vbat_flying_percentage];
188         
189         // Set  all texts in Hud view
190         if((strlen(controlData->error_msg) != 0) && (controlData->framecounter >= (kFPS / 2.0)))
191                 [hud setMessageBox:[[NSBundle mainBundle] localizedStringForKey :[NSString stringWithCString:controlData->error_msg encoding:NSUTF8StringEncoding] value:@"" table:@"languages"]];
192         else
193                 [hud setMessageBox:@""];
194         
195         [hud performSelectorOnMainThread:@selector(setTakeOff:) withObject:[NSString stringWithFormat:@"%s", controlData->takeoff_msg] waitUntilDone:YES];
196         [hud performSelectorOnMainThread:@selector(setEmergency:) withObject:[NSString stringWithFormat:@"%s", controlData->emergency_msg] waitUntilDone:YES];
197 }
198
199 - (void) TimerHandler {
200     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // Top-level pool
201         
202         ardrone_timer_t timer;
203         int refreshTimeInUs = 1000000 / kFPS;
204         
205         ardrone_timer_reset(&timer);
206         ardrone_timer_update(&timer);
207         
208         while(bContinue)
209         {
210                 int delta = ardrone_timer_delta_us(&timer);
211                 if( delta >= refreshTimeInUs)
212                 {
213                         // Render frame
214                         ardrone_timer_update(&timer);
215                         
216                         if(self.view.hidden == NO)
217                         {
218                                 [navdata_delegate parrotNavdata:&ctrlnavdata];
219                                 [self performSelectorOnMainThread:@selector(update) withObject:nil waitUntilDone:YES];
220                                 checkErrors();
221                         }
222                         
223                         controlData->framecounter = (controlData->framecounter + 1) % kFPS;
224                 }
225                 else
226                 {
227                         //printf("Time waited : %d us\n", refreshTimeInUs - delta);
228                         usleep(refreshTimeInUs - delta);
229                 }
230         }
231
232     [pool release];  // Release the objects in the pool.
233 }
234
235 - (ARDroneNavigationData*)navigationData
236 {
237         return &navigationData;
238 }
239
240 - (ARDroneDetectionCamera*)detectionCamera
241 {
242         return &detectionCamera;
243 }
244
245 - (ARDroneCamera*)droneCamera
246 {
247         return &droneCamera;
248 }
249
250 - (ARDroneEnemiesData*)humanEnemiesData
251 {
252         return &humanEnemiesData;
253 }
254
255 - (void)changeState:(BOOL)inGame
256 {
257         self.view.hidden = !inGame;
258         [hud changeState:inGame];
259     
260     if (inGame)
261         configuration_get();
262 }
263
264 - (void)executeCommandIn:(ARDRONE_COMMAND_IN_WITH_PARAM)commandIn fromSender:(id)sender refreshSettings:(BOOL)refresh
265 {
266         int32_t i_value;
267         switch (commandIn.command) {
268         
269                 case ARDRONE_COMMAND_ISCLIENT:
270                         i_value = ((int)commandIn.parameter == 0) ? ADC_CMD_SELECT_ULTRASOUND_25Hz : ADC_CMD_SELECT_ULTRASOUND_22Hz;
271                         ARDRONE_TOOL_CONFIGURATION_ADDEVENT(ultrasound_freq, &i_value, commandIn.callback);
272                         break;
273                         
274                 case ARDRONE_COMMAND_DRONE_ANIM:
275                         {
276                                 ARDRONE_ANIMATION_PARAM *param = (ARDRONE_ANIMATION_PARAM*)commandIn.parameter;
277                                 char str_param[SMALL_STRING_SIZE];
278                                 sprintf(str_param, "%d,%d", param->drone_anim, ((param->timeout == 0) ? MAYDAY_TIMEOUT[param->drone_anim] : param->timeout));
279                                 ARDRONE_TOOL_CONFIGURATION_ADDEVENT(flight_anim, str_param, commandIn.callback);
280                         }
281                         break;
282                         
283                 case ARDRONE_COMMAND_DRONE_LED_ANIM:
284                         {
285                                 char param[SMALL_STRING_SIZE];
286                                 float_or_int_t freq;
287                                 freq.f = ((ARDRONE_LED_ANIMATION_PARAM*)commandIn.parameter)->frequency;
288                                 sprintf(param, "%d,%d,%d", ((ARDRONE_LED_ANIMATION_PARAM*)commandIn.parameter)->led_anim, freq.i, ((ARDRONE_LED_ANIMATION_PARAM*)commandIn.parameter)->duration);
289                                 ARDRONE_TOOL_CONFIGURATION_ADDEVENT(leds_anim, param, commandIn.callback);
290                         }
291                         break;
292                         
293                 case ARDRONE_COMMAND_ENABLE_COMBINED_YAW:
294                         {
295                                 bool_t enable = (bool_t)commandIn.parameter;
296                                 i_value = enable ? (ardrone_control_config.control_level | (1 << CONTROL_LEVEL_COMBINED_YAW)) : (ardrone_control_config.control_level & ~(1 << CONTROL_LEVEL_COMBINED_YAW));
297                                 ARDRONE_TOOL_CONFIGURATION_ADDEVENT(control_level, &i_value, commandIn.callback);
298                                 [hud combinedYawValueChanged:enable];
299                         }
300                         break;
301                         
302                 case ARDRONE_COMMAND_SET_CONFIG:
303                 {
304                         ARDRONE_CONFIG_PARAM *param = (ARDRONE_CONFIG_PARAM *)commandIn.parameter;
305                         switch (param->config_key)
306                         {
307 #undef COMMAND_IN_CONFIG_KEY
308 #undef COMMAND_IN_CONFIG_KEY_STRING
309 #define COMMAND_IN_CONFIG_KEY(CASE, KEY, TYPE)                                                                                                  \
310 case CASE:                                                                                                                                                                              \
311         ardrone_control_config.KEY = *(TYPE *)(param->pvalue);                                                                          \
312         ARDRONE_TOOL_CONFIGURATION_ADDEVENT (KEY, &ardrone_control_config.KEY, commandIn.callback);     \
313         break;
314 #define COMMAND_IN_CONFIG_KEY_STRING(CASE, KEY)                                                                                                 \
315 case CASE:                                                                                                                                                                              \
316         strcpy (ardrone_control_config.KEY, (char *)(param->pvalue));                                                           \
317         ARDRONE_TOOL_CONFIGURATION_ADDEVENT (KEY, ardrone_control_config.KEY, commandIn.callback);      \
318         break;
319 #include "ARDroneGeneratedCommandIn.h"
320 #undef COMMAND_IN_CONFIG_KEY
321 #undef COMMAND_IN_CONFIG_KEY_STRING
322                                         
323                                 default:
324                                         NSLog(@"The ARDRONE_CONFIG_KEY %d is not implemented !", param->config_key);
325                                         break;
326                         }
327                 }       
328                 break;
329                 
330                 default:
331                         NSLog(@"The ARDRONE_COMMAND_IN %d is not implemented !", commandIn.command);
332                         break;
333         }
334         
335         if (refresh)
336         {
337                 [menuSettings performSelectorOnMainThread:@selector(configChanged) withObject:nil waitUntilDone:YES];
338         }
339 }
340
341 - (void)executeCommandIn:(ARDRONE_COMMAND_IN)commandId withParameter:(void*)parameter fromSender:(id)sender
342 {
343         int32_t i_value;
344         switch (commandId) {
345                 case ARDRONE_COMMAND_ISCLIENT:
346         {
347             i_value = ((int)parameter == 0) ? ADC_CMD_SELECT_ULTRASOUND_25Hz : ADC_CMD_SELECT_ULTRASOUND_22Hz;
348             ARDRONE_TOOL_CONFIGURATION_ADDEVENT(ultrasound_freq, &i_value, NULL);
349         }
350             break;
351                         
352                 case ARDRONE_COMMAND_DRONE_ANIM:
353         {
354             ARDRONE_ANIMATION_PARAM *param = (ARDRONE_ANIMATION_PARAM*)parameter;
355             char str_param[SMALL_STRING_SIZE];
356             sprintf(str_param, "%d,%d", param->drone_anim, ((param->timeout == 0) ? MAYDAY_TIMEOUT[param->drone_anim] : param->timeout));
357             ARDRONE_TOOL_CONFIGURATION_ADDEVENT(flight_anim, str_param, NULL);
358         }
359                         break;
360                         
361                 case ARDRONE_COMMAND_VIDEO_CHANNEL:
362                         i_value = (int32_t)parameter;
363                         ARDRONE_TOOL_CONFIGURATION_ADDEVENT(video_channel, &i_value, NULL);
364                         break;
365                         
366                 case ARDRONE_COMMAND_SET_FLY_MODE:
367                         i_value = (int32_t)parameter;
368                         ARDRONE_TOOL_CONFIGURATION_ADDEVENT(flying_mode, &i_value, NULL);
369                         break;
370                         
371                 case ARDRONE_COMMAND_CAMERA_DETECTION:
372                         i_value = (int32_t)parameter;
373                         ARDRONE_TOOL_CONFIGURATION_ADDEVENT(detect_type, &i_value, NULL);
374                         break;
375                         
376                 case ARDRONE_COMMAND_ENEMY_SET_PARAM:
377                         i_value = ((ARDRONE_ENEMY_PARAM*)parameter)->color;
378                         ARDRONE_TOOL_CONFIGURATION_ADDEVENT(enemy_colors, &i_value, NULL);
379                         i_value = ((ARDRONE_ENEMY_PARAM*)parameter)->outdoor_shell;
380                         ARDRONE_TOOL_CONFIGURATION_ADDEVENT(enemy_without_shell, &i_value, NULL);
381                         break;
382                         
383                 case ARDRONE_COMMAND_DRONE_LED_ANIM:
384                 {
385                         char param[SMALL_STRING_SIZE];
386                         float_or_int_t freq;
387                         freq.f = ((ARDRONE_LED_ANIMATION_PARAM*)parameter)->frequency;
388                         sprintf(param, "%d,%d,%d", ((ARDRONE_LED_ANIMATION_PARAM*)parameter)->led_anim, freq.i, ((ARDRONE_LED_ANIMATION_PARAM*)parameter)->duration);
389                         ARDRONE_TOOL_CONFIGURATION_ADDEVENT(leds_anim, param, NULL);
390                 }
391                         break;
392                         
393                 case ARDRONE_COMMAND_ENABLE_COMBINED_YAW:
394         {
395             bool_t enable = (bool_t)parameter;
396             i_value = enable ? (ardrone_control_config.control_level | (1 << CONTROL_LEVEL_COMBINED_YAW)) : (ardrone_control_config.control_level & ~(1 << CONTROL_LEVEL_COMBINED_YAW));
397             ARDRONE_TOOL_CONFIGURATION_ADDEVENT(control_level, &i_value, NULL);
398             [hud combinedYawValueChanged:enable];
399         }
400                         break;
401                         
402                 default:
403                         NSLog(@"The ARDRONE_COMMAND_IN %d is not implemented !");
404                         break;
405         }
406 }
407
408 - (void)setDefaultConfigurationForKey:(ARDRONE_CONFIG_KEYS)key withValue:(void *)value
409 {
410         switch (key)
411         {
412 #undef COMMAND_IN_CONFIG_KEY
413 #undef COMMAND_IN_CONFIG_KEY_STRING
414 #define COMMAND_IN_CONFIG_KEY(CASE, KEY, TYPE)                                                                  \
415                 case CASE:                                                                                                                              \
416                         ardrone_application_default_config.KEY = *(TYPE *)(value);                      \
417                         break;
418 #define COMMAND_IN_CONFIG_KEY_STRING(CASE, KEY)                                                                 \
419                 case CASE:                                                                                                                              \
420                         strcpy (ardrone_application_default_config.KEY, (char *)(value));       \
421                         break;
422 #include "ARDroneGeneratedCommandIn.h"
423 #undef COMMAND_IN_CONFIG_KEY
424 #undef COMMAND_IN_CONFIG_KEY_STRING
425                 default:
426                         NSLog(@"The ARDRONE_CONFIG_KEY %d is not implemented !", key);
427                         break;
428         }
429 }
430
431 - (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
432 {
433         return (toInterfaceOrientation == UIInterfaceOrientationLandscapeRight || toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft);
434 }
435
436 - (void)didReceiveMemoryWarning 
437 {
438         // Releases the view if it doesn't have a superview.
439     [super didReceiveMemoryWarning];
440         
441         // Release any cached data, images, etc that aren't in use.
442 }
443
444 - (void)viewDidUnload {
445         // Release any retained subviews of the main view.
446         // e.g. self.myOutlet = nil;
447 }
448
449
450 - (void)dealloc {
451         [self changeState:NO];
452         bContinue = TRUE;
453         
454         [hud release];
455         [menuSettings release];
456         
457         [super dealloc];
458 }
459
460 @end