2929#include " intruder_item.h"
3030#include " arrow_item.h"
3131#include " pprzmain.h"
32+ #include " coordinatestransform.h"
3233
3334#include " quiver_item.h"
3435#include " gvf_traj_line.h"
@@ -113,6 +114,13 @@ MapWidget::MapWidget(QWidget *parent) : Map2D(parent),
113114 connect (show_hidden_wp_action, &QAction::toggled, [=](bool show) {
114115 setProperty (" show_hidden_waypoints" , show);
115116 });
117+
118+ show_crash_prediction_action = mapMenu->addAction (" Show crash prediction" );
119+ show_crash_prediction_action->setCheckable (true );
120+ connect (show_crash_prediction_action, &QAction::toggled, [=](bool show) {
121+ setProperty (" show_crash_prediction" , show);
122+ });
123+
116124 auto clear_shapes = mapMenu->addAction (" Clear Shapes" );
117125 connect (clear_shapes, &QAction::triggered, this , [=](){
118126 clearShapes ();
@@ -134,11 +142,11 @@ MapWidget::MapWidget(QWidget *parent) : Map2D(parent),
134142 [=](QString sender, QVector<int >* gvfViewer_config) {
135143 gvf_trajectories_config.remove (sender);
136144 gvf_trajectories_config[sender] = gvfViewer_config;
137- });
145+ });
138146
139147 connect ( DispatcherUi::get (), &DispatcherUi::new_ac_config, this , &MapWidget::handleNewAC);
140148 connect ( DispatcherUi::get (), &DispatcherUi::ac_deleted, this , &MapWidget::removeAC);
141- connect ( DispatcherUi::get (), &DispatcherUi::ac_selected, this , &MapWidget::changeCurrentAC);
149+ connect ( DispatcherUi::get (), &DispatcherUi::ac_selected, this , &MapWidget::changeCurrentAC);
142150 connect ( DispatcherUi::get (), &DispatcherUi::centerMap, this , &MapWidget::centerLatLon);
143151 connect (PprzDispatcher::get (), &PprzDispatcher::flight_param, this , &MapWidget::updateAircraftItem);
144152 connect (PprzDispatcher::get (), &PprzDispatcher::nav_status, this , &MapWidget::updateTarget);
@@ -188,6 +196,11 @@ MapWidget::MapWidget(QWidget *parent) : Map2D(parent),
188196 onGVF (sender, msg);
189197 });
190198
199+ PprzDispatcher::get ()->bind (" ROTORCRAFT_FP" , this ,
200+ [=](QString sender, pprzlink::Message msg) {
201+ onROTORCRAFT_FP (sender, msg);
202+ });
203+
191204 setAcceptDrops (true );
192205
193206 // Add menu to app menu bar.
@@ -747,6 +760,16 @@ void MapWidget::handleNewAC(QString ac_id) {
747760 double z_carrot = settings.value (" map/z_values/carrot" ).toDouble ();
748761 target->setZValues (z_carrot, z_carrot);
749762
763+ // create crash item at dummy position
764+ auto crash_item = new WaypointItem (Point2DLatLon (0 , 0 ), ac_id, 16 );
765+ crash_item->setStyle (GraphicsObject::Style::CRASH);
766+ if (!show_crash_prediction_action->isChecked ()) {
767+ crash_item->setVisible (false );
768+ } else {
769+ crash_item->setVisible (true );
770+ }
771+ addItem (crash_item);
772+
750773 ArrowItem* arrow = new ArrowItem (ac_id, 15 , this );
751774 addItem (arrow);
752775 arrow->setProperty (" size" , _ac_arrow_size);
@@ -757,7 +780,7 @@ void MapWidget::handleNewAC(QString ac_id) {
757780 });
758781
759782 // create the ACItemManager for this aircraft
760- item_manager = new ACItemManager (ac_id, target, aircraft_item, arrow, this );
783+ item_manager = new ACItemManager (ac_id, target, aircraft_item, arrow, crash_item, this );
761784
762785 auto clear_track = new QAction (ac->name (), ac);
763786 connect (clear_track, &QAction::triggered, aircraft_item, [=](){
@@ -767,7 +790,7 @@ void MapWidget::handleNewAC(QString ac_id) {
767790
768791 } else {
769792 // create the ACItemManager for this fake aircraft (flightplan only)
770- item_manager = new ACItemManager (ac_id, nullptr , nullptr , nullptr , this );
793+ item_manager = new ACItemManager (ac_id, nullptr , nullptr , nullptr , nullptr , this );
771794 }
772795
773796 ac_items_managers[ac_id] = item_manager;
@@ -1196,6 +1219,47 @@ void MapWidget::onDcShot(QString sender, pprzlink::Message msg) {
11961219 dc_shots.append (dsw);
11971220}
11981221
1222+ void MapWidget::onROTORCRAFT_FP (QString sender, pprzlink::Message msg) {
1223+
1224+ int32_t east, north, up, vnorth, veast, vup;
1225+ msg.getField (" east" , east);
1226+ msg.getField (" north" , north);
1227+ msg.getField (" up" , up);
1228+ msg.getField (" vnorth" , vnorth);
1229+ msg.getField (" veast" , veast);
1230+ msg.getField (" vup" , vup);
1231+
1232+ if (AircraftManager::get ()->aircraftExists (sender)) {
1233+ ac_items_managers[sender]->getCrashItem ();
1234+
1235+ float g = -9 .81f ;
1236+
1237+ double vx = veast*0.00000190734 ;
1238+ double vy = vnorth*0.00000190734 ;
1239+ double vz = vup*0.00000190734 ;
1240+
1241+ double x = east*0.0039063 ;
1242+ double y = north*0.0039063 ;
1243+ double z = up*0.0039063 ;
1244+
1245+ double h = fabs (z); // Should be height above ground, make sure to initialize local frame on ground
1246+
1247+ // With h always larger than 0, the sqrt can never give nan
1248+ float time_fall = (-vz - sqrtf (vz*vz -2 .f *h*g))/g;
1249+
1250+ double x_pos = x + time_fall*vx;
1251+ double y_pos = y + time_fall*vy;
1252+
1253+ auto ac = AircraftManager::get ()->getAircraft (sender);
1254+ auto orig = ac->getFlightPlan ()->getOrigin ();
1255+ Point2DLatLon pos (orig);
1256+
1257+ Point2DLatLon markerpos = CoordinatesTransform::get ()->ltp_to_wgs84 (pos,x_pos,y_pos);
1258+
1259+ ac_items_managers[sender]->getCrashItem ()->setPosition (markerpos);
1260+ }
1261+ }
1262+
11991263void MapWidget::onGCSPos (pprzlink::Message msg) {
12001264 if (gcsItem) {
12011265 removeItem (gcsItem);
@@ -1228,7 +1292,7 @@ void MapWidget::setAcArrowSize(int s) {
12281292}
12291293
12301294void MapWidget::onGVF (QString sender, pprzlink::Message msg) {
1231-
1295+
12321296 if (!gvf_loaded) {
12331297 return ;
12341298 }
@@ -1245,7 +1309,7 @@ void MapWidget::onGVF(QString sender, pprzlink::Message msg) {
12451309
12461310 gvf_trajectories[sender]->purge_trajectory ();
12471311 delete gvf_trajectories[sender];
1248-
1312+
12491313 gvf_trajectories.remove (sender);
12501314 ac_items_managers[sender]->setCurrentGVF (nullptr );
12511315 }
@@ -1256,7 +1320,7 @@ void MapWidget::onGVF(QString sender, pprzlink::Message msg) {
12561320 QList<float > param = {0.0 };
12571321 int8_t direction;
12581322 GVF_trajectory* gvf_traj;
1259-
1323+
12601324 // GVF message parser
12611325 if (msg.getDefinition ().getName () == " GVF" ) {
12621326 float error, ke;
@@ -1268,7 +1332,7 @@ void MapWidget::onGVF(QString sender, pprzlink::Message msg) {
12681332 msg.getField (" p" , param);
12691333
12701334 switch (traj)
1271- {
1335+ {
12721336 case 0 : {// Straight line
12731337 gvf_traj = new GVF_traj_line (sender, param, direction, ke, gvf_trajectories_config[sender]);
12741338 break ;
@@ -1290,14 +1354,14 @@ void MapWidget::onGVF(QString sender, pprzlink::Message msg) {
12901354 // GVF_PARAMETRIC
12911355 else if (msg.getDefinition ().getName () == " GVF_PARAMETRIC" ) {
12921356 QList<float > phi = {0.0 }; // Error signals
1293-
1357+
12941358 msg.getField (" traj" , traj);
12951359 msg.getField (" w" , wb);
12961360 msg.getField (" p" , param);
12971361 msg.getField (" phi" , phi);
12981362
12991363 switch (traj)
1300- {
1364+ {
13011365 case 0 : {// Trefoil 2D
13021366 gvf_traj = new GVF_traj_trefoil (sender, param, phi, gvf_trajectories_config[sender]);
13031367 break ;
@@ -1321,7 +1385,7 @@ void MapWidget::onGVF(QString sender, pprzlink::Message msg) {
13211385 } else {
13221386 return ;
13231387 }
1324-
1388+
13251389 addItem (gvf_traj->getTraj ());
13261390 addItem (gvf_traj->getVField ());
13271391 ac_items_managers[sender]->setCurrentGVF (gvf_traj);
@@ -1344,3 +1408,16 @@ void MapWidget::showHiddenWaypoints(bool state) {
13441408 }
13451409 }
13461410}
1411+
1412+ void MapWidget::showCrashPrediction (bool state) {
1413+ show_crash_prediction_action->blockSignals (true );
1414+ show_crash_prediction_action->setChecked (state);
1415+ show_crash_prediction_action->blockSignals (false );
1416+ for (auto &itemManager: ac_items_managers) {
1417+ if (state) {
1418+ itemManager->getCrashItem ()->setVisible (true );
1419+ } else {
1420+ itemManager->getCrashItem ()->setVisible (false );
1421+ }
1422+ }
1423+ }
0 commit comments