Skip to content

Commit 4df9963

Browse files
authored
Merge pull request #24 from EwoudSmeur/crash_prediction
predict crash location on GCS
2 parents c1ae3a0 + 14eebfd commit 4df9963

File tree

7 files changed

+113
-14
lines changed

7 files changed

+113
-14
lines changed

src/widgets/map/acitemmanager.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
#include "acitemmanager.h"
22

3-
ACItemManager::ACItemManager(QString ac_id, WaypointItem* target, AircraftItem* aircraft_item, ArrowItem* arrow, QObject* parent):
3+
ACItemManager::ACItemManager(QString ac_id, WaypointItem* target, AircraftItem* aircraft_item, ArrowItem* arrow, WaypointItem* crash_item, QObject* parent):
44
QObject(parent),
55
ac_id(ac_id), target(target), aircraft_item(aircraft_item),
6-
current_nav_shape(nullptr), max_dist_circle(nullptr), arrow_item(arrow), gvf_trajectory(nullptr)
6+
current_nav_shape(nullptr), max_dist_circle(nullptr), arrow_item(arrow), crash_item(crash_item), gvf_trajectory(nullptr)
77
{
88

99
}
@@ -72,4 +72,9 @@ void ACItemManager::removeItems(MapWidget* map) {
7272
map->removeItem(max_dist_circle);
7373
max_dist_circle = nullptr;
7474
}
75+
76+
if(crash_item) {
77+
map->removeItem(crash_item);
78+
crash_item = nullptr;
79+
}
7580
}

src/widgets/map/acitemmanager.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class ACItemManager: public QObject
1414
{
1515
Q_OBJECT
1616
public:
17-
ACItemManager(QString ac_id, WaypointItem* target, AircraftItem* aircraft_item, ArrowItem* arrow_item, QObject* parent=nullptr);
17+
ACItemManager(QString ac_id, WaypointItem* target, AircraftItem* aircraft_item, ArrowItem* arrow_item, WaypointItem* crash_item, QObject* parent=nullptr);
1818

1919
void addWaypointItem(WaypointItem*);
2020
void addPathItem(PathItem*);
@@ -27,6 +27,7 @@ class ACItemManager: public QObject
2727
MapItem* getCurrentNavShape() {return current_nav_shape;}
2828
AircraftItem* getAircraftItem() {return aircraft_item;}
2929
ArrowItem* getArrowItem() {return arrow_item;}
30+
WaypointItem* getCrashItem() {return crash_item;}
3031
void removeItems(MapWidget* map);
3132

3233
private:
@@ -38,6 +39,7 @@ class ACItemManager: public QObject
3839
MapItem* current_nav_shape;
3940
CircleItem* max_dist_circle;
4041
ArrowItem* arrow_item;
42+
WaypointItem* crash_item;
4143

4244
GVF_trajectory* gvf_trajectory;
4345
};

src/widgets/map/graphics_objects/graphics_object.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class GraphicsObject : public QObject
1818
CARROT,
1919
GCS,
2020
DCSHOT,
21+
CRASH,
2122
};
2223

2324
enum Animation {

src/widgets/map/graphics_objects/graphics_point.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,13 @@ void GraphicsPoint::paint(QPainter *painter, const QStyleOptionGraphicsItem *opt
9797
painter->drawEllipse(QPoint(0, 0), halfSize/2, halfSize/2);
9898
}
9999
break;
100+
case CRASH: {
101+
// Draw a red cross with thickness 3
102+
painter->setPen(QPen(QColor(255, 0, 0), 3));
103+
painter->drawLine(QPoint(-halfSize/2, -halfSize/2), QPoint(halfSize/2, halfSize/2));
104+
painter->drawLine(QPoint(-halfSize/2, halfSize/2), QPoint(halfSize/2, -halfSize/2));
105+
}
106+
break;
100107
}
101108

102109
}

src/widgets/map/graphics_objects/graphics_text.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ void GraphicsText::changeFocus() {
3131
case DCSHOT:
3232
setVisible(false);
3333
break;
34+
case CRASH:
35+
setVisible(false);
36+
break;
3437
}
3538

3639
update();

src/widgets/map/mapwidget.cpp

Lines changed: 88 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
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+
11991263
void MapWidget::onGCSPos(pprzlink::Message msg) {
12001264
if(gcsItem) {
12011265
removeItem(gcsItem);
@@ -1228,7 +1292,7 @@ void MapWidget::setAcArrowSize(int s) {
12281292
}
12291293

12301294
void 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+
}

src/widgets/map/mapwidget.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class MapWidget : public Map2D, public Configurable
4242
Q_OBJECT
4343
Q_PROPERTY(int ac_arrow_size MEMBER _ac_arrow_size WRITE setAcArrowSize)
4444
Q_PROPERTY(bool show_hidden_waypoints WRITE showHiddenWaypoints)
45+
Q_PROPERTY(bool show_crash_prediction WRITE showCrashPrediction)
4546
public:
4647
explicit MapWidget(QWidget *parent = nullptr);
4748

@@ -61,6 +62,7 @@ class MapWidget : public Map2D, public Configurable
6162
void rotateMap(double rot);
6263
void setAcArrowSize(int s);
6364
void showHiddenWaypoints(bool state);
65+
void showCrashPrediction(bool state);
6466

6567
signals:
6668
void mouseMoved(QPointF scenePos);
@@ -91,6 +93,7 @@ private slots:
9193
void clearDcShots();
9294
void onIntruder(QString sender, pprzlink::Message msg);
9395
void onDcShot(QString sender, pprzlink::Message msg);
96+
void onROTORCRAFT_FP(QString sender, pprzlink::Message msg);
9497
void onGCSPos(pprzlink::Message msg);
9598
void onGVF(QString sender, pprzlink::Message msg);
9699

@@ -154,6 +157,7 @@ private slots:
154157
QMenu* mapMenu;
155158
QMenu* menu_clear_track;
156159
QAction* show_hidden_wp_action;
160+
QAction* show_crash_prediction_action;
157161
};
158162

159163
#endif // MAPWIDGET_H

0 commit comments

Comments
 (0)