79d5da1d73a8cf4efb840d0cf8b36f21399ace6f
[mardrone] / mardrone / ARDrone_SDK_Version_1_8_20110726 / ControlEngine / iPhone / Classes / ARDrone.m
1 /**
2  * @file ARDrone.m
3  *
4  * Copyright 2009 Parrot SA. All rights reserved.
5  * @author D HAEYER Frederic
6  * @date 2009/10/26
7  */
8 #import "MainViewController.h"
9 #import "GLViewController.h"
10 #import "InternalProtocols.h"
11 #import "ARDrone.h"
12 #import "TVOut.h"
13
14 //#define DEBUG_ENNEMIES_DETECTON
15 //#define DEBUG_NAVIGATION_DATA
16 //#define DEBUG_DETECTION_CAMERA
17 //#define DEBUG_DRONE_CAMERA
18
19 extern navdata_unpacked_t ctrlnavdata;
20 extern char drone_address[];
21 extern ControlData ctrldata;
22 static bool_t threadStarted = false;
23 char root_dir[256];
24
25 static void ARDroneCallback(ARDRONE_ENGINE_MESSAGE msg)
26 {
27         switch(msg)
28         {
29                 case ARDRONE_ENGINE_INIT_OK:
30                         threadStarted = true;
31                         break;
32                         
33                 default:
34                         break;
35         }
36 }
37
38 @interface ARDrone () <NavdataProtocol>
39         GLViewController *glviewctrl;
40         MainViewController *mainviewctrl;
41         BOOL inGameOnDemand;
42         CGRect screenFrame;
43         id <ARDroneProtocolOut> _uidelegate;
44         ARDroneHUDConfiguration *hudconfig;
45
46 - (void) parrotNavdata:(navdata_unpacked_t*)data;
47 - (void) checkThreadStatus;
48 @end
49
50 /**
51  * Define a few methods to make it possible for the game engine to control the Parrot drone
52  */
53 @implementation ARDrone
54 @synthesize running;
55 @synthesize view;
56
57 /**
58  * Initialize the Parrot library.<br/>
59  * Note: the library will clean-up everything it allocates by itself, when being destroyed (i.e. when its retain count reaches 0).
60  *
61  * @param frame Frame of parent view, used to create the library view (which shall cover the whole screen).
62  * @param inGame Initial state of the game at startup.
63  * @param uidelegate Pointer to the object that implements the Parrot protocol ("ARDroneProtocol"), which will be called whenever the library needs the game engine to change its state.
64  * @return Pointer to the newly initialized Parrot library instance.
65  */
66 - (id) initWithFrame:(CGRect)frame withState:(BOOL)inGame withDelegate:(id <ARDroneProtocolOut>)uidelegate withHUDConfiguration:(ARDroneHUDConfiguration*)hudconfiguration
67 {
68         if((self = [super init]) != nil)
69         {
70                 NSLog(@"Frame ARDrone Engine : %f, %f", frame.size.width, frame.size.height);
71
72 #ifdef ENABLE_AUTO_TVOUT
73                 [[[TVOut alloc] init] setupScreenMirroringWithFramesPerSecond:10];
74 #endif
75
76                 running = NO;
77                 inGameOnDemand = inGame;
78                 threadStarted = false;
79                 _uidelegate = uidelegate;
80                 
81                 // Update user path
82                 [[NSFileManager defaultManager]changeCurrentDirectoryPath:[[NSBundle mainBundle]resourcePath]];
83                 NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); //creates paths so that you can pull the app's path from it
84                 strcpy(root_dir, [[paths objectAtIndex:0] cStringUsingEncoding:NSUTF8StringEncoding]);
85                 
86                 // Create View Controller
87                 glviewctrl = [[GLViewController alloc] initWithFrame:frame withDelegate:self];
88                 
89                 // Create main view controller
90                 initControlData();
91                 mainviewctrl = [[MainViewController alloc] initWithFrame:frame withState:inGame withDelegate:uidelegate withNavdataDelegate:self withControlData:&ctrldata withHUDConfiguration:hudconfiguration];
92                 view = mainviewctrl.view;
93                 
94                 NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"];
95         NSString *username = [NSString stringWithFormat:@".%@:%@", [[UIDevice currentDevice] model], [[UIDevice currentDevice] uniqueIdentifier]];
96                 ardroneEngineStart(ARDroneCallback, [bundleName cStringUsingEncoding:NSUTF8StringEncoding], [username cStringUsingEncoding:NSUTF8StringEncoding]);
97                 [self checkThreadStatus];
98         }
99         
100         return( self );
101 }
102
103 - (void) checkThreadStatus
104 {
105         NSLog(@"%s", __FUNCTION__);
106
107         [mainviewctrl setWifiReachabled:threadStarted];
108
109         if(threadStarted)
110         {
111                 running = YES;
112                 [_uidelegate executeCommandOut:ARDRONE_COMMAND_RUN withParameter:(void*)drone_address fromSender:self];
113                 [self changeState:inGameOnDemand];
114         }
115         else
116         {
117                 [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(checkThreadStatus) userInfo:nil repeats:NO];
118         }
119 }
120
121 /*
122  * Render a frame. Basically, the Parrot Library renders:<ul>
123  * <li> A full screen textured quad in the background (= the video sent by the drone);</li>
124  * <li> A set of elements in the foreground (=HUD).</li>
125  * </ul>
126  */
127 - (void) render
128 {               
129         // Make sure the library is "running"
130         [glviewctrl drawView];
131 }
132
133 - (void) dealloc
134 {
135         [self changeState:NO];
136         
137         [mainviewctrl release];
138         [glviewctrl release];
139         
140         [super dealloc];
141 }
142
143 /**
144  * Set what shall be the orientation of the screen when rendering a frame.
145  *
146  * @param right Orientation of the screen: FALSE for "landscape left", TRUE for "landscape right".
147  */
148 - (void)setScreenOrientationRight:(BOOL)right
149 {
150         NSLog(@"Screen orientation right : %d", right);
151         if(mainviewctrl != nil)
152                 [mainviewctrl setScreenOrientationRight:right];
153         
154         if(glviewctrl != nil)
155                 [glviewctrl setScreenOrientationRight:right];   
156 }
157
158 - (void)parrotNavdata:(navdata_unpacked_t*)data
159 {
160         ardrone_navdata_get_data(data);
161 }
162
163 /**
164  * Get the latest drone's navigation data.
165  *
166  * @param data Pointer to a navigation data structure.
167  */
168 - (void)navigationData:(ARDroneNavigationData*)data
169 {
170         if(view != nil)
171         {
172                 vp_os_memcpy(data, [mainviewctrl navigationData], sizeof(ARDroneNavigationData));
173 #ifdef DEBUG_NAVIGATION_DATA
174                 static int numsamples = 0;
175                 if(numsamples++ > 64)
176                 {
177                         NSLog(@"x : %f, y : %f, z : %f, flying state : %d, navdata video num frame : %d, video num frames : %d", data->angularPosition.x, data->angularPosition.y, data->angularPosition.z, data->flyingState, data->navVideoNumFrames, data->videoNumFrames);          
178                         numsamples = 0;
179                 }
180 #endif
181         }
182 }
183
184 /**
185  * Get the latest detection camera structure (rotation and translation).
186  *
187  * @param data Pointer to a detection camera structure.
188  */
189 - (void)detectionCamera:(ARDroneDetectionCamera*)camera
190 {
191         if(view != nil)
192         {
193                 vp_os_memcpy(camera, [mainviewctrl detectionCamera], sizeof(ARDroneDetectionCamera));
194 #ifdef DEBUG_DETECTION_CAMERA
195                 static int numsamples = 0;
196                 if(numsamples++ > 64)
197                 {
198                         NSLog(@"Detection Camera Rotation : %f %f %f %f %f %f %f %f %f",
199                                         camera->rotation[0][0], camera->rotation[0][1], camera->rotation[0][2],
200                                         camera->rotation[1][0], camera->rotation[1][1], camera->rotation[1][2],
201                                         camera->rotation[2][0], camera->rotation[2][1], camera->rotation[2][2]);
202                         NSLog(@"Detection Camera Translation : %f %f %f", camera->translation[0], camera->translation[1], camera->translation[2]);
203                         NSLog(@"Detection Camera Tag Index : %d", camera->tag_index);
204                         
205                         numsamples = 0;
206                 }
207 #endif
208         }
209 }
210
211 /**
212  * Get the latest drone camera structure (rotation and translation).
213  *
214  * @param data Pointer to a drone camera structure.
215  */
216 - (void)droneCamera:(ARDroneCamera*)camera
217 {
218         if(view != nil)
219         {
220                 vp_os_memcpy(camera, [mainviewctrl droneCamera], sizeof(ARDroneCamera));
221 #ifdef DEBUG_DRONE_CAMERA
222                 static int numsamples = 0;
223                 if(numsamples++ > 64)
224                 {
225                         NSLog(@"Drone Camera Rotation : %f %f %f %f %f %f %f %f %f",
226                                   camera->rotation[0][0], camera->rotation[0][1], camera->rotation[0][2],
227                                   camera->rotation[1][0], camera->rotation[1][1], camera->rotation[1][2],
228                                   camera->rotation[2][0], camera->rotation[2][1], camera->rotation[2][2]);
229                         NSLog(@"Drone Camera Translation : %f %f %f", camera->translation[0], camera->translation[1], camera->translation[2]);
230                         numsamples = 0;
231                 }
232 #endif
233         }
234 }
235
236 /**
237  * Exchange enemies data.<br/>
238  * Note: basically, data should be provided by the Parrot library when in multiplayer mode (enemy type = "HUMAN"), and by the game controller when in single player mode (enemy type = "AI").
239  *
240  * @param data Pointer to an enemies data structure.
241  */
242 - (void)humanEnemiesData:(ARDroneEnemiesData*)data
243 {
244         if(view != nil)
245         {
246                 vp_os_memcpy(data, [mainviewctrl humanEnemiesData], sizeof(ARDroneEnemiesData));
247 #ifdef DEBUG_ENNEMIES_DETECTON
248                 static int old_value = 0;
249                 if(old_value != data->count) 
250                         NSLog(@"enemies detected : %d", data->count);
251                 old_value = data->count;
252 #endif
253         }
254 }
255
256 - (void)changeState:(BOOL)inGame
257 {
258         // Check whether there is a change of state
259         if(threadStarted)
260         {
261                 // Change the state of the library
262                 if(inGame)
263                         ardroneEngineResume();
264                 else
265                         ardroneEnginePause();
266
267                 running = inGame;
268         }
269         else
270         {
271                 inGameOnDemand = inGame;
272         }
273         
274         // Change state of view
275         [mainviewctrl changeState:inGame];
276
277 }
278
279 - (void)executeCommandIn:(ARDRONE_COMMAND_IN_WITH_PARAM)commandIn fromSender:(id)sender refreshSettings:(BOOL)refresh
280 {
281         [mainviewctrl executeCommandIn:commandIn fromSender:sender refreshSettings:refresh];    
282 }
283
284 - (void)executeCommandIn:(ARDRONE_COMMAND_IN)commandId withParameter:(void*)parameter fromSender:(id)sender
285 {
286         [mainviewctrl executeCommandIn:commandId withParameter:parameter fromSender:sender];    
287 }
288
289 - (void)setDefaultConfigurationForKey:(ARDRONE_CONFIG_KEYS)key withValue:(void *)value
290 {
291         [mainviewctrl setDefaultConfigurationForKey:key withValue:value];
292 }
293
294 - (BOOL)checkState
295 {
296         return running;
297 }
298
299 @end