3
3
#include < cmath>
4
4
5
5
#include < QDebug>
6
+ #include < QString>
6
7
7
8
#include " selfdrive/common/timing.h"
8
9
#include " selfdrive/ui/qt/util.h"
@@ -171,8 +172,7 @@ void OnroadAlerts::paintEvent(QPaintEvent *event) {
171
172
OnroadHud::OnroadHud (QWidget *parent) : QWidget(parent) {
172
173
engage_img = loadPixmap (" ../assets/img_chffr_wheel.png" , {img_size, img_size});
173
174
dm_img = loadPixmap (" ../assets/img_driver_face.png" , {img_size, img_size});
174
-
175
- connect (this , &OnroadHud::valueChanged, [=] { update (); });
175
+ brake_img = loadPixmap (" ../assets/img_brake_disc.png" , {img_size, img_size});
176
176
}
177
177
178
178
void OnroadHud::updateState (const UIState &s) {
@@ -185,27 +185,176 @@ void OnroadHud::updateState(const UIState &s) {
185
185
if (cruise_set && !s.scene .is_metric ) {
186
186
maxspeed *= KM_TO_MILE;
187
187
}
188
- QString maxspeed_str = cruise_set ? QString::number (std::nearbyint (maxspeed)) : " N/A " ;
189
- float cur_speed = sm[" carState" ].getCarState ().getVEgo () * (s.scene .is_metric ? MS_TO_KPH : MS_TO_MPH);
188
+ QString maxspeed_str = cruise_set ? QString::number (std::nearbyint (maxspeed)) : " - " ;
189
+ float cur_speed = std::max ( 0.0 , sm[" carState" ].getCarState ().getVEgo () * (s.scene .is_metric ? MS_TO_KPH : MS_TO_MPH) );
190
190
191
191
setProperty (" is_cruise_set" , cruise_set);
192
192
setProperty (" speed" , QString::number (std::nearbyint (cur_speed)));
193
193
setProperty (" maxSpeed" , maxspeed_str);
194
194
setProperty (" speedUnit" , s.scene .is_metric ? " km/h" : " mph" );
195
195
setProperty (" hideDM" , cs.getAlertSize () != cereal::ControlsState::AlertSize::NONE);
196
196
setProperty (" status" , s.status );
197
-
198
- // update engageability and DM icons at 2Hz
199
- if (sm.frame % (UI_FREQ / 2 ) == 0 ) {
200
- setProperty (" engageable" , cs.getEngageable () || cs.getEnabled ());
201
- setProperty (" dmActive" , sm[" driverMonitoringState" ].getDriverMonitoringState ().getIsActiveMode ());
202
- }
197
+ setProperty (" engageable" , cs.getEngageable () || cs.getEnabled ());
198
+ setProperty (" dmActive" , sm[" driverMonitoringState" ].getDriverMonitoringState ().getIsActiveMode ());
199
+ // -1.96133 is -0.2g of braking force, which is where most one-pedal enabled cars turn on brakelight -wn2
200
+ setProperty (" braking" , sm[" carControl" ].getCarControl ().getActuators ().getAccel () < -1.96133 || sm[" carState" ].getCarState ().getBrakePressed () || sm[" carState" ].getCarState ().getBrakeLightsDEPRECATED ());
201
+
202
+ const auto leadOne = sm[" radarState" ].getRadarState ().getLeadOne ();
203
+ setProperty (" lead_d_rel" , leadOne.getDRel ());
204
+ setProperty (" lead_v_rel" , leadOne.getVRel ());
205
+ setProperty (" lead_status" , leadOne.getStatus ());
206
+ setProperty (" angleSteers" , sm[" carState" ].getCarState ().getSteeringAngleDeg ());
207
+
208
+ // If your car uses INDI or LQR, adjust this accordingly. -wirelessnet2
209
+ setProperty (" steerAngleDesired" , sm[" controlsState" ].getControlsState ().getLateralControlState ().getPidState ().getSteeringAngleDesiredDeg ());
210
+ setProperty (" engineRPM" , sm[" carState" ].getCarState ().getEngineRPM ());
203
211
}
204
212
205
213
void OnroadHud::paintEvent (QPaintEvent *event) {
206
214
QPainter p (this );
207
215
p.setRenderHint (QPainter::Antialiasing);
208
216
217
+ int NvgWindow::devUiDrawElement (QPainter &p, int x, int y, const char * value, const char * label, const char * units, QColor &color) {
218
+ configFont (p, " Open Sans" , 30 * 2 , " SemiBold" );
219
+ drawColoredText (p, x + 92 , y + 80 , QString (value), color);
220
+
221
+ configFont (p, " Open Sans" , 28 , " Regular" );
222
+ drawText (p, x + 92 , y + 80 + 42 , QString (label), 255 );
223
+
224
+ if (strlen (units) > 0 ) {
225
+ p.save ();
226
+ p.translate (x + 54 + 30 - 3 + 92 , y + 37 + 25 );
227
+ p.rotate (-90 );
228
+ drawText (p, 0 , 0 , QString (units), 255 );
229
+ p.restore ();
230
+ }
231
+
232
+ return 110 ;
233
+ }
234
+
235
+ void NvgWindow::drawLeftDevUi (QPainter &p, int x, int y) {
236
+ int rh = 5 ;
237
+ int ry = y;
238
+
239
+ // Add Relative Distance to Primary Lead Car
240
+ // Unit: Meters
241
+ if (true ) {
242
+ char val_str[8 ];
243
+ char units_str[8 ];
244
+ QColor valueColor = QColor (255 , 255 , 255 , 255 );
245
+
246
+ if (lead_status) {
247
+ // Orange if close, Red if very close
248
+ if (lead_d_rel < 5 ) {
249
+ valueColor = QColor (255 , 0 , 0 , 255 );
250
+ } else if (lead_d_rel < 15 ) {
251
+ valueColor = QColor (255 , 188 , 0 , 255 );
252
+ }
253
+ snprintf (val_str, sizeof (val_str), " %d" , (int )lead_d_rel);
254
+ } else {
255
+ snprintf (val_str, sizeof (val_str), " -" );
256
+ }
257
+
258
+ snprintf (units_str, sizeof (units_str), " m" );
259
+
260
+ rh += devUiDrawElement (p, x, ry, val_str, " REL DIST" , units_str, valueColor);
261
+ ry = y + rh;
262
+ }
263
+
264
+ // Add Relative Velocity vs Primary Lead Car
265
+ // Unit: kph if metric, else mph
266
+ if (true ) {
267
+ char val_str[8 ];
268
+ QColor valueColor = QColor (255 , 255 , 255 , 255 );
269
+
270
+ if (lead_status) {
271
+ // Red if approaching faster than 10mph
272
+ // Orange if approaching (negative)
273
+ if (lead_v_rel < -4.4704 ) {
274
+ valueColor = QColor (255 , 0 , 0 , 255 );
275
+ } else if (lead_v_rel < 0 ) {
276
+ valueColor = QColor (255 , 188 , 0 , 255 );
277
+ }
278
+
279
+ if (speedUnit == " mph" ) {
280
+ snprintf (val_str, sizeof (val_str), " %d" , (int )(lead_v_rel * 2.236936 )); // mph
281
+ } else {
282
+ snprintf (val_str, sizeof (val_str), " %d" , (int )(lead_v_rel * 3.6 )); // kph
283
+ }
284
+ } else {
285
+ snprintf (val_str, sizeof (val_str), " -" );
286
+ }
287
+
288
+ rh += devUiDrawElement (p, x, ry, val_str, " REL SPEED" , speedUnit.toStdString ().c_str (), valueColor);
289
+ ry = y + rh;
290
+ }
291
+
292
+ // Add Real Steering Angle
293
+ // Unit: Degrees
294
+ if (true ) {
295
+ char val_str[8 ];
296
+ QColor valueColor = QColor (255 , 255 , 255 , 255 );
297
+
298
+ // Red if large steering angle
299
+ // Orange if moderate steering angle
300
+ if (std::fabs (angleSteers) > 12 ) {
301
+ valueColor = QColor (255 , 0 , 0 , 255 );
302
+ } else if (std::fabs (angleSteers) > 6 ) {
303
+ valueColor = QColor (255 , 188 , 0 , 255 );
304
+ }
305
+
306
+ snprintf (val_str, sizeof (val_str), " %.0f%s%s" , angleSteers , " °" , " " );
307
+
308
+ rh += devUiDrawElement (p, x, ry, val_str, " REAL STEER" , " " , valueColor);
309
+ ry = y + rh;
310
+ }
311
+
312
+ // Add Desired Steering Angle
313
+ // Unit: Degrees
314
+ if (false ) {
315
+ char val_str[8 ];
316
+ QColor valueColor = QColor (255 , 255 , 255 , 255 );
317
+
318
+ if (status != STATUS_DISENGAGED) {
319
+ // Red if large steering angle
320
+ // Orange if moderate steering angle
321
+ if (std::fabs (angleSteers) > 12 ) {
322
+ valueColor = QColor (255 , 0 , 0 , 255 );
323
+ } else if (std::fabs (angleSteers) > 6 ) {
324
+ valueColor = QColor (255 , 188 , 0 , 255 );
325
+ }
326
+
327
+ snprintf (val_str, sizeof (val_str), " %.0f%s%s" , steerAngleDesired, " °" , " " );
328
+ } else {
329
+ snprintf (val_str, sizeof (val_str), " -" );
330
+ }
331
+
332
+ rh += devUiDrawElement (p, x, ry, val_str, " DESIR STEER" , " " , valueColor);
333
+ ry = y + rh;
334
+ }
335
+
336
+ // Add Engine RPM
337
+ // Unit: RPM
338
+ if (true ) {
339
+ char val_str[8 ];
340
+ QColor valueColor = QColor (255 , 255 , 255 , 255 );
341
+
342
+ if (engineRPM == 0 ) {
343
+ snprintf (val_str, sizeof (val_str), " OFF" );
344
+ } else {
345
+ snprintf (val_str, sizeof (val_str), " %d" , (engineRPM));
346
+ }
347
+
348
+ rh += devUiDrawElement (p, x, ry, val_str, " ENG RPM" , " " , valueColor);
349
+ ry = y + rh;
350
+ }
351
+
352
+ rh += 25 ;
353
+ p.setBrush (QColor (0 , 0 , 0 , 0 ));
354
+ QRect ldu (x, y, 184 , rh);
355
+ p.drawRoundedRect (ldu, 20 , 20 );
356
+ }
357
+
209
358
// Header gradient
210
359
QLinearGradient bg (0 , header_h - (header_h / 2.5 ), 0 , header_h);
211
360
bg.setColorAt (0 , QColor::fromRgbF (0 , 0 , 0 , 0.45 ));
@@ -241,10 +390,21 @@ void OnroadHud::paintEvent(QPaintEvent *event) {
241
390
engage_img, bg_colors[status], 1.0 );
242
391
}
243
392
244
- // dm icon
245
393
if (!hideDM) {
246
- drawIcon (p, radius / 2 + (bdr_s * 2 ), rect ().bottom () - footer_h / 2 ,
394
+ // left Dev UI
395
+ drawLeftDevUi (p, bdr_s * 2 , bdr_s * 2 + rc.height ());
396
+
397
+ // dm icon
398
+ drawIcon (p, rc.center ().x (), rect ().bottom () - footer_h / 2 + 50 ,
247
399
dm_img, QColor (0 , 0 , 0 , 70 ), dmActive ? 1.0 : 0.2 );
400
+
401
+ p.setOpacity (1.0 ); // dmActive will determine opacity of brake_img's bg without this :/ -wirelessnet2
402
+
403
+ // brake icon
404
+ if (false ) {
405
+ drawIcon (p, rc.center ().x () + 250 , rect ().bottom () - footer_h / 2 + 50 ,
406
+ brake_img, QColor (0 , 0 , 0 , 70 ), braking ? 1.0 : 0.2 );
407
+ }
248
408
}
249
409
}
250
410
@@ -258,7 +418,17 @@ void OnroadHud::drawText(QPainter &p, int x, int y, const QString &text, int alp
258
418
p.drawText (real_rect.x (), real_rect.bottom (), text);
259
419
}
260
420
261
- void OnroadHud::drawIcon (QPainter &p, int x, int y, QPixmap &img, QBrush bg, float opacity) {
421
+ void NvgWindow::drawColoredText (QPainter &p, int x, int y, const QString &text, QColor &color) {
422
+ QFontMetrics fm (p.font ());
423
+ QRect init_rect = fm.boundingRect (text);
424
+ QRect real_rect = fm.boundingRect (init_rect, 0 , text);
425
+ real_rect.moveCenter ({x, y - real_rect.height () / 2 });
426
+
427
+ p.setPen (color);
428
+ p.drawText (real_rect.x (), real_rect.bottom (), text);
429
+ }
430
+
431
+ void NvgWindow::drawIcon (QPainter &p, int x, int y, QPixmap &img, QBrush bg, float opacity) {
262
432
p.setPen (Qt::NoPen);
263
433
p.setBrush (bg);
264
434
p.drawEllipse (x - radius / 2 , y - radius / 2 , radius, radius);
@@ -320,7 +490,27 @@ void NvgWindow::drawLaneLines(QPainter &painter, const UIState *s) {
320
490
321
491
// paint path
322
492
QLinearGradient bg (0 , height (), 0 , height () / 4 );
323
- if (scene.end_to_end ) {
493
+ // wirelessnet2's rainbow barf path
494
+ if (scene.enabled ) {
495
+ // openpilot is not disengaged
496
+ if (scene.steeringPressed ) {
497
+ // The user is applying torque to the steering wheel
498
+ bg.setColorAt (0 , QColor (0 , 191 , 255 , 255 ));
499
+ bg.setColorAt (1 , QColor (0 , 95 , 128 , 50 ));
500
+ } else {
501
+ // Draw colored track
502
+ int torqueScale = (int )std::fabs (510 * (float )scene.pidStateOutput );
503
+ int red_lvl = std::fmin (255 , torqueScale);
504
+ int green_lvl = std::fmin (255 , 510 - torqueScale);
505
+ bg.setColorAt (0 , QColor (red_lvl, green_lvl, 0 , 255 ));
506
+ bg.setColorAt (1 , QColor ((int )(0.5 * red_lvl), (int )(0.5 * green_lvl), 0 , 50 ));
507
+ }
508
+ } else if (!scene.end_to_end ) {
509
+ // Draw white track when disengaged and not end_to_end
510
+ bg.setColorAt (0 , whiteColor ());
511
+ bg.setColorAt (1 , whiteColor (0 ));
512
+ } else {
513
+ // Draw red vision track when disengaged and end_to_end
324
514
const auto &orientation = (*s->sm )[" modelV2" ].getModelV2 ().getOrientation ();
325
515
float orientation_future = 0 ;
326
516
if (orientation.getZ ().size () > 16 ) {
@@ -330,15 +520,11 @@ void NvgWindow::drawLaneLines(QPainter &painter, const UIState *s) {
330
520
float curve_hue = fmax (70 , 112 - (orientation_future * 420 ));
331
521
// FIXME: painter.drawPolygon can be slow if hue is not rounded
332
522
curve_hue = int (curve_hue * 100 + 0.5 ) / 100 ;
333
-
334
- bg.setColorAt (0.0 / 1.5 , QColor::fromHslF (148 / 360 ., 1.0 , 0.5 , 1.0 ));
335
- bg.setColorAt (0.55 / 1.5 , QColor::fromHslF (112 / 360 ., 1.0 , 0.68 , 0.8 ));
336
- bg.setColorAt (0.9 / 1.5 , QColor::fromHslF (curve_hue / 360 ., 1.0 , 0.65 , 0.6 ));
337
- bg.setColorAt (1.0 , QColor::fromHslF (curve_hue / 360 ., 1.0 , 0.65 , 0.0 ));
338
- } else {
339
- bg.setColorAt (0 , whiteColor ());
340
- bg.setColorAt (1 , whiteColor (0 ));
523
+ bg.setColorAt (0.0 , QColor::fromHslF (148 / 360 ., 0.94 , 0.51 , 0.4 ));
524
+ bg.setColorAt (0.75 / 1.5 , QColor::fromHslF (curve_hue / 360 ., 1.0 , 0.68 , 0.35 ));
525
+ bg.setColorAt (1.0 , QColor::fromHslF (curve_hue / 360 ., 1.0 , 0.68 , 0.0 ));
341
526
}
527
+
342
528
painter.setBrush (bg);
343
529
painter.drawPolygon (scene.track_vertices .v , scene.track_vertices .cnt );
344
530
}
0 commit comments