Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
834 - 1
#!/usr/bin/perl
2
#!/usr/bin/perl -d:ptkdb
3
 
4
###############################################################################
5
#
6
# libmksim.pl -  Simple MK simulator
7
#
8
# Copyright (C) 2009  Rainer Walther  (rainerwalther-mail@web.de)
9
#
10
# Creative Commons Lizenz mit den Zusaetzen (by, nc, sa)
11
#
12
# Es ist Ihnen gestattet: 
13
#     * das Werk vervielfältigen, verbreiten und öffentlich zugänglich machen
14
#     * Abwandlungen bzw. Bearbeitungen des Inhaltes anfertigen
15
# 
16
# Zu den folgenden Bedingungen:
17
#     * Namensnennung.
18
#       Sie müssen den Namen des Autors/Rechteinhabers in der von ihm festgelegten Weise nennen.
19
#     * Keine kommerzielle Nutzung.
20
#       Dieses Werk darf nicht für kommerzielle Zwecke verwendet werden.
21
#     * Weitergabe unter gleichen Bedingungen.
22
#       Wenn Sie den lizenzierten Inhalt bearbeiten oder in anderer Weise umgestalten,
23
#       verändern oder als Grundlage für einen anderen Inhalt verwenden,
24
#       dürfen Sie den neu entstandenen Inhalt nur unter Verwendung von Lizenzbedingungen
25
#       weitergeben, die mit denen dieses Lizenzvertrages identisch oder vergleichbar sind.
26
# 
27
# Im Falle einer Verbreitung müssen Sie anderen die Lizenzbedingungen, unter welche dieses
28
# Werk fällt, mitteilen. Am Einfachsten ist es, einen Link auf diese Seite einzubinden.
29
# 
30
# Jede der vorgenannten Bedingungen kann aufgehoben werden, sofern Sie die Einwilligung
31
# des Rechteinhabers dazu erhalten.
32
# 
33
# Diese Lizenz lässt die Urheberpersönlichkeitsrechte unberührt.
34
# 
35
# Weitere Details zur Lizenzbestimmung gibt es hier:
36
#   Kurzform: http://creativecommons.org/licenses/by-nc-sa/3.0/de/
37
#   Komplett: http://creativecommons.org/licenses/by-nc-sa/3.0/de/legalcode
38
#
39
###############################################################################
40
#
41
# 2009-10-10 0.0.1 rw created
42
# 2009-12-05 0.0.2 rw check, if no WP is defined
43
# 2010-01-27 0.0.3 rw UsedCapacity, Current
44
#                     switch of logging while sim is active
45
# 2010-09-15 0.0.4 rw Check invalid $MkSim{'Target_Heading'} >= 360
46
# 2010-11-03 0.0.5 rw NC 0.21
47
#
48
###############################################################################
49
 
50
$Version{'libmksim.pl'} = "0.0.5 - 2010-11-03";
51
 
52
my $Simulator = "OFF";
53
 
54
sub MkSim()
55
    {
56
    # switch off logging
57
    $LogQueue->enqueue( "OFF" );
58
 
59
    my $popup = $main->Toplevel();
60
    $popup->title("MikroKopter Simulator");
61
 
62
    # Catch delete window event and exit sim
63
    $popup->protocol( 'WM_DELETE_WINDOW' => sub
64
        {
65
        &CbSimStop();
66
        $popup->destroy();
67
        });
68
 
69
 
70
    my $menu_bar = $popup->Menu;
71
    $popup->optionAdd("*tearOff", "false");
72
    $popup->configure ('-menu' => $menu_bar);
73
 
74
    my $menu_action = $menu_bar->cascade('-label' => "Action");
75
    $menu_action->command('-label' => "3D Fix",
76
                          '-command' => [\&CbSim3DFix ],
77
                        );
78
    $menu_action->command('-label' => "Make MK Fly",
79
                          '-command' => [\&CbSimMkFly ],
80
                        );
81
    $menu_action->separator;                                   
82
    $menu_action->command('-label' => "Start Simulator",
83
                          '-command' => [\&CbSimStart ],
84
                         );
85
    $menu_action->command('-label' => "Stop Simulator",
86
                          '-command' => [\&CbSimStop ],
87
                        );
88
 
89
    my $frame = $popup->Frame() -> pack('-side' => 'top',
90
                                        '-expand' => 'y',
91
                                        '-anchor' => 's',
92
                                        '-padx' => 5,
93
                                        '-pady' => 5,
94
                                        );
95
 
96
    my $button = $popup->Frame() -> pack('-side' => 'bottom',
97
                                          '-expand' => 'y',
98
                                          '-anchor' => 's',
99
                                          '-padx' => 5,
100
                                          '-pady' => 5,
101
                                          );
102
 
103
     # Exit Button
104
     $button->Button('-text'    => 'Exit',
105
                     '-width' => 10,
106
                     '-command' => sub
107
                {
108
                &CbSimStop();
109
                $popup->destroy();
110
                }) -> pack( '-anchor' => 's',
111
                            '-padx' => 5,
112
                            '-pady' => 5,
113
                          );
114
 
115
 
116
    # Tabs erstellen
117
    my $book = $frame->NoteBook()->pack( -fill=>'both', -expand=>1 );
118
 
119
    #
120
    # Tab: GPS
121
    #
122
    my $GpsTab = $book->add( "GPS", -label=>"GPS" );
123
 
124
    # canvas grid position
125
    my $GpsRow = 0;
126
    my $GpsCol = 0;
127
    my $GpsRowMap = $GpsRow + 1;
128
    my $GpsColMap = $GpsCol;
129
    my $GpsRowAlt = $GpsRow + 2;
130
    my $GpsColAlt = $GpsCol;
131
    my $GpsRowStat = $GpsRow + 4;
132
    my $GpsColStat = $GpsCol;
133
    my $GpsRowSats = $GpsRow + 5;
134
    my $GpsColSats = $GpsCol;
135
 
136
    # Create and scale Photo
137
    my $ImgWidth = "$Cfg->{'map'}->{'SimImageSize'}" || 300;
138
    my $Factor = $MapSizeX / $ImgWidth;
139
 
140
    my $Img1 = $popup->Photo( 'SimFoto',
141
                              '-file' => "$Cfg->{'map'}->{'MapDir'}/$Map{'File'}",
142
                            );
143
    my $Img2 = $popup->Photo ('SimFoto-Resized');
144
    $Img2->copy ( $Img1,
145
                  '-shrink',
146
                  '-subsample' => $Factor, $Factor,
147
                 );
148
 
149
    my $ImgWidth  = $Img2->width;
150
    my $ImgHeight = $Img2->height;
151
    my $ImgScaleX = $MapSizeX / $ImgWidth;
152
    my $ImgScaleY = $MapSizeY / $ImgHeight;
153
 
154
    # display scaled Photo on canvas
155
    my $canvas = $GpsTab->Canvas( '-width'  => $ImgWidth,
156
                                  '-height' => $ImgHeight,
157
                                ) -> grid (-row    => $GpsRowMap,
158
                                           -column => $GpsColMap,
159
                                           -columnspan => 4,
160
                                          );
161
    $canvas->createImage( 0, 0,
162
                          '-tags'   => 'SimMap',
163
                          '-anchor' => 'nw',
164
                          '-image'  => $Img2,
165
                         );
166
 
167
    # Circle-Icon for MK, Target, Home
168
    my $Dia = 14;
169
    my $ImgSplit = $ImgWidth / 4;
170
    my $MkX     = $ImgSplit - $Dia/2;
171
    my $MkY     = $ImgHeight / 2 + $Dia/2;
172
    my $TargetX = $ImgSplit * 2  - $Dia/2;
173
    my $TargetY = $ImgHeight / 2 + $Dia/2;
174
    my $HomeX   = $ImgSplit * 3  - $Dia/2;
175
    my $HomeY   = $ImgHeight / 2 + $Dia/2;
176
 
177
 
178
    ($MkOsd{'CurPos_Lat'}, $MkOsd{'CurPos_Lon'})       = &MapXY2Gps ($MkX * $ImgScaleX, $MkY * $ImgScaleY);
179
    ($MkOsd{'TargetPos_Lat'}, $MkOsd{'TargetPos_Lon'}) = &MapXY2Gps ($TargetX * $ImgScaleX, $TargetY * $ImgScaleY);
180
    ($MkOsd{'HomePos_Lat'}, $MkOsd{'HomePos_Lon'})     = &MapXY2Gps ($HomeX * $ImgScaleX, $HomeY * $ImgScaleY);
181
 
182
    $canvas->createOval ( $HomeX, $HomeY, $HomeX + $Dia, $HomeY + $Dia,
183
                         '-tags'    => "SimHome",
184
                         '-fill'    => $Cfg->{'mkcockpit'}->{'ColorHomeLine'},
185
                         '-outline' => "white",
186
                       );
187
    $canvas->createOval ( $TargetX, $TargetY, $TargetX + $Dia, $TargetY + $Dia,
188
                         '-tags'    => "SimTarget",
189
                         '-fill'    => $Cfg->{'mkcockpit'}->{'ColorTargetLine'},
190
                         '-outline' => "white",
191
                       );
192
    $canvas->createOval ( $MkX, $MkY, $MkX + $Dia, $MkY + $Dia,
193
                         '-tags'    => "SimMk",
194
                         '-fill'    => $Cfg->{'mkcockpit'}->{'ColorMkSatGood'},
195
                         '-outline' => "white",
196
                       );
197
 
198
    # GPS Alt MK
199
    $GpsTab->Label(-text => , $Translate{'CurPos_Alt'},
200
                  )->grid ('-row'    => $GpsRowAlt,
201
                           '-column' => $GpsColAlt,
202
                           '-sticky' => 'w',
203
                         );
204
 
205
    $MkOsd{'CurPos_Alt'} = 0;
206
    $scCurPos_Alt = $GpsTab->Scale(
207
                    '-orient'       => 'vertical',
208
                    '-from'         => 400,
209
                    '-to'           => 0,
210
                    '-tickinterval' => 50,
211
                    '-resolution'   => 1,
212
                    '-label'        => "",
213
                    '-font'         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
214
                    '-length'       => 150,
215
                    '-width'        => 15,
216
                    '-variable'     => \$MkOsd{'CurPos_Alt'},
217
                   )->grid ('-row'    => $GpsRowAlt+1,
218
                            '-column' => $GpsColAlt,
219
                           );
220
 
221
    $MkOsd{'CurPos_Stat'} = 0;
222
    $cbCurPos_Stat = $GpsTab->Checkbutton(
223
                      -text => $Translate{'CurPos_Stat'},
224
                      -offvalue  => 0x00,
225
                      -onvalue   => 0x01,
226
                      -variable  => \$MkOsd{'CurPos_Stat'},
227
                     )->grid (-row    => $GpsRowStat,
228
                              -column => $GpsColStat,
229
                              -columnspan => 2,
230
                              -sticky => 'w',
231
                             );
232
 
233
    # Altimeter
234
    $GpsTab->Label(-text => , $Translate{'Altimeter'},
235
                  )->grid ('-row'    => $GpsRowAlt,
236
                           '-column' => $GpsColAlt +1,
237
                         );
238
 
239
    $MkOsd{'Altimeter'} = 0;
240
    $scAltimeter = $GpsTab->Scale(
241
                  -orient       => 'vertical',
242
                  -from         => 8000,
243
                  -to           => 0,
244
                  -tickinterval => 2000,
245
                  -resolution   => 1,
246
                  -label        => "",
247
                  -font         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
248
                  -length       => 150,
249
                  -width        => 15,
250
                  -variable     => \$MkOsd{'Altimeter'},
251
                  )->grid (-row    => $GpsRowAlt +1,
252
                           -column => $GpsColAlt +1,
253
                          );
254
 
255
    # GPS Alt Target
256
    $GpsTab->Label(-text => , $Translate{'TargetPos_Alt'},
257
                  )->grid ('-row'    => $GpsRowAlt,
258
                           '-column' => $GpsColAlt +2,
259
                         );
260
 
261
    $MkOsd{'TargetPos_Alt'} = 0;
262
    $scTargetPos_Alt = $GpsTab->Scale(
263
                    '-orient'       => 'vertical',
264
                    '-from'         => 400,
265
                    '-to'           => 0,
266
                    '-tickinterval' => 50,
267
                    '-resolution'   => 1,
268
                    '-label'        => "",
269
                    '-font'         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
270
                    '-length'       => 150,
271
                    '-width'        => 15,
272
                    '-variable'     => \$MkOsd{'TargetPos_Alt'},
273
                   )->grid ('-row'    => $GpsRowAlt +1,
274
                            '-column' => $GpsColAlt +2,
275
                           );
276
 
277
    $MkOsd{'TargetPos_Stat'} = 0;
278
    $cbTargetPos_Stat = $GpsTab->Checkbutton(-text => $Translate{'TargetPos_Stat'},
279
                      -offvalue  => 0x00,
280
                      -onvalue   => 0x01,
281
                      -variable  => \$MkOsd{'TargetPos_Stat'},
282
                     )->grid (-row    => $GpsRowStat,
283
                              -column => $GpsColStat +2,
284
                             );
285
 
286
    # GPS Alt Home
287
    $GpsTab->Label(-text => , $Translate{'HomePos_Alt'},
288
                  )->grid ('-row'    => $GpsRowAlt,
289
                           '-column' => $GpsColAlt +3,
290
                         );
291
 
292
    $MkOsd{'HomePos_Alt'} = 0;
293
    $scHomePos_Alt = $GpsTab->Scale(
294
                    '-orient'       => 'vertical',
295
                    '-from'         => 400,
296
                    '-to'           => 0,
297
                    '-tickinterval' => 50,
298
                    '-resolution'   => 1,
299
                    '-label'        => "",
300
                    '-font'         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
301
                    '-length'       => 150,
302
                    '-width'        => 15,
303
                    '-variable'     => \$MkOsd{'HomePos_Alt'},
304
                   )->grid ('-row'    => $GpsRowAlt +1,
305
                            '-column' => $GpsColAlt +3,
306
                           );
307
 
308
    $MkOsd{'HomePos_Stat'} = 0;
309
    $cbHomePos_Stat = $GpsTab->Checkbutton(
310
                      -text => "Home Status",   # $Translate{'HomePos_Stat'},
311
                      -offvalue  => 0x00,
312
                      -onvalue   => 0x01,
313
                      -variable  => \$MkOsd{'HomePos_Stat'},
314
                     )->grid (-row    => $GpsRowStat,
315
                              -column => $GpsColStat +3,
316
                             );
317
 
318
    # Sats in Use
319
    $MkOsd{'SatsInUse'} = 0;
320
    $scSatsInUse = $GpsTab->Scale(
321
                   '-orient'       => 'horizontal',
322
                   '-from'         => 0,
323
                   '-to'           => 12,
324
                   '-resolution'   => 1,
325
                   '-tickinterval' => 1,
326
                   '-label'        => $Translate{'SatsInUse'},
327
                   '-font'         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
328
                   '-length'       => 300,
329
                   '-width'        => 15,
330
                   '-variable'     => \$MkOsd{'SatsInUse'},
331
                   )->grid (-row    => $GpsRowSats,
332
                            -column => $GpsColSats,
333
                            -columnspan => 4,
334
                           );
335
 
336
     # Balloon
337
     my $simballoon = $popup->Balloon();
338
     $simballoon->attach($canvas,
339
                         '-balloonposition' => 'mouse',
340
                         '-state' => 'balloon',
341
                         '-msg' => { 'SimMk'     => 'MikroKopter',
342
                                     'SimTarget' => 'Target',
343
                                     'SimHome'   => 'Home',
344
                                   },
345
                        );
346
 
347
    # Mouse button 1 for MK
348
    my $MkOldx = 0;
349
    my $MkOldy = 0;
350
 
351
    # Pick MK
352
    $canvas->bind('SimMk' => '<Button-1>' => sub
353
        {
354
        # prepare to move
355
        my ($x, $y) = ($Tk::event->x, $Tk::event->y);
356
        $MkOldx = $x;
357
        $MkOldy = $y;
358
        });
359
 
360
    # Move Mk
361
    $canvas->bind('SimMk' => '<Button1-Motion>' => sub
362
        {
363
        my ($x, $y) = ($Tk::event->x, $Tk::event->y);
364
        my $id      = $canvas->find('withtag', 'current');
365
 
366
        my $Dia2 = $Dia/2;
367
        if ( $x < $Dia2 ) { $x = $Dia2 };
368
        if ( $y < $Dia2 ) { $y = $Dia2 };
369
        if ( $x > $ImgWidth - $Dia2 ) { $x = $ImgWidth - $Dia2 };
370
        if ( $y > $ImgHeight - $Dia2) { $y = $ImgHeight - $Dia2 };
371
 
372
        $canvas->move($id => $x - $MkOldx, $y - $MkOldy);
373
        $MkOldx = $x;
374
        $MkOldy = $y;
375
 
376
        ($MkOsd{'CurPos_Lat'}, $MkOsd{'CurPos_Lon'}) = &MapXY2Gps ($x * $ImgScaleX, $y * $ImgScaleY);
377
        });
378
 
379
    # Mouse button 1 for Target
380
    my $TargetOldx = 0;
381
    my $TargetOldy = 0;
382
 
383
    # Pick Target
384
    $canvas->bind('SimTarget' => '<Button-1>' => sub
385
        {
386
        # prepare to move
387
        my ($x, $y) = ($Tk::event->x, $Tk::event->y);
388
        $TargetOldx = $x;
389
        $TargetOldy = $y;
390
        });
391
 
392
    # Move Target
393
    $canvas->bind('SimTarget' => '<Button1-Motion>' => sub
394
        {
395
        my ($x, $y) = ($Tk::event->x, $Tk::event->y);
396
        my $id      = $canvas->find('withtag', 'current');
397
 
398
        my $Dia2 = $Dia/2;
399
        if ( $x < $Dia2 ) { $x = $Dia2 };
400
        if ( $y < $Dia2 ) { $y = $Dia2 };
401
        if ( $x > $ImgWidth - $Dia2 ) { $x = $ImgWidth - $Dia2 };
402
        if ( $y > $ImgHeight - $Dia2) { $y = $ImgHeight - $Dia2 };
403
 
404
        $canvas->move($id => $x - $TargetOldx, $y - $TargetOldy);
405
        $TargetOldx = $x;
406
        $TargetOldy = $y;
407
 
408
        ($MkOsd{'TargetPos_Lat'}, $MkOsd{'TargetPos_Lon'}) = &MapXY2Gps ($x * $ImgScaleX, $y * $ImgScaleY);
409
        });
410
 
411
    # Mouse button 1 for Home
412
    my $HomeOldx = 0;
413
    my $HomeOldy = 0;
414
 
415
    # Pick Home
416
    $canvas->bind('SimHome' => '<Button-1>' => sub
417
        {
418
        # prepare to move
419
        my ($x, $y) = ($Tk::event->x, $Tk::event->y);
420
        $HomeOldx = $x;
421
        $HomeOldy = $y;
422
        });
423
 
424
    # Move Home
425
    $canvas->bind('SimHome' => '<Button1-Motion>' => sub
426
        {
427
        my ($x, $y) = ($Tk::event->x, $Tk::event->y);
428
        my $id      = $canvas->find('withtag', 'current');
429
 
430
        my $Dia2 = $Dia/2;
431
        if ( $x < $Dia2 ) { $x = $Dia2 };
432
        if ( $y < $Dia2 ) { $y = $Dia2 };
433
        if ( $x > $ImgWidth - $Dia2 ) { $x = $ImgWidth - $Dia2 };
434
        if ( $y > $ImgHeight - $Dia2) { $y = $ImgHeight - $Dia2 };
435
 
436
        $canvas->move($id => $x - $HomeOldx, $y - $HomeOldy);
437
        $HomeOldx = $x;
438
        $HomeOldy = $y;
439
 
440
        ($MkOsd{'HomePos_Lat'}, $MkOsd{'HomePos_Lon'}) = &MapXY2Gps ($x * $ImgScaleX, $y * $ImgScaleY);
441
        });
442
 
443
 
444
    #
445
    # Tab: Navigation
446
    #
447
    my $NavTab = $book->add( "Navigation", -label=>"Navigation", );
448
 
449
    my $Row = 0;
450
    my $Col = 0;
451
 
452
    # Waypoint Index
453
    $MkOsd{'WaypointIndex'} = 0;
454
    $scWaypointIndex = $NavTab->Scale(
455
                   -orient       => 'horizontal',
456
                   -from         => 0,
457
                   -to           => 20,
458
                   -tickinterval => 5,
459
                   -resolution   => 1,
460
                   -label        => $Translate{'WaypointIndex'},
461
                   -font         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
462
                   -length       => 300,
463
                   -width        => 15,
464
                   -variable     => \$MkOsd{'WaypointIndex'},
465
                   )->grid (-row    => $Row + 1,
466
                            -column => $Col,
467
                           );
468
 
469
    # Waypoint Number
470
    $MkOsd{'WaypointNumber'} = 0;
471
    $scWaypointNumber = $NavTab->Scale(
472
                   -orient       => 'horizontal',
473
                   -from         => 0,
474
                   -to           => 20,
475
                   -tickinterval => 5,
476
                   -resolution   => 1,
477
                   -label        => $Translate{'WaypointNumber'},
478
                   -font         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
479
                   -length       => 300,
480
                   -width        => 15,
481
                   -variable     => \$MkOsd{'WaypointNumber'},
482
                   )->grid (-row    => $Row + 2,
483
                            -column => $Col,
484
                           );
485
 
486
    # Operating Radius
487
    $MkOsd{'OperatingRadius'} = 250;
488
    $scOperatingRadius = $NavTab->Scale(
489
                   -orient       => 'horizontal',
490
                   -from         => 0,
491
                   -to           => 250,
492
                   -tickinterval => 50,
493
                   -resolution   => 1,
494
                   -label        => "$Translate{'OperatingRadius'} (m)",
495
                   -font         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
496
                   -length       => 300,
497
                   -width        => 15,
498
                   -variable     => \$MkOsd{'OperatingRadius'},
499
                   )->grid (-row    => $Row + 3,
500
                            -column => $Col,
501
                           );
502
 
503
    # TargetPosDev_Dist
504
    $MkOsd{'TargetPosDev_Dist'} = 250;
505
    $scTargetPosDev_Dist = $NavTab->Scale(
506
                   -orient       => 'horizontal',
507
                   -from         => 0,
508
                   -to           => 500,
509
                   -tickinterval => 100,
510
                   -resolution   => 1,
511
                   -label        => "$Translate{'TargetPosDev_Dist'} (dm)",
512
                   -font         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
513
                   -length       => 300,
514
                   -width        => 15,
515
                   -variable     => \$MkOsd{'TargetPosDev_Dist'},
516
                   )->grid (-row    => $Row + 4,
517
                            -column => $Col,
518
                           );
519
 
520
 
521
    #
522
    # Tab: MK
523
    #
524
    my $MkTab = $book->add( "MikroKopter1", -label=>"MikroKopter 1", );
525
 
526
    my $Row = 0;
527
    my $Col = 0;
528
 
529
    # Battery
530
    $MkOsd{'UBat'} = 12.6;
531
    $scUBat = $MkTab->Scale(
532
                   -orient       => 'horizontal',
533
                   -from         => 6.0,
534
                   -to           => 18.0,
535
                   -tickinterval => 2,
536
                   -resolution   => 0.1,
537
                   -label        => "$Translate{'UBat'} (V)",
538
                   -font         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
539
                   -length       => 200,
540
                   -width        => 15,
541
                   -variable     => \$MkOsd{'UBat'},
542
                   )->grid (-row    => $Row,
543
                            -column => $Col,
544
                           );
545
 
546
    # RC Quality
547
    $MkOsd{'RC_Quality'} = 190;
548
    $scRC_Quality = $MkTab->Scale(
549
                  -orient       => 'horizontal',
550
                  -from         => 0,
551
                  -to           => 200,
552
                  -tickinterval => 50,
553
                  -resolution   => 1,
554
                  -label        => $Translate{'RC_Quality'},
555
                  -font         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
556
                  -length       => 200,
557
                  -width        => 15,
558
                  -variable     => \$MkOsd{'RC_Quality'},
559
                  )->grid (-row    => $Row +1,
560
                           -column => $Col,
561
                          );
562
    # CompassHeading
563
    $MkOsd{'CompassHeading'} = 0;
564
    $scCompassHeading = $MkTab->Scale(
565
                  -orient       => 'horizontal',
566
                  -from         => 0,
567
                  -to           => 360,
568
                  -tickinterval => 45,
569
                  -resolution   => 1,
570
                  -label        => $Translate{'CompassHeading'},
571
                  -font         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
572
                  -length       => 200,
573
                  -width        => 15,
574
                  -variable     => \$MkOsd{'CompassHeading'},
575
                  )->grid (-row    => $Row +2,
576
                           -rowspan => 4,
577
                           -column => $Col,
578
                          );
579
 
580
    # GPS Groundspeed
581
    $MkOsd{'GroundSpeed'} = 0;
582
    $scGroundSpeed = $MkTab->Scale(
583
                  -orient       => 'horizontal',
584
                  -from         => 0,
585
                  -to           => 1000,
586
                  -tickinterval => 200,
587
                  -resolution   => 1,
588
                  -label        => "$Translate{'GroundSpeed'} (dm/s)",
589
                  -font         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
590
                  -length       => 200,
591
                  -width        => 15,
592
                  -variable     => \$MkOsd{'GroundSpeed'},
593
                  )->grid (-row    => $Row + 6,
594
                           -rowspan => 4,
595
                           -column => $Col,
596
                          );
597
 
598
    # GPS Heading
599
    $MkOsd{'Heading'} = 0;
600
    $scHeading = $MkTab->Scale(
601
                  -orient       => 'horizontal',
602
                  -from         => 0,
603
                  -to           => 360,
604
                  -tickinterval => 45,
605
                  -resolution   => 1,
606
                  -label        => "$Translate{'Heading'}",
607
                  -font         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
608
                  -length       => 200,
609
                  -width        => 15,
610
                  -variable     => \$MkOsd{'Heading'},
611
                  )->grid (-row    => $Row + 10,
612
                           -rowspan => 4,
613
                           -column => $Col,
614
                          );
615
 
616
    # Variometer
617
    $MkOsd{'Variometer'} = 0;
618
    $scVariometer = $MkTab->Scale(
619
                  -orient       => 'vertical',
620
                  -from         => 30,
621
                  -to           => -30,
622
                  -tickinterval => 10,
623
                  -resolution   => 1,
624
                  -label        => $Translate{'Variometer'},
625
                  -font         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
626
                  -length       => 100,
627
                  -width        => 15,
628
                  -variable     => \$MkOsd{'Variometer'},
629
                  )->grid (-row    => $Row,
630
                           -rowspan => 2,
631
                           -column => $Col + 1,
632
                          );
633
 
634
    my $DataLink = 1;
635
    $cbDataLink = $MkTab->Checkbutton(
636
                        -text => $Translate{'DataLink'},
637
                        -offvalue => 0x00,
638
                        -onvalue  => 0x01,
639
                        -variable  => \$DataLink,
640
                       )->grid (-row    => $Row + 2,
641
                                -column => $Col +1,
642
                                -sticky=>'w',
643
                                -ipadx => 10,
644
                               );
645
 
646
    $MkTab->Label(-text => "$Translate{'MKFlags'}: --------",
647
                 )->grid (-row    => $Row +3,
648
                          -column => $Col +1,
649
                          -sticky=>'w',
650
                          -ipadx => 10,
651
                         );
652
    my $MkMotorRun = 0;
653
    $cbMkMotorRun = $MkTab->Checkbutton(
654
                        -text => $Translate{'MkMotorRun'},
655
                        -offvalue => 0x00,
656
                        -onvalue  => 0x01,
657
                        -variable  => \$MkMotorRun,
658
                       )->grid (-row    => $Row + 4,
659
                                -column => $Col +1,
660
                                -sticky=>'w',
661
                                -ipadx => 10,
662
                               );
663
    my $MkFly = 0;
664
    $cbMkFly = $MkTab->Checkbutton(
665
                      -text => $Translate{'MkFly'},
666
                      -variable  => \$MkFly,
667
                      -offvalue => 0x00,
668
                      -onvalue  => 0x02,
669
                     )->grid (-row    => $Row + 5,
670
                              -column => $Col +1,
671
                                -sticky=>'w',
672
                                -ipadx => 10,
673
                             );
674
    my $MkCalibrate = 0;
675
    $cbMkCalibrate = $MkTab->Checkbutton(
676
                      -text => $Translate{'MkCalibrate'},
677
                      -variable  => \$MkCalibrate,
678
                      -offvalue => 0x00,
679
                      -onvalue  => 0x04,
680
                     )->grid (-row    => $Row + 6,
681
                              -column => $Col +1,
682
                               -sticky=>'w',
683
                               -ipadx => 10,
684
                             );
685
    my $MkStart = 0;
686
    $cbMkStart = $MkTab->Checkbutton(
687
                      -text => $Translate{'MkStart'},
688
                      -variable  => \$MkStart,
689
                      -offvalue => 0x00,
690
                      -onvalue  => 0x08,
691
                     )->grid (-row    => $Row + 7,
692
                              -column => $Col + 1,
693
                              -sticky=>'w',
694
                              -ipadx => 10,
695
                             );
696
    my $MkEmergency = 0;
697
    $cbMkEmergency = $MkTab->Checkbutton(
698
                      -text => $Translate{'MkEmergency'},
699
                      -variable  => \$MkEmergency,
700
                      -offvalue => 0x00,
701
                      -onvalue  => 0x10,
702
                     )->grid (-row    => $Row + 8,
703
                              -column => $Col + 1,
704
                              -sticky=>'w',
705
                              -ipadx => 10,
706
                             );
707
 
708
    $MkTab->Label(-text => "$Translate{'NCFlags'}: --------",
709
                 )->grid (-row    => $Row + 9,
710
                          -column => $Col + 1,
711
                           -sticky=>'w',
712
                           -ipadx => 10,
713
                         );
714
    my $NcFlagFree = 0;
715
    $cbNcFlagFree = $MkTab->Checkbutton(
716
                      -text => $Translate{'NcFlagFree'},
717
                      -offvalue => 0x00,
718
                      -onvalue  => 0x01,
719
                      -variable  => \$NcFlagFree,
720
                     )->grid (-row    => $Row + 10,
721
                              -column => $Col + 1,
722
                              -sticky=>'w',
723
                              -ipadx => 10,
724
                             );
725
    my $NcFlagPH = 0;
726
    $cbNcFlagPH = $MkTab->Checkbutton(
727
                      -text => $Translate{'NcFlagPH'},
728
                      -offvalue => 0x00,
729
                      -onvalue  => 0x02,
730
                      -variable  => \$NcFlagPH,
731
                     )->grid (-row    => $Row + 11,
732
                              -column => $Col + 1,
733
                              -sticky=>'w',
734
                              -ipadx => 10,
735
                             );
736
    my $NcFlagCH = 0;
737
    $cbNcFlagCH = $MkTab->Checkbutton(
738
                      -text => $Translate{'NcFlagCH'},
739
                      -offvalue => 0x00,
740
                      -onvalue  => 0x04,
741
                      -variable  => \$NcFlagCH,
742
                     )->grid (-row    => $Row + 12,
743
                              -column => $Col + 1,
744
                              -sticky=>'w',
745
                              -ipadx => 10,
746
                             );
747
    my $NcFlagRangeLimit = 0;
748
    $cbNcFlagRangeLimit = $MkTab->Checkbutton(
749
                      -text => $Translate{'NcFlagRangeLimit'},
750
                      -offvalue => 0x00,
751
                      -onvalue  => 0x08,
752
                      -variable  => \$NcFlagRangeLimit,
753
                     )->grid (-row    => $Row + 13,
754
                              -column => $Col + 1,
755
                              -sticky=>'w',
756
                              -ipadx => 10,
757
                             );
758
    my $NcFlagNoSerialLink = 0;
759
    $cbNcFlagNoSerialLink = $MkTab->Checkbutton(
760
                      -text => $Translate{'NcFlagNoSerialLink'},
761
                      -offvalue => 0x00,
762
                      -onvalue  => 0x10,
763
                      -variable  => \$NcFlagNoSerialLink,
764
                     )->grid (-row    => $Row + 14,
765
                              -column => $Col + 1,
766
                              -sticky=>'w',
767
                              -ipadx => 10,
768
                             );
769
    my $NcFlagTargetReached = 0;
770
    $cbNcFlagTargetReached = $MkTab->Checkbutton(
771
                      -text => $Translate{'NcFlagTargetReached'},
772
                      -offvalue => 0x00,
773
                      -onvalue  => 0x20,
774
                      -variable  => \$NcFlagTargetReached,
775
                     )->grid (-row    => $Row + 15,
776
                              -column => $Col + 1,
777
                              -sticky=>'w',
778
                              -ipadx => 10,
779
                             );
780
 
781
    my $NcFlagManualControl = 0;
782
    $cbNcFlagManualControl = $MkTab->Checkbutton(
783
                      -text => $Translate{'NcFlagManualControl'},
784
                      -offvalue => 0x00,
785
                      -onvalue  => 0x40,
786
                      -variable  => \$NcFlagManualControl
787
                     )->grid (-row    => $Row + 16,
788
                              -column => $Col + 1,
789
                              -sticky=>'w',
790
                              -ipadx => 10,
791
                             );
792
 
793
    my $NcFlagGpsOk = 0;
794
    $cbNcFlagGpsOk = $MkTab->Checkbutton(
795
                      -text => $Translate{'NcFlagGpsOk'},
796
                      -offvalue => 0x00,
797
                      -onvalue  => 0x80,
798
                      -variable  => \$NcFlagGpsOk
799
                     )->grid (-row    => $Row + 17,
800
                              -column => $Col + 1,
801
                              -sticky=>'w',
802
                              -ipadx => 10,
803
                             );
804
 
805
    #
806
    # Tab: MK 2
807
    #
808
    my $Mk2Tab = $book->add( "MikroKopter2", -label=>"MikroKopter 2", );
809
 
810
    my $Row = 0;
811
    my $Col = 0;
812
 
813
    # Current
814
    $MkOsd{'Current'} = 0;
815
    $scCurrent = $Mk2Tab->Scale(
816
                  -orient       => 'horizontal',
817
                  -from         => 0,
818
                  -to           => 50,
819
                  -tickinterval => 10,
820
                  -resolution   => 1,
821
                  -label        => "$Translate{'Current'} (A)",
822
                  -font         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
823
                  -length       => 300,
824
                  -width        => 15,
825
                  -variable     => \$MkOsd{'Current'},
826
                  )->grid (-row    => $Row,
827
                           -column => $Col,
828
                          );
829
 
830
    # Used Capacity
831
    $MkOsd{'UsedCapacity'} = 0;
832
    $scUsedCapacity = $Mk2Tab->Scale(
833
                  -orient       => 'horizontal',
834
                  -from         => 0,
835
                  -to           => 5000,
836
                  -tickinterval => 1000,
837
                  -resolution   => 50,
838
                  -label        => "$Translate{'UsedCapacity'} (mAh)",
839
                  -font         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
840
                  -length       => 300,
841
                  -width        => 15,
842
                  -variable     => \$MkOsd{'UsedCapacity'},
843
                  )->grid (-row    => $Row + 1,
844
                           -column => $Col,
845
                          );
846
 
847
    #
848
    # Tab: Simulator
849
    #
850
    my $MkTab = $book->add( "Simulator", -label=>"Simulator", );
851
 
852
    my $Row = 0;
853
    my $Col = 0;
854
 
855
    # Speed
856
    my $SimSpeed = 20;  # km/h
857
    $scSimSpeed = $MkTab->Scale(
858
                  -orient       => 'horizontal',
859
                  -from         => 0,
860
                  -to           => 50,
861
                  -tickinterval => 5,
862
                  -resolution   => 1,
863
                  -label        => "Speed (km/h)",
864
                  -font         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
865
                  -length       => 300,
866
                  -width        => 15,
867
                  -variable     => \$SimSpeed,
868
                  )->grid (-row    => $Row,
869
                           -column => $Col,
870
                          );
871
 
872
    # Acceleration
873
    my $SimAcc = 10;  # m/s**2
874
    $scSimAcc = $MkTab->Scale(
875
                  -orient       => 'horizontal',
876
                  -from         => 0,
877
                  -to           => 30,
878
                  -tickinterval => 5,
879
                  -resolution   => 0.5,
880
                  -label        => "Acceleration (m/s**2)",
881
                  -font         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
882
                  -length       => 300,
883
                  -width        => 15,
884
                  -variable     => \$SimAcc,
885
                  )->grid (-row    => $Row +1,
886
                           -column => $Col,
887
                          );
888
 
889
 
890
    my $Speed  = 0;  # Current Mk Speed
891
    my $SpeedN = 0;  # Speed North
892
    my $SpeedE = 0;  # Speed East
893
 
894
 
895
    #
896
    # Timer
897
    #
898
    my $SimTimebase = 100;    # Simulator Timebase in ms
899
    $popup->repeat ($SimTimebase, sub
900
        {
901
        lock (%MkOsd);              # until end of block
902
 
903
        $MkOsd{'MKFlags'} = $MkMotorRun | $MkFly | $MkCalibrate | $MkStart | $MkEmergency;
904
        $MkOsd{'NCFlags'} = $NcFlagFree | $NcFlagPH | $NcFlagCH | $NcFlagRangeLimit |
905
                            $NcFlagNoSerialLink | $NcFlagTargetReached |
906
                            $NcFlagManualControl | $NcFlagGpsOk;
907
 
908
        # Calibration sequence
909
        if ( $CalibCount > 0 )
910
            {
911
            $CalibCount ++;
912
            }
913
        if ( $CalibCount > 2 * 1000 / $SimTimebase )  # 2s
914
            {
915
            $cbMkCalibrate-> deselect();
916
            $cbMkStart->deselect();
917
 
918
            $cbMkMotorRun->select();
919
            $cbMkFly->select();
920
 
921
            $CalibCount = 0;
922
            }
923
 
924
        #
925
        # Simulator
926
        #
927
        if ( $Simulator =~ /ON/i and
928
             $MkSim{'Target_Lat'} ne ""  and $MkSim{'Target_Lon'} ne "" )
929
            {
930
            # Set Target-Pos
931
            $MkOsd{'TargetPos_Lat'} = $MkSim{'Target_Lat'};
932
            $MkOsd{'TargetPos_Lon'} = $MkSim{'Target_Lon'};
933
            $MkOsd{'TargetPos_Alt'} = $MkSim{'Target_Alt'};
934
            $MkOsd{'TargetPos_Stat'} = 1;
935
 
936
            my ($HomeDist, $HomeBearing) = &MapGpsTo($MkOsd{'HomePos_Lat'},   $MkOsd{'HomePos_Lon'},
937
                                                     $MkOsd{'TargetPos_Lat'}, $MkOsd{'TargetPos_Lon'} );
938
            if ( $HomeDist > $MkOsd{'OperatingRadius'} )
939
                {
940
                # Target entsprechend Operation Radius neu berechnen
941
                $HomeDist = $MkOsd{'OperatingRadius'};
942
                ($MkOsd{'TargetPos_Lat'}, $MkOsd{'TargetPos_Lon'}) = &MapGpsAt($MkOsd{'HomePos_Lat'}, $MkOsd{'HomePos_Lon'},
943
                                                                               $HomeDist, $HomeBearing);
944
                $cbNcFlagRangeLimit->select;
945
                }
946
            else
947
                {
948
                $cbNcFlagRangeLimit->deselect;
949
                }
950
 
951
            #
952
            # Mk physics
953
            # Move MK to Target with constant acceleration
954
            #
955
            my ($Dist, $Bearing) = &MapGpsTo($MkOsd{'CurPos_Lat'}, $MkOsd{'CurPos_Lon'},
956
                                             $MkOsd{'TargetPos_Lat'}, $MkOsd{'TargetPos_Lon'} );
957
 
958
            $MkOsd{'TargetPosDev_Dist'} = $Dist * 10;  # in dm
959
            $MkOsd{'TargetPosDev_Bearing'} = $Bearing;
960
 
961
            my $AccN = $SimAcc * cos (deg2rad $Bearing);     # Acceleration North
962
            my $AccE = $SimAcc * sin (deg2rad $Bearing);     # Acceleration East
963
            my $t = $SimTimebase / 1000;
964
 
965
            $SpeedN = $SpeedN + $AccN * $t;  # Speed North
966
            $SpeedE = $SpeedE + $AccE * $t;  # Speed East
967
            $Speed  = sqrt ($SpeedN * $SpeedN + $SpeedE * $SpeedE);
968
            $SpeedBearing = rad2deg (atan2 ($SpeedE, $SpeedN));
969
 
970
            if ( $Speed >= $SimSpeed/3.6 )
971
                {
972
                # Limit maximum Speed
973
                $SpeedN = $SimSpeed/3.6 * cos (deg2rad $SpeedBearing);
974
                $SpeedE = $SimSpeed/3.6 * sin (deg2rad $SpeedBearing);
975
                $Speed = $SimSpeed/3.6;
976
                }
977
 
978
            my $BreakDist = 5;
979
            if ( $Dist <= $BreakDist )
980
                {
981
                $Speed = $SimSpeed/3.6 - $SimSpeed/3.6 * (1 - $Dist/$BreakDist);
982
                $SpeedN = $Speed * cos (deg2rad $SpeedBearing);
983
                $SpeedE = $Speed * sin (deg2rad $SpeedBearing);
984
                $AccN = 0;
985
                $AccE = 0;
986
                }
987
 
988
            # Distance to go in this loop
989
            my $GoDistN = $SpeedN * $t + 0.5 * $AccN * $t * $t;
990
            my $GoDistE = $SpeedE * $t + 0.5 * $AccE * $t * $t;
991
            my $GoDist = sqrt ( $GoDistN * $GoDistN + $GoDistE * $GoDistE);
992
            my $GoBearing = rad2deg (atan2 ($GoDistE, $GoDistN));
993
 
994
            if ($GoDist > 0 )
995
                {
996
                ($MkOsd{'CurPos_Lat'}, $MkOsd{'CurPos_Lon'}) = &MapGpsAt($MkOsd{'CurPos_Lat'}, $MkOsd{'CurPos_Lon'},
997
                                                                         $GoDist, $GoBearing);            
998
                }
999
 
1000
            if ( $Dist < $MkSim{'Target_ToleranceRadius'} )
1001
                {
1002
                $cbNcFlagTargetReached -> select();
1003
                }
1004
            else
1005
                {
1006
                $cbNcFlagTargetReached -> deselect();
1007
                }
1008
 
1009
            # GPS Groundspeed, Heading
1010
            $MkOsd{'GroundSpeed'}  = $Speed * 100;  # dm/s
1011
            $MkOsd{'Heading'} = $SpeedBearing % 360;
1012
 
1013
            # Heading
1014
            if ( $MkSim{'Target_Heading'} != 0  and  $MkSim{'Target_Heading'} < 360 )
1015
                {
1016
                $scCompassHeading -> set($MkSim{'Target_Heading'});
1017
                }
1018
            }
1019
 
1020
        # update display
1021
        $scTargetPos_Alt -> set($MkOsd{'TargetPos_Alt'});
1022
        $scTargetPosDev_Dist -> set ($MkOsd{'TargetPosDev_Dist'});
1023
        $scGroundSpeed -> set($MkOsd{'GroundSpeed'});
1024
        $scHeading -> set($MkOsd{'Heading'});
1025
        $scWaypointNumber -> set ($MkOsd{'WaypointNumber'});
1026
        $scWaypointIndex -> set ($MkOsd{'WaypointIndex'});
1027
 
1028
        # move MK symbol on canvas
1029
        my ($x, $y) = &MapGps2XY ($MkOsd{'CurPos_Lat'}, $MkOsd{'CurPos_Lon'});
1030
        $x = $x / $ImgScaleX;
1031
        $y = $y / $ImgScaleY;
1032
        $canvas->coords ('SimMk', $x, $y, $x + $Dia, $y + $Dia);
1033
 
1034
        # move Home symbol on canvas
1035
        my ($x, $y) = &MapGps2XY ($MkOsd{'HomePos_Lat'}, $MkOsd{'HomePos_Lon'});
1036
        $x = $x / $ImgScaleX;
1037
        $y = $y / $ImgScaleY;
1038
        $canvas->coords ('SimHome', $x, $y, $x + $Dia, $y + $Dia);
1039
 
1040
        # move Target symbol on canvas
1041
        my ($x, $y) = &MapGps2XY ($MkOsd{'TargetPos_Lat'}, $MkOsd{'TargetPos_Lon'});
1042
        $x = $x / $ImgScaleX;
1043
        $y = $y / $ImgScaleY;
1044
        $canvas->coords ('SimTarget', $x, $y, $x + $Dia, $y + $Dia);
1045
 
1046
        if ( $DataLink)
1047
            {
1048
            # Timestamp, wann der Datensatz geschrieben wurde
1049
            $MkOsd{'_Timestamp'} = time;
1050
            }
1051
 
1052
        });
1053
    }
1054
 
1055
# Make MK Fly
1056
sub CbSimMkFly
1057
    {
1058
    $scWaypointIndex->set(5);
1059
    $scWaypointNumber->set(10);
1060
    $cbNcFlagCH->select();
1061
 
1062
    # start calibration sequence
1063
    $cbMkCalibrate-> select();
1064
    $cbMkStart->select();
1065
    $CalibCount = 1;
1066
    }
1067
 
1068
 
1069
# 3D Fix
1070
sub CbSim3DFix
1071
    {
1072
    my $Alt = 50;
1073
    $scCurPos_Alt->set($Alt);
1074
    $scAltimeter->set($Alt * $Cfg->{'map'}->{'AltFactor'});
1075
 
1076
    $scSatsInUse->set(10);
1077
    $cbCurPos_Stat->select();
1078
    $cbTargetPos_Stat->select();
1079
    $cbHomePos_Stat->select();
1080
    $cbNcFlagGpsOk->select();
1081
 
1082
    # Set Home-Pos to Cur-Pos
1083
    $MkOsd{'HomePos_Lat'} = $MkOsd{'CurPos_Lat'};
1084
    $MkOsd{'HomePos_Lon'} = $MkOsd{'CurPos_Lon'};
1085
 
1086
    $scGroundSpeed->set(400);
1087
    $scHeading->set(0);
1088
    }
1089
 
1090
# Switch Simulator ON
1091
sub CbSimStart
1092
    {
1093
    $Simulator = "ON";
1094
 
1095
    # Only one Target from Player
1096
    $MkOsd{'WaypointNumber'} = 1;
1097
    $MkOsd{'WaypointIndex'} = 0;
1098
    }
1099
 
1100
 
1101
# Switch Simulator OFF
1102
sub CbSimStop
1103
    {
1104
    $Simulator = "OFF";
1105
 
1106
    # switch on logging
1107
    $MkOsd{'_Timestamp'} = 0;
1108
    $LogQueue->enqueue( "LOG" );
1109
    }
1110
 
1111
 
1112
1;
1113
 
1114
__END__