0,0 → 1,1130 |
#!/usr/bin/perl |
#!/usr/bin/perl -d:ptkdb |
|
############################################################################### |
# |
# libmap.pl - Conversion GPS and Map-X/Y Coordinates |
# |
# Copyright (C) 2009 Rainer Walther (rainerwalther-mail@web.de) |
# |
# Creative Commons Lizenz mit den Zusaetzen (by, nc, sa) |
# |
# Es ist Ihnen gestattet: |
# * das Werk vervielfältigen, verbreiten und öffentlich zugänglich machen |
# * Abwandlungen bzw. Bearbeitungen des Inhaltes anfertigen |
# |
# Zu den folgenden Bedingungen: |
# * Namensnennung. |
# Sie müssen den Namen des Autors/Rechteinhabers in der von ihm festgelegten Weise nennen. |
# * Keine kommerzielle Nutzung. |
# Dieses Werk darf nicht für kommerzielle Zwecke verwendet werden. |
# * Weitergabe unter gleichen Bedingungen. |
# Wenn Sie den lizenzierten Inhalt bearbeiten oder in anderer Weise umgestalten, |
# verändern oder als Grundlage für einen anderen Inhalt verwenden, |
# dürfen Sie den neu entstandenen Inhalt nur unter Verwendung von Lizenzbedingungen |
# weitergeben, die mit denen dieses Lizenzvertrages identisch oder vergleichbar sind. |
# |
# Im Falle einer Verbreitung müssen Sie anderen die Lizenzbedingungen, unter welche dieses |
# Werk fällt, mitteilen. Am Einfachsten ist es, einen Link auf diese Seite einzubinden. |
# |
# Jede der vorgenannten Bedingungen kann aufgehoben werden, sofern Sie die Einwilligung |
# des Rechteinhabers dazu erhalten. |
# |
# Diese Lizenz lässt die Urheberpersönlichkeitsrechte unberührt. |
# |
# Weitere Details zur Lizenzbestimmung gibt es hier: |
# Kurzform: http://creativecommons.org/licenses/by-nc-sa/3.0/de/ |
# Komplett: http://creativecommons.org/licenses/by-nc-sa/3.0/de/legalcode |
# |
############################################################################### |
# |
# 2009-10-10 0.0.1 rw created |
# 2009-12-05 0.0.2 rw check, if no WP is defined |
# 2010-01-27 0.0.3 rw UsedCapacity, Current |
# switch of logging while sim is active |
# 2010-09-15 0.0.4 rw Check invalid $MkSim{'Target_Heading'} >= 360 |
# |
############################################################################### |
|
$Version{'libmksim.pl'} = "0.0.4 - 2010-09-15"; |
|
my $Simulator = "OFF"; |
|
sub MkSim() |
{ |
# switch off logging |
$LogQueue->enqueue( "OFF" ); |
|
my $popup = $main->Toplevel(); |
$popup->title("MikroKopter Simulator"); |
|
# Catch delete window event and exit sim |
$popup->protocol( 'WM_DELETE_WINDOW' => sub |
{ |
&CbSimStop(); |
$popup->destroy(); |
}); |
|
|
my $menu_bar = $popup->Menu; |
$popup->optionAdd("*tearOff", "false"); |
$popup->configure ('-menu' => $menu_bar); |
|
my $menu_action = $menu_bar->cascade('-label' => "Action"); |
$menu_action->command('-label' => "3D Fix", |
'-command' => [\&CbSim3DFix ], |
); |
$menu_action->command('-label' => "Make MK Fly", |
'-command' => [\&CbSimMkFly ], |
); |
$menu_action->separator; |
$menu_action->command('-label' => "Start Simulator", |
'-command' => [\&CbSimStart ], |
); |
$menu_action->command('-label' => "Stop Simulator", |
'-command' => [\&CbSimStop ], |
); |
|
my $frame = $popup->Frame() -> pack('-side' => 'top', |
'-expand' => 'y', |
'-anchor' => 's', |
'-padx' => 5, |
'-pady' => 5, |
); |
|
my $button = $popup->Frame() -> pack('-side' => 'bottom', |
'-expand' => 'y', |
'-anchor' => 's', |
'-padx' => 5, |
'-pady' => 5, |
); |
|
# Exit Button |
$button->Button('-text' => 'Exit', |
'-width' => 10, |
'-command' => sub |
{ |
&CbSimStop(); |
$popup->destroy(); |
}) -> pack( '-anchor' => 's', |
'-padx' => 5, |
'-pady' => 5, |
); |
|
|
# Tabs erstellen |
my $book = $frame->NoteBook()->pack( -fill=>'both', -expand=>1 ); |
|
# |
# Tab: GPS |
# |
my $GpsTab = $book->add( "GPS", -label=>"GPS" ); |
|
# canvas grid position |
my $GpsRow = 0; |
my $GpsCol = 0; |
my $GpsRowMap = $GpsRow + 1; |
my $GpsColMap = $GpsCol; |
my $GpsRowAlt = $GpsRow + 2; |
my $GpsColAlt = $GpsCol; |
my $GpsRowStat = $GpsRow + 4; |
my $GpsColStat = $GpsCol; |
my $GpsRowSats = $GpsRow + 5; |
my $GpsColSats = $GpsCol; |
|
# Create and scale Photo |
my $ImgWidth = "$Cfg->{'map'}->{'SimImageSize'}" || 300; |
my $Factor = $MapSizeX / $ImgWidth; |
|
my $Img1 = $popup->Photo( 'SimFoto', |
'-file' => "$Cfg->{'map'}->{'MapDir'}/$Map{'File'}", |
); |
my $Img2 = $popup->Photo ('SimFoto-Resized'); |
$Img2->copy ( $Img1, |
'-shrink', |
'-subsample' => $Factor, $Factor, |
); |
|
my $ImgWidth = $Img2->width; |
my $ImgHeight = $Img2->height; |
my $ImgScaleX = $MapSizeX / $ImgWidth; |
my $ImgScaleY = $MapSizeY / $ImgHeight; |
|
# display scaled Photo on canvas |
my $canvas = $GpsTab->Canvas( '-width' => $ImgWidth, |
'-height' => $ImgHeight, |
) -> grid (-row => $GpsRowMap, |
-column => $GpsColMap, |
-columnspan => 4, |
); |
$canvas->createImage( 0, 0, |
'-tags' => 'SimMap', |
'-anchor' => 'nw', |
'-image' => $Img2, |
); |
|
# Circle-Icon for MK, Target, Home |
my $Dia = 14; |
my $ImgSplit = $ImgWidth / 4; |
my $MkX = $ImgSplit - $Dia/2; |
my $MkY = $ImgHeight / 2 + $Dia/2; |
my $TargetX = $ImgSplit * 2 - $Dia/2; |
my $TargetY = $ImgHeight / 2 + $Dia/2; |
my $HomeX = $ImgSplit * 3 - $Dia/2; |
my $HomeY = $ImgHeight / 2 + $Dia/2; |
|
|
($MkOsd{'CurPos_Lat'}, $MkOsd{'CurPos_Lon'}) = &MapXY2Gps ($MkX * $ImgScaleX, $MkY * $ImgScaleY); |
($MkOsd{'TargetPos_Lat'}, $MkOsd{'TargetPos_Lon'}) = &MapXY2Gps ($TargetX * $ImgScaleX, $TargetY * $ImgScaleY); |
($MkOsd{'HomePos_Lat'}, $MkOsd{'HomePos_Lon'}) = &MapXY2Gps ($HomeX * $ImgScaleX, $HomeY * $ImgScaleY); |
|
$canvas->createOval ( $HomeX, $HomeY, $HomeX + $Dia, $HomeY + $Dia, |
'-tags' => "SimHome", |
'-fill' => $Cfg->{'mkcockpit'}->{'ColorHomeLine'}, |
'-outline' => "white", |
); |
$canvas->createOval ( $TargetX, $TargetY, $TargetX + $Dia, $TargetY + $Dia, |
'-tags' => "SimTarget", |
'-fill' => $Cfg->{'mkcockpit'}->{'ColorTargetLine'}, |
'-outline' => "white", |
); |
$canvas->createOval ( $MkX, $MkY, $MkX + $Dia, $MkY + $Dia, |
'-tags' => "SimMk", |
'-fill' => $Cfg->{'mkcockpit'}->{'ColorMkSatGood'}, |
'-outline' => "white", |
); |
|
# GPS Alt MK |
$GpsTab->Label(-text => , $Translate{'CurPos_Alt'}, |
)->grid ('-row' => $GpsRowAlt, |
'-column' => $GpsColAlt, |
'-sticky' => 'w', |
); |
|
$MkOsd{'CurPos_Alt'} = 0; |
$scCurPos_Alt = $GpsTab->Scale( |
'-orient' => 'vertical', |
'-from' => 400, |
'-to' => 0, |
'-tickinterval' => 50, |
'-resolution' => 1, |
'-label' => "", |
'-font' => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1', |
'-length' => 150, |
'-width' => 15, |
'-variable' => \$MkOsd{'CurPos_Alt'}, |
)->grid ('-row' => $GpsRowAlt+1, |
'-column' => $GpsColAlt, |
); |
|
$MkOsd{'CurPos_Stat'} = 0; |
$cbCurPos_Stat = $GpsTab->Checkbutton( |
-text => $Translate{'CurPos_Stat'}, |
-offvalue => 0x00, |
-onvalue => 0x01, |
-variable => \$MkOsd{'CurPos_Stat'}, |
)->grid (-row => $GpsRowStat, |
-column => $GpsColStat, |
-columnspan => 2, |
-sticky => 'w', |
); |
|
# Altimeter |
$GpsTab->Label(-text => , $Translate{'Altimeter'}, |
)->grid ('-row' => $GpsRowAlt, |
'-column' => $GpsColAlt +1, |
); |
|
$MkOsd{'Altimeter'} = 0; |
$scAltimeter = $GpsTab->Scale( |
-orient => 'vertical', |
-from => 8000, |
-to => 0, |
-tickinterval => 2000, |
-resolution => 1, |
-label => "", |
-font => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1', |
-length => 150, |
-width => 15, |
-variable => \$MkOsd{'Altimeter'}, |
)->grid (-row => $GpsRowAlt +1, |
-column => $GpsColAlt +1, |
); |
|
# GPS Alt Target |
$GpsTab->Label(-text => , $Translate{'TargetPos_Alt'}, |
)->grid ('-row' => $GpsRowAlt, |
'-column' => $GpsColAlt +2, |
); |
|
$MkOsd{'TargetPos_Alt'} = 0; |
$scTargetPos_Alt = $GpsTab->Scale( |
'-orient' => 'vertical', |
'-from' => 400, |
'-to' => 0, |
'-tickinterval' => 50, |
'-resolution' => 1, |
'-label' => "", |
'-font' => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1', |
'-length' => 150, |
'-width' => 15, |
'-variable' => \$MkOsd{'TargetPos_Alt'}, |
)->grid ('-row' => $GpsRowAlt +1, |
'-column' => $GpsColAlt +2, |
); |
|
$MkOsd{'TargetPos_Stat'} = 0; |
$cbTargetPos_Stat = $GpsTab->Checkbutton(-text => $Translate{'TargetPos_Stat'}, |
-offvalue => 0x00, |
-onvalue => 0x01, |
-variable => \$MkOsd{'TargetPos_Stat'}, |
)->grid (-row => $GpsRowStat, |
-column => $GpsColStat +2, |
); |
|
# GPS Alt Home |
$GpsTab->Label(-text => , $Translate{'HomePos_Alt'}, |
)->grid ('-row' => $GpsRowAlt, |
'-column' => $GpsColAlt +3, |
); |
|
$MkOsd{'HomePos_Alt'} = 0; |
$scHomePos_Alt = $GpsTab->Scale( |
'-orient' => 'vertical', |
'-from' => 400, |
'-to' => 0, |
'-tickinterval' => 50, |
'-resolution' => 1, |
'-label' => "", |
'-font' => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1', |
'-length' => 150, |
'-width' => 15, |
'-variable' => \$MkOsd{'HomePos_Alt'}, |
)->grid ('-row' => $GpsRowAlt +1, |
'-column' => $GpsColAlt +3, |
); |
|
$MkOsd{'HomePos_Stat'} = 0; |
$cbHomePos_Stat = $GpsTab->Checkbutton( |
-text => "Home Status", # $Translate{'HomePos_Stat'}, |
-offvalue => 0x00, |
-onvalue => 0x01, |
-variable => \$MkOsd{'HomePos_Stat'}, |
)->grid (-row => $GpsRowStat, |
-column => $GpsColStat +3, |
); |
|
# Sats in Use |
$MkOsd{'SatsInUse'} = 0; |
$scSatsInUse = $GpsTab->Scale( |
'-orient' => 'horizontal', |
'-from' => 0, |
'-to' => 12, |
'-resolution' => 1, |
'-tickinterval' => 1, |
'-label' => $Translate{'SatsInUse'}, |
'-font' => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1', |
'-length' => 300, |
'-width' => 15, |
'-variable' => \$MkOsd{'SatsInUse'}, |
)->grid (-row => $GpsRowSats, |
-column => $GpsColSats, |
-columnspan => 4, |
); |
|
# Balloon |
my $simballoon = $popup->Balloon(); |
$simballoon->attach($canvas, |
'-balloonposition' => 'mouse', |
'-state' => 'balloon', |
'-msg' => { 'SimMk' => 'MikroKopter', |
'SimTarget' => 'Target', |
'SimHome' => 'Home', |
}, |
); |
|
# Mouse button 1 for MK |
my $MkOldx = 0; |
my $MkOldy = 0; |
|
# Pick MK |
$canvas->bind('SimMk' => '<Button-1>' => sub |
{ |
# prepare to move |
my ($x, $y) = ($Tk::event->x, $Tk::event->y); |
$MkOldx = $x; |
$MkOldy = $y; |
}); |
|
# Move Mk |
$canvas->bind('SimMk' => '<Button1-Motion>' => sub |
{ |
my ($x, $y) = ($Tk::event->x, $Tk::event->y); |
my $id = $canvas->find('withtag', 'current'); |
|
my $Dia2 = $Dia/2; |
if ( $x < $Dia2 ) { $x = $Dia2 }; |
if ( $y < $Dia2 ) { $y = $Dia2 }; |
if ( $x > $ImgWidth - $Dia2 ) { $x = $ImgWidth - $Dia2 }; |
if ( $y > $ImgHeight - $Dia2) { $y = $ImgHeight - $Dia2 }; |
|
$canvas->move($id => $x - $MkOldx, $y - $MkOldy); |
$MkOldx = $x; |
$MkOldy = $y; |
|
($MkOsd{'CurPos_Lat'}, $MkOsd{'CurPos_Lon'}) = &MapXY2Gps ($x * $ImgScaleX, $y * $ImgScaleY); |
}); |
|
# Mouse button 1 for Target |
my $TargetOldx = 0; |
my $TargetOldy = 0; |
|
# Pick Target |
$canvas->bind('SimTarget' => '<Button-1>' => sub |
{ |
# prepare to move |
my ($x, $y) = ($Tk::event->x, $Tk::event->y); |
$TargetOldx = $x; |
$TargetOldy = $y; |
}); |
|
# Move Target |
$canvas->bind('SimTarget' => '<Button1-Motion>' => sub |
{ |
my ($x, $y) = ($Tk::event->x, $Tk::event->y); |
my $id = $canvas->find('withtag', 'current'); |
|
my $Dia2 = $Dia/2; |
if ( $x < $Dia2 ) { $x = $Dia2 }; |
if ( $y < $Dia2 ) { $y = $Dia2 }; |
if ( $x > $ImgWidth - $Dia2 ) { $x = $ImgWidth - $Dia2 }; |
if ( $y > $ImgHeight - $Dia2) { $y = $ImgHeight - $Dia2 }; |
|
$canvas->move($id => $x - $TargetOldx, $y - $TargetOldy); |
$TargetOldx = $x; |
$TargetOldy = $y; |
|
($MkOsd{'TargetPos_Lat'}, $MkOsd{'TargetPos_Lon'}) = &MapXY2Gps ($x * $ImgScaleX, $y * $ImgScaleY); |
}); |
|
# Mouse button 1 for Home |
my $HomeOldx = 0; |
my $HomeOldy = 0; |
|
# Pick Home |
$canvas->bind('SimHome' => '<Button-1>' => sub |
{ |
# prepare to move |
my ($x, $y) = ($Tk::event->x, $Tk::event->y); |
$HomeOldx = $x; |
$HomeOldy = $y; |
}); |
|
# Move Home |
$canvas->bind('SimHome' => '<Button1-Motion>' => sub |
{ |
my ($x, $y) = ($Tk::event->x, $Tk::event->y); |
my $id = $canvas->find('withtag', 'current'); |
|
my $Dia2 = $Dia/2; |
if ( $x < $Dia2 ) { $x = $Dia2 }; |
if ( $y < $Dia2 ) { $y = $Dia2 }; |
if ( $x > $ImgWidth - $Dia2 ) { $x = $ImgWidth - $Dia2 }; |
if ( $y > $ImgHeight - $Dia2) { $y = $ImgHeight - $Dia2 }; |
|
$canvas->move($id => $x - $HomeOldx, $y - $HomeOldy); |
$HomeOldx = $x; |
$HomeOldy = $y; |
|
($MkOsd{'HomePos_Lat'}, $MkOsd{'HomePos_Lon'}) = &MapXY2Gps ($x * $ImgScaleX, $y * $ImgScaleY); |
}); |
|
|
# |
# Tab: Navigation |
# |
my $NavTab = $book->add( "Navigation", -label=>"Navigation", ); |
|
my $Row = 0; |
my $Col = 0; |
|
# Waypoint Index |
$MkOsd{'WaypointIndex'} = 0; |
$scWaypointIndex = $NavTab->Scale( |
-orient => 'horizontal', |
-from => 0, |
-to => 20, |
-tickinterval => 5, |
-resolution => 1, |
-label => $Translate{'WaypointIndex'}, |
-font => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1', |
-length => 300, |
-width => 15, |
-variable => \$MkOsd{'WaypointIndex'}, |
)->grid (-row => $Row + 1, |
-column => $Col, |
); |
|
# Waypoint Number |
$MkOsd{'WaypointNumber'} = 0; |
$scWaypointNumber = $NavTab->Scale( |
-orient => 'horizontal', |
-from => 0, |
-to => 20, |
-tickinterval => 5, |
-resolution => 1, |
-label => $Translate{'WaypointNumber'}, |
-font => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1', |
-length => 300, |
-width => 15, |
-variable => \$MkOsd{'WaypointNumber'}, |
)->grid (-row => $Row + 2, |
-column => $Col, |
); |
|
# Operating Radius |
$MkOsd{'OperatingRadius'} = 250; |
$scOperatingRadius = $NavTab->Scale( |
-orient => 'horizontal', |
-from => 0, |
-to => 250, |
-tickinterval => 50, |
-resolution => 1, |
-label => "$Translate{'OperatingRadius'} (m)", |
-font => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1', |
-length => 300, |
-width => 15, |
-variable => \$MkOsd{'OperatingRadius'}, |
)->grid (-row => $Row + 3, |
-column => $Col, |
); |
|
# TargetPosDev_Dist |
$MkOsd{'TargetPosDev_Dist'} = 250; |
$scTargetPosDev_Dist = $NavTab->Scale( |
-orient => 'horizontal', |
-from => 0, |
-to => 500, |
-tickinterval => 100, |
-resolution => 1, |
-label => "$Translate{'TargetPosDev_Dist'} (dm)", |
-font => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1', |
-length => 300, |
-width => 15, |
-variable => \$MkOsd{'TargetPosDev_Dist'}, |
)->grid (-row => $Row + 4, |
-column => $Col, |
); |
|
|
# |
# Tab: MK |
# |
my $MkTab = $book->add( "MikroKopter1", -label=>"MikroKopter 1", ); |
|
my $Row = 0; |
my $Col = 0; |
|
# Battery |
$MkOsd{'UBat'} = 12.6; |
$scUBat = $MkTab->Scale( |
-orient => 'horizontal', |
-from => 6.0, |
-to => 18.0, |
-tickinterval => 2, |
-resolution => 0.1, |
-label => "$Translate{'UBat'} (V)", |
-font => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1', |
-length => 200, |
-width => 15, |
-variable => \$MkOsd{'UBat'}, |
)->grid (-row => $Row, |
-column => $Col, |
); |
|
# RC Quality |
$MkOsd{'RC_Quality'} = 190; |
$scRC_Quality = $MkTab->Scale( |
-orient => 'horizontal', |
-from => 0, |
-to => 200, |
-tickinterval => 50, |
-resolution => 1, |
-label => $Translate{'RC_Quality'}, |
-font => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1', |
-length => 200, |
-width => 15, |
-variable => \$MkOsd{'RC_Quality'}, |
)->grid (-row => $Row +1, |
-column => $Col, |
); |
# CompassHeading |
$MkOsd{'CompassHeading'} = 0; |
$scCompassHeading = $MkTab->Scale( |
-orient => 'horizontal', |
-from => 0, |
-to => 360, |
-tickinterval => 45, |
-resolution => 1, |
-label => $Translate{'CompassHeading'}, |
-font => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1', |
-length => 200, |
-width => 15, |
-variable => \$MkOsd{'CompassHeading'}, |
)->grid (-row => $Row +2, |
-rowspan => 4, |
-column => $Col, |
); |
|
# GPS Groundspeed |
$MkOsd{'GroundSpeed'} = 0; |
$scGroundSpeed = $MkTab->Scale( |
-orient => 'horizontal', |
-from => 0, |
-to => 1000, |
-tickinterval => 200, |
-resolution => 1, |
-label => "$Translate{'GroundSpeed'} (dm/s)", |
-font => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1', |
-length => 200, |
-width => 15, |
-variable => \$MkOsd{'GroundSpeed'}, |
)->grid (-row => $Row + 6, |
-rowspan => 4, |
-column => $Col, |
); |
|
# GPS Speed North |
$MkNcDebug{'Analog_21'} = 0; |
$scAnalog_21 = $MkTab->Scale( |
-orient => 'horizontal', |
-from => -1000, |
-to => 1000, |
-tickinterval => 400, |
-resolution => 1, |
-label => "$Translate{'Analog_21'} (dm/s)", |
-font => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1', |
-length => 200, |
-width => 15, |
-variable => \$MkNcDebug{'Analog_21'}, |
)->grid (-row => $Row + 10, |
-rowspan => 4, |
-column => $Col, |
); |
|
# GPS Speed East |
$MkNcDebug{'Analog_22'} = 0; |
$scAnalog_22 = $MkTab->Scale( |
-orient => 'horizontal', |
-from => -1000, |
-to => 1000, |
-tickinterval => 400, |
-resolution => 1, |
-label => "$Translate{'Analog_22'} (dm/s)", |
-font => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1', |
-length => 200, |
-width => 15, |
-variable => \$MkNcDebug{'Analog_22'}, |
)->grid (-row => $Row + 14, |
-rowspan => 4, |
-column => $Col, |
); |
|
# Variometer |
$MkOsd{'Variometer'} = 0; |
$scVariometer = $MkTab->Scale( |
-orient => 'vertical', |
-from => 30, |
-to => -30, |
-tickinterval => 10, |
-resolution => 1, |
-label => $Translate{'Variometer'}, |
-font => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1', |
-length => 100, |
-width => 15, |
-variable => \$MkOsd{'Variometer'}, |
)->grid (-row => $Row, |
-rowspan => 2, |
-column => $Col + 1, |
); |
|
my $DataLink = 1; |
$cbDataLink = $MkTab->Checkbutton( |
-text => $Translate{'DataLink'}, |
-offvalue => 0x00, |
-onvalue => 0x01, |
-variable => \$DataLink, |
)->grid (-row => $Row + 2, |
-column => $Col +1, |
-sticky=>'w', |
-ipadx => 10, |
); |
|
$MkTab->Label(-text => "", # space |
)->grid (-row => $Row +3, |
-column => $Col +1, |
-sticky=>'w', |
-ipadx => 10, |
); |
|
$MkTab->Label(-text => "$Translate{'MKFlags'}: --------", |
)->grid (-row => $Row +4, |
-column => $Col +1, |
-sticky=>'w', |
-ipadx => 10, |
); |
my $MkMotorRun = 0; |
$cbMkMotorRun = $MkTab->Checkbutton( |
-text => $Translate{'MkMotorRun'}, |
-offvalue => 0x00, |
-onvalue => 0x01, |
-variable => \$MkMotorRun, |
)->grid (-row => $Row + 5, |
-column => $Col +1, |
-sticky=>'w', |
-ipadx => 10, |
); |
my $MkFly = 0; |
$cbMkFly = $MkTab->Checkbutton( |
-text => $Translate{'MkFly'}, |
-variable => \$MkFly, |
-offvalue => 0x00, |
-onvalue => 0x02, |
)->grid (-row => $Row + 6, |
-column => $Col +1, |
-sticky=>'w', |
-ipadx => 10, |
); |
my $MkCalibrate = 0; |
$cbMkCalibrate = $MkTab->Checkbutton( |
-text => $Translate{'MkCalibrate'}, |
-variable => \$MkCalibrate, |
-offvalue => 0x00, |
-onvalue => 0x04, |
)->grid (-row => $Row + 7, |
-column => $Col +1, |
-sticky=>'w', |
-ipadx => 10, |
); |
my $MkStart = 0; |
$cbMkStart = $MkTab->Checkbutton( |
-text => $Translate{'MkStart'}, |
-variable => \$MkStart, |
-offvalue => 0x00, |
-onvalue => 0x08, |
)->grid (-row => $Row + 8, |
-column => $Col + 1, |
-sticky=>'w', |
-ipadx => 10, |
); |
my $MkEmergency = 0; |
$cbMkEmergency = $MkTab->Checkbutton( |
-text => $Translate{'MkEmergency'}, |
-variable => \$MkEmergency, |
-offvalue => 0x00, |
-onvalue => 0x10, |
)->grid (-row => $Row + 9, |
-column => $Col + 1, |
-sticky=>'w', |
-ipadx => 10, |
); |
|
$MkTab->Label(-text => "$Translate{'NCFlags'}: --------", |
)->grid (-row => $Row + 10, |
-column => $Col + 1, |
-sticky=>'w', |
-ipadx => 10, |
); |
my $NcFlagFree = 0; |
$cbNcFlagFree = $MkTab->Checkbutton( |
-text => $Translate{'NcFlagFree'}, |
-offvalue => 0x00, |
-onvalue => 0x01, |
-variable => \$NcFlagFree, |
)->grid (-row => $Row + 11, |
-column => $Col + 1, |
-sticky=>'w', |
-ipadx => 10, |
); |
my $NcFlagPH = 0; |
$cbNcFlagPH = $MkTab->Checkbutton( |
-text => $Translate{'NcFlagPH'}, |
-offvalue => 0x00, |
-onvalue => 0x02, |
-variable => \$NcFlagPH, |
)->grid (-row => $Row + 12, |
-column => $Col + 1, |
-sticky=>'w', |
-ipadx => 10, |
); |
my $NcFlagCH = 0; |
$cbNcFlagCH = $MkTab->Checkbutton( |
-text => $Translate{'NcFlagCH'}, |
-offvalue => 0x00, |
-onvalue => 0x04, |
-variable => \$NcFlagCH, |
)->grid (-row => $Row + 13, |
-column => $Col + 1, |
-sticky=>'w', |
-ipadx => 10, |
); |
my $NcFlagRangeLimit = 0; |
$cbNcFlagRangeLimit = $MkTab->Checkbutton( |
-text => $Translate{'NcFlagRangeLimit'}, |
-offvalue => 0x00, |
-onvalue => 0x08, |
-variable => \$NcFlagRangeLimit, |
)->grid (-row => $Row + 14, |
-column => $Col + 1, |
-sticky=>'w', |
-ipadx => 10, |
); |
my $NcFlagNoSerialLink = 0; |
$cbNcFlagNoSerialLink = $MkTab->Checkbutton( |
-text => $Translate{'NcFlagNoSerialLink'}, |
-offvalue => 0x00, |
-onvalue => 0x10, |
-variable => \$NcFlagNoSerialLink, |
)->grid (-row => $Row + 15, |
-column => $Col + 1, |
-sticky=>'w', |
-ipadx => 10, |
); |
my $NcFlagTargetReached = 0; |
$cbNcFlagTargetReached = $MkTab->Checkbutton( |
-text => $Translate{'NcFlagTargetReached'}, |
-offvalue => 0x00, |
-onvalue => 0x20, |
-variable => \$NcFlagTargetReached, |
)->grid (-row => $Row + 16, |
-column => $Col + 1, |
-sticky=>'w', |
-ipadx => 10, |
); |
|
my $NcFlagManualControl = 0; |
$cbNcFlagManualControl = $MkTab->Checkbutton( |
-text => $Translate{'NcFlagManualControl'}, |
-offvalue => 0x00, |
-onvalue => 0x40, |
-variable => \$NcFlagManualControl |
)->grid (-row => $Row + 17, |
-column => $Col + 1, |
-sticky=>'w', |
-ipadx => 10, |
); |
|
# |
# Tab: MK 2 |
# |
my $Mk2Tab = $book->add( "MikroKopter2", -label=>"MikroKopter 2", ); |
|
my $Row = 0; |
my $Col = 0; |
|
# Current |
$MkOsd{'Current'} = 0; |
$scCurrent = $Mk2Tab->Scale( |
-orient => 'horizontal', |
-from => 0, |
-to => 50, |
-tickinterval => 10, |
-resolution => 1, |
-label => "$Translate{'Current'} (A)", |
-font => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1', |
-length => 300, |
-width => 15, |
-variable => \$MkOsd{'Current'}, |
)->grid (-row => $Row, |
-column => $Col, |
); |
|
# Used Capacity |
$MkOsd{'UsedCapacity'} = 0; |
$scUsedCapacity = $Mk2Tab->Scale( |
-orient => 'horizontal', |
-from => 0, |
-to => 5000, |
-tickinterval => 1000, |
-resolution => 50, |
-label => "$Translate{'UsedCapacity'} (mAh)", |
-font => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1', |
-length => 300, |
-width => 15, |
-variable => \$MkOsd{'UsedCapacity'}, |
)->grid (-row => $Row + 1, |
-column => $Col, |
); |
|
# |
# Tab: Simulator |
# |
my $MkTab = $book->add( "Simulator", -label=>"Simulator", ); |
|
my $Row = 0; |
my $Col = 0; |
|
# Speed |
my $SimSpeed = 20; # km/h |
$scSimSpeed = $MkTab->Scale( |
-orient => 'horizontal', |
-from => 0, |
-to => 50, |
-tickinterval => 5, |
-resolution => 1, |
-label => "Speed (km/h)", |
-font => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1', |
-length => 300, |
-width => 15, |
-variable => \$SimSpeed, |
)->grid (-row => $Row, |
-column => $Col, |
); |
|
# Acceleration |
my $SimAcc = 10; # m/s**2 |
$scSimAcc = $MkTab->Scale( |
-orient => 'horizontal', |
-from => 0, |
-to => 30, |
-tickinterval => 5, |
-resolution => 0.5, |
-label => "Acceleration (m/s**2)", |
-font => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1', |
-length => 300, |
-width => 15, |
-variable => \$SimAcc, |
)->grid (-row => $Row +1, |
-column => $Col, |
); |
|
|
my $Speed = 0; # Current Mk Speed |
my $SpeedN = 0; # Speed North |
my $SpeedE = 0; # Speed East |
|
|
# |
# Timer |
# |
my $SimTimebase = 100; # Simulator Timebase in ms |
$popup->repeat ($SimTimebase, sub |
{ |
lock (%MkOsd); # until end of block |
|
$MkOsd{'MKFlags'} = $MkMotorRun | $MkFly | $MkCalibrate | $MkStart | $MkEmergency; |
$MkOsd{'NCFlags'} = $NcFlagFree | $NcFlagPH | $NcFlagCH | $NcFlagRangeLimit | |
$NcFlagNoSerialLink | $NcFlagTargetReached | $NcFlagManualControl; |
|
# Calibration sequence |
if ( $CalibCount > 0 ) |
{ |
$CalibCount ++; |
} |
if ( $CalibCount > 2 * 1000 / $SimTimebase ) # 2s |
{ |
$cbMkCalibrate-> deselect(); |
$cbMkStart->deselect(); |
|
$cbMkMotorRun->select(); |
$cbMkFly->select(); |
|
$CalibCount = 0; |
} |
|
# |
# Simulator |
# |
if ( $Simulator =~ /ON/i and |
$MkSim{'Target_Lat'} ne "" and $MkSim{'Target_Lon'} ne "" ) |
{ |
# Set Target-Pos |
$MkOsd{'TargetPos_Lat'} = $MkSim{'Target_Lat'}; |
$MkOsd{'TargetPos_Lon'} = $MkSim{'Target_Lon'}; |
$MkOsd{'TargetPos_Alt'} = $MkSim{'Target_Alt'}; |
$MkOsd{'TargetPos_Stat'} = 1; |
|
my ($HomeDist, $HomeBearing) = &MapGpsTo($MkOsd{'HomePos_Lat'}, $MkOsd{'HomePos_Lon'}, |
$MkOsd{'TargetPos_Lat'}, $MkOsd{'TargetPos_Lon'} ); |
if ( $HomeDist > $MkOsd{'OperatingRadius'} ) |
{ |
# Target entsprechend Operation Radius neu berechnen |
$HomeDist = $MkOsd{'OperatingRadius'}; |
($MkOsd{'TargetPos_Lat'}, $MkOsd{'TargetPos_Lon'}) = &MapGpsAt($MkOsd{'HomePos_Lat'}, $MkOsd{'HomePos_Lon'}, |
$HomeDist, $HomeBearing); |
$cbNcFlagRangeLimit->select; |
} |
else |
{ |
$cbNcFlagRangeLimit->deselect; |
} |
|
# |
# Mk physics |
# Move MK to Target with constant acceleration |
# |
my ($Dist, $Bearing) = &MapGpsTo($MkOsd{'CurPos_Lat'}, $MkOsd{'CurPos_Lon'}, |
$MkOsd{'TargetPos_Lat'}, $MkOsd{'TargetPos_Lon'} ); |
|
$MkOsd{'TargetPosDev_Dist'} = $Dist * 10; # in dm |
$MkOsd{'TargetPosDev_Bearing'} = $Bearing; |
|
my $AccN = $SimAcc * cos (deg2rad $Bearing); # Acceleration North |
my $AccE = $SimAcc * sin (deg2rad $Bearing); # Acceleration East |
my $t = $SimTimebase / 1000; |
|
$SpeedN = $SpeedN + $AccN * $t; # Speed North |
$SpeedE = $SpeedE + $AccE * $t; # Speed East |
$Speed = sqrt ($SpeedN * $SpeedN + $SpeedE * $SpeedE); |
|
if ( $Speed >= $SimSpeed/3.6 ) |
{ |
# Limit maximum Speed |
my $SpeedBearing = rad2deg (atan2 ($SpeedE, $SpeedN)); |
|
$SpeedN = $SimSpeed/3.6 * cos (deg2rad $SpeedBearing); |
$SpeedE = $SimSpeed/3.6 * sin (deg2rad $SpeedBearing); |
$Speed = $SimSpeed/3.6; |
} |
|
my $BreakDist = 5; |
if ( $Dist <= $BreakDist ) |
{ |
$Speed = $SimSpeed/3.6 - $SimSpeed/3.6 * (1 - $Dist/$BreakDist); |
my $SpeedBearing = rad2deg (atan2 ($SpeedE, $SpeedN)); |
$SpeedN = $Speed * cos (deg2rad $SpeedBearing); |
$SpeedE = $Speed * sin (deg2rad $SpeedBearing); |
$AccN = 0; |
$AccE = 0; |
} |
|
# Distance to go in this loop |
my $GoDistN = $SpeedN * $t + 0.5 * $AccN * $t * $t; |
my $GoDistE = $SpeedE * $t + 0.5 * $AccE * $t * $t; |
my $GoDist = sqrt ( $GoDistN * $GoDistN + $GoDistE * $GoDistE); |
my $GoBearing = rad2deg (atan2 ($GoDistE, $GoDistN)); |
|
if ($GoDist > 0 ) |
{ |
($MkOsd{'CurPos_Lat'}, $MkOsd{'CurPos_Lon'}) = &MapGpsAt($MkOsd{'CurPos_Lat'}, $MkOsd{'CurPos_Lon'}, |
$GoDist, $GoBearing); |
} |
|
if ( $Dist < $MkSim{'Target_ToleranceRadius'} ) |
{ |
$cbNcFlagTargetReached -> select(); |
} |
else |
{ |
$cbNcFlagTargetReached -> deselect(); |
} |
|
# GPS Groundspeed, North, East |
$MkOsd{'GroundSpeed'} = $Speed * 100; # dm/s |
$MkNcDebug{'Analog_21'} = $SpeedN * 100; |
$MkNcDebug{'Analog_22'} = $SpeedE * 100; |
|
# Heading |
if ( $MkSim{'Target_Heading'} != 0 and $MkSim{'Target_Heading'} < 360 ) |
{ |
$scCompassHeading -> set($MkSim{'Target_Heading'}); |
} |
|
} |
|
# update display |
$scAnalog_21 -> set($MkNcDebug{'Analog_21'}); |
$scAnalog_22 -> set($MkNcDebug{'Analog_22'}); |
$scTargetPos_Alt -> set($MkOsd{'TargetPos_Alt'}); |
$scTargetPosDev_Dist -> set ($MkOsd{'TargetPosDev_Dist'}); |
$scGroundSpeed -> set($MkOsd{'GroundSpeed'}); |
$scWaypointNumber -> set ($MkOsd{'WaypointNumber'}); |
$scWaypointIndex -> set ($MkOsd{'WaypointIndex'}); |
|
# move MK symbol on canvas |
my ($x, $y) = &MapGps2XY ($MkOsd{'CurPos_Lat'}, $MkOsd{'CurPos_Lon'}); |
$x = $x / $ImgScaleX; |
$y = $y / $ImgScaleY; |
$canvas->coords ('SimMk', $x, $y, $x + $Dia, $y + $Dia); |
|
# move Home symbol on canvas |
my ($x, $y) = &MapGps2XY ($MkOsd{'HomePos_Lat'}, $MkOsd{'HomePos_Lon'}); |
$x = $x / $ImgScaleX; |
$y = $y / $ImgScaleY; |
$canvas->coords ('SimHome', $x, $y, $x + $Dia, $y + $Dia); |
|
# move Target symbol on canvas |
my ($x, $y) = &MapGps2XY ($MkOsd{'TargetPos_Lat'}, $MkOsd{'TargetPos_Lon'}); |
$x = $x / $ImgScaleX; |
$y = $y / $ImgScaleY; |
$canvas->coords ('SimTarget', $x, $y, $x + $Dia, $y + $Dia); |
|
if ( $DataLink) |
{ |
# Timestamp, wann der Datensatz geschrieben wurde |
$MkOsd{'_Timestamp'} = time; |
} |
|
}); |
} |
|
# Make MK Fly |
sub CbSimMkFly |
{ |
$scWaypointIndex->set(5); |
$scWaypointNumber->set(10); |
$cbNcFlagCH->select(); |
|
# start calibration sequence |
$cbMkCalibrate-> select(); |
$cbMkStart->select(); |
$CalibCount = 1; |
} |
|
|
# 3D Fix |
sub CbSim3DFix |
{ |
my $Alt = 50; |
$scCurPos_Alt->set($Alt); |
$scAltimeter->set($Alt * $Cfg->{'map'}->{'AltFactor'}); |
|
$scSatsInUse->set(10); |
$cbCurPos_Stat->select(); |
$cbTargetPos_Stat->select(); |
$cbHomePos_Stat->select(); |
|
# Set Home-Pos to Cur-Pos |
$MkOsd{'HomePos_Lat'} = $MkOsd{'CurPos_Lat'}; |
$MkOsd{'HomePos_Lon'} = $MkOsd{'CurPos_Lon'}; |
|
$scGroundSpeed->set(400); |
$scAnalog_21->set(10); |
$scAnalog_22->set(10); |
} |
|
# Switch Simulator ON |
sub CbSimStart |
{ |
$Simulator = "ON"; |
|
# Only one Target from Player |
$MkOsd{'WaypointNumber'} = 1; |
$MkOsd{'WaypointIndex'} = 0; |
} |
|
|
# Switch Simulator OFF |
sub CbSimStop |
{ |
$Simulator = "OFF"; |
|
# switch on logging |
$MkOsd{'_Timestamp'} = 0; |
$LogQueue->enqueue( "LOG" ); |
} |
|
|
1; |
|
__END__ |