2 ******************************************************************************
4 * @file Antennatrackwidget.cpp
5 * @author Sami Korhonen & the OpenPilot team Copyright (C) 2010.
6 * @addtogroup GCSPlugins GCS Plugins
8 * @addtogroup AntennaTrackGadgetPlugin Antenna Track Gadget Plugin
10 * @brief A gadget that communicates with antenna tracker and enables basic configuration
11 *****************************************************************************/
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 * You should have received a copy of the GNU General Public License along
24 * with this program; if not, write to the Free Software Foundation, Inc.,
25 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include "antennatrackwidget.h"
29 #include "extensionsystem/pluginmanager.h"
30 #include "uavobjectmanager.h"
38 * Initialize the widget
40 AntennaTrackWidget::AntennaTrackWidget(QWidget
*parent
) : QWidget(parent
)
48 AntennaTrackWidget::~AntennaTrackWidget()
50 void AntennaTrackWidget::setPort(QPointer
<QSerialPort
> portx
)
55 void AntennaTrackWidget::dumpPacket(const QString
&packet
)
57 textBrowser
->append(packet
);
58 if (textBrowser
->document()->lineCount() > 200) {
59 QTextCursor tc
= textBrowser
->textCursor();
60 tc
.movePosition(QTextCursor::Start
);
61 tc
.movePosition(QTextCursor::Down
, QTextCursor::KeepAnchor
);
62 tc
.movePosition(QTextCursor::StartOfLine
, QTextCursor::KeepAnchor
);
63 tc
.removeSelectedText();
67 void AntennaTrackWidget::setPosition(double lat
, double lon
, double alt
)
71 double deg
= floor(fabs(lat
));
72 double min
= (fabs(lat
) - deg
) * 60;
75 str1
.sprintf("%.0f%c%.3f' ", deg
, 0x00b0, min
);
81 coord_value
->setText(str1
);
82 deg
= floor(fabs(lon
));
83 min
= (fabs(lon
) - deg
) * 60;
85 str2
.sprintf("%.0f%c%.3f' ", deg
, 0x00b0, min
);
91 coord_value_2
->setText(str2
);
93 str3
.sprintf("%.2f m", alt
);
94 coord_value_3
->setText(str3
);
95 TrackData
.Latitude
= lat
;
96 TrackData
.Longitude
= lon
;
97 TrackData
.Altitude
= alt
;
98 calcAntennaPosition();
101 void AntennaTrackWidget::setHomePosition(double lat
, double lon
, double alt
)
105 double deg
= floor(fabs(lat
));
106 double min
= (fabs(lat
) - deg
) * 60;
109 str1
.sprintf("%.0f%c%.3f' ", deg
, 0x00b0, min
);
115 speed_value
->setText(str1
);
116 deg
= floor(fabs(lon
));
117 min
= (fabs(lon
) - deg
) * 60;
119 str2
.sprintf("%.0f%c%.3f' ", deg
, 0x00b0, min
);
125 bear_label
->setText(str2
);
127 str3
.sprintf("%.2f m", alt
);
128 bear_value
->setText(str3
);
129 TrackData
.HomeLatitude
= lat
;
130 TrackData
.HomeLongitude
= lon
;
131 TrackData
.HomeAltitude
= alt
;
132 calcAntennaPosition();
135 void AntennaTrackWidget::calcAntennaPosition(void)
137 /** http://www.movable-type.co.uk/scripts/latlong.html **/
138 double lat1
, lat2
, lon1
, lon2
, a
, c
, d
, x
, y
, brng
;
139 double azimuth
, elevation
;
140 double gcsAlt
= TrackData
.HomeAltitude
; // Home MSL altitude
141 double uavAlt
= TrackData
.Altitude
; // UAV MSL altitude
142 double dAlt
= uavAlt
- gcsAlt
; // Altitude difference
144 // Convert to radians
145 lat1
= TrackData
.HomeLatitude
* (M_PI
/ 180); // Home lat
146 lon1
= TrackData
.HomeLongitude
* (M_PI
/ 180); // Home lon
147 lat2
= TrackData
.Latitude
* (M_PI
/ 180); // UAV lat
148 lon2
= TrackData
.Longitude
* (M_PI
/ 180); // UAV lon
152 var y = Math.sin(dLon) * Math.cos(lat2);
153 var x = Math.cos(lat1)*Math.sin(lat2) -
154 Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon);
155 var brng = Math.atan2(y, x).toDeg();
157 y
= sin(lon2
- lon1
) * cos(lat2
);
158 x
= cos(lat1
) * sin(lat2
) - sin(lat1
) * cos(lat2
) * cos(lon2
- lon1
);
159 brng
= atan2((sin(lon2
- lon1
) * cos(lat2
)), (cos(lat1
) * sin(lat2
) - sin(lat1
) * cos(lat2
) * cos(lon2
- lon1
))) * (180 / M_PI
);
164 // bearing to stepper
167 // Haversine formula for distance
170 var dLat = (lat2-lat1).toRad();
171 var dLon = (lon2-lon1).toRad();
172 var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
173 Math.cos(lat1.toRad()) * Math.cos(lat2.toRad()) *
174 Math.sin(dLon/2) * Math.sin(dLon/2);
175 var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
178 a
= sin((lat2
- lat1
) / 2) * sin((lat2
- lat1
) / 2) +
179 cos(lat1
) * cos(lat2
) *
180 sin((lon2
- lon1
) / 2) * sin((lon2
- lon1
) / 2);
181 c
= 2 * atan2(sqrt(a
), sqrt(1 - a
));
184 // Elevation v depends servo direction
186 elevation
= 90 - (atan(dAlt
/ d
) * (180 / M_PI
));
190 // ! TODO: sanity check
193 str3
.sprintf("%.0f deg", azimuth
);
194 azimuth_value
->setText(str3
);
196 str3
.sprintf("%.0f deg", elevation
);
197 elevation_value
->setText(str3
);
199 // servo value 2000-4000
200 int servo
= (int)(2000.0 / 180 * elevation
+ 2000);
201 int stepper
= (int)(400.0 / 360 * (azimuth
- azimuth_old
));
203 // send azimuth and elevation to tracker hardware
204 str3
.sprintf("move %d 2000 2000 2000 %d\r", stepper
, servo
);
205 if (port
->isOpen()) {
206 if (azimuth_old
!= azimuth
|| elevation
!= elevation_old
) {
207 port
->write(str3
.toLatin1());
210 azimuth_old
= azimuth
;
211 elevation_old
= elevation
;