Apollo 11.0
自动驾驶开放平台
main_window.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2018 The Apollo Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *****************************************************************************/
16
17#include <QtWidgets/QCheckBox>
18#include <QtWidgets/QColorDialog>
19#include <QtWidgets/QComboBox>
20#include <QtWidgets/QMessageBox>
21#include <QtWidgets/QPushButton>
22#include <QtWidgets/QSpinBox>
23
29#include "modules/tools/visualizer/ui_main_window.h"
31
32namespace {
33const char* globalTreeItemStyle = "margin-right:10px";
34
35const char* aboutMessage =
36 "Cyber_Visualizer\n"
37 "\n"
38 "One Visualization Tool for Presenting Cyber Channel Data\n"
39 "\n"
40 "F5 Play | Pause\n"
41 "\n"
42 "Main View PointCloud view\n"
43 "All Views have right button Menu";
44
45const char* licenseMessage =
46 "Copyright 2018 The Apollo Authors. All Rights Reserved.\n"
47 "\n"
48 "Licensed under the Apache License, Version 2.0 (the \"License\");\n"
49 "you may not use this file except in compliance with the License.\n"
50 "You may obtain a copy of the License at\n"
51 "\n"
52 "http://www.apache.org/licenses/LICENSE-2.0\n"
53 "\n"
54 "Unless required by applicable law or agreed to in writing, software\n"
55 "distributed under the License is distributed on an \"AS IS\" BASIS,\n"
56 "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n"
57 "See the License for the specific language governing permissions and\n"
58 "limitations under the License.\n";
59
60const char* pcTempObjGroupName = "pointcloud";
61const char* pcVertexPath = "/apollo/modules/tools/visualizer/shaders/pointcloud.vert";
62const char* pcFragPath = "/apollo/modules/tools/visualizer/shaders/grid_pointcloud.frag";
63const char* gridVertexPath = "/apollo/modules/tools/visualizer/shaders/grid.vert";
64const char* gridFragPath = "/apollo/modules/tools/visualizer/shaders/grid_pointcloud.frag";
65const char* radarVertexPath = "/apollo/modules/tools/visualizer/shaders/radarpoints.vert";
66const char* radarFragPath = "/apollo/modules/tools/visualizer/shaders/radarpoints.frag";
67
68const std::string CompressedImageType("apollo.drivers.CompressedImage");
69
70} // namespace
71
72#define MEMBER_OFFSET(StructType, Member) \
73 (size_t)( \
74 reinterpret_cast<char*>(&(reinterpret_cast<StructType*>(1)->Member)) - \
75 1)
76#define StructPtrByMemberPtr(MemberPtr, StructType, Member) \
77 reinterpret_cast<StructType*>(reinterpret_cast<char*>(MemberPtr) - \
78 MEMBER_OFFSET(StructType, Member))
79
135
166
168 : QMainWindow(parent),
169 ui_(new Ui::MainWindow),
170 msg_dialog_(new MessageDialog),
171 open_images_dialog_(nullptr),
172
173 grid_(nullptr),
174 enable_grid_checkBox_(nullptr),
175 grid_root_item_(nullptr),
176
177 pointcloud_top_item_(nullptr),
178 pointcloud_comboBox_(new QComboBox),
179 pointcloud_button_(new QPushButton),
180 pointcloud_channel_Reader_(nullptr),
181
182 pointcloud_reader_mutex_(),
183
184 pointcloud_shader_(nullptr),
185 grid_shader_(nullptr),
186 radar_points_shader_(nullptr),
187 video_image_viewer_list_(),
188 closed_video_image_viewer_list_(),
189 radarData_list_(),
190 closed_radarData_list_(),
191 _channelName2TypeMap() {
192 ui_->setupUi(this);
193 ui_->videoImageGridLayout->setContentsMargins(2, 2, 2, 2);
194 ui_->videoImageWidget->setVisible(false);
195
196 ui_->mainToolBar->addAction(ui_->actionAddGrid);
197 ui_->mainToolBar->addAction(ui_->actionPointCloud);
198 ui_->mainToolBar->addSeparator();
199 ui_->mainToolBar->addAction(ui_->actionOpenImage);
200 ui_->mainToolBar->addAction(ui_->actionOpenImages);
201 ui_->mainToolBar->addAction(ui_->actionDelImage);
202 ui_->mainToolBar->addSeparator();
203 ui_->mainToolBar->addAction(ui_->actionPlay);
204 ui_->mainToolBar->addAction(ui_->actionPause);
205
206 pointcloud_reader_mutex_.lock();
207
208 {
209 QStringList tmp;
210 tmp << "ChannelNames"
211 << " ";
212 all_channel_root_ = new QTreeWidgetItem(tmp);
213 ui_->treeWidget->addTopLevelItem(all_channel_root_);
214 }
215
216 connect(ui_->actionAbout, SIGNAL(triggered(bool)), this, SLOT(showMessage()));
217 connect(ui_->actionLicense, SIGNAL(triggered(bool)), this,
218 SLOT(showMessage()));
219
220 pointcloud_button_->setCheckable(true);
221 pointcloud_button_->setStyleSheet(globalTreeItemStyle);
222 pointcloud_comboBox_->setStyleSheet(globalTreeItemStyle);
223
224 connect(pointcloud_button_, SIGNAL(clicked(bool)), this,
225 SLOT(PlayRenderableObject(bool)));
226 connect(pointcloud_comboBox_, SIGNAL(currentIndexChanged(int)), this,
227 SLOT(ChangePointCloudChannel()));
228
229 connect(ui_->treeWidget, SIGNAL(itemSelectionChanged()), this,
230 SLOT(UpdateActions()));
231 connect(ui_->treeWidget, SIGNAL(visibilityChanged(bool)), ui_->actionGlobal,
232 SLOT(setChecked(bool)));
233 connect(ui_->actionPlay, SIGNAL(triggered(bool)), this, SLOT(PlayPause()));
234 connect(ui_->actionPause, SIGNAL(triggered(bool)), this, SLOT(PlayPause()));
235}
236
238 for (VideoImgProxy* item : video_image_viewer_list_) {
239 item->reader_mutex_.unlock();
240 }
241 for (VideoImgProxy* item : closed_video_image_viewer_list_) {
242 item->reader_mutex_.unlock();
243 }
244 for (RadarData* item : radarData_list_) {
245 item->reader_mutex_.unlock();
246 }
247 for (RadarData* item : closed_radarData_list_) {
248 item->reader_mutex_.unlock();
249 }
250
251 pointcloud_reader_mutex_.unlock();
252
253 if (pointcloud_channel_Reader_) {
254 delete pointcloud_channel_Reader_;
255 pointcloud_channel_Reader_ = nullptr;
256 }
257
258 for (VideoImgProxy* item : video_image_viewer_list_) {
259 delete item;
260 }
261
262 for (VideoImgProxy* item : closed_video_image_viewer_list_) {
263 delete item;
264 }
265
266 for (RadarData* item : radarData_list_) {
267 delete item;
268 }
269
270 for (RadarData* item : closed_radarData_list_) {
271 delete item;
272 }
273
274 delete ui_;
275 delete msg_dialog_;
276}
277
278void MainWindow::calculateWH(void) {
279 int count = video_image_viewer_list_.count();
280
281 if (count > 0) {
282 QSize wh;
283 wh.setWidth(ui_->sceneWidget->width() - count * 2 + 2);
284 wh.setHeight(50);
285 wh.setWidth(wh.width() / count);
286 int index = 0;
287
288 for (VideoImgProxy* p : video_image_viewer_list_) {
289 p->video_image_viewer_.setMinimumSize(wh);
290 ui_->videoImageGridLayout->removeWidget(&p->video_image_viewer_);
291 ui_->videoImageGridLayout->addWidget(&p->video_image_viewer_, index / 3,
292 index % 3, 1, 1);
293 ++index;
294 }
295 ui_->videoImageWidget->adjustSize();
296 }
297}
298
299MainWindow::VideoImgProxy* MainWindow::AddVideoImgViewer() {
300 std::shared_ptr<Texture> tex(new Texture);
301 if (tex == nullptr) {
302 return nullptr;
303 }
304 VideoImgProxy* ret = new VideoImgProxy();
305
306 if (ret) {
307 int index = video_image_viewer_list_.count();
308 ret->video_image_viewer_.set_index(index);
309
310 ret->video_image_viewer_.setStyleSheet("background-color:black;");
311 ret->video_image_viewer_.setVisible(false);
312
313 QString imgName = tr("Camera%1").arg(index);
314
315 ret->root_item_.setHidden(true);
316 ret->root_item_.setText(0, imgName);
317 ret->root_item_.setText(1, "");
318
319 ret->channel_name_item_.setText(0, "ChannelName");
320 ret->action_item_.setText(0, "Action");
321
322 ret->action_item_button_.setObjectName(tr("pushButton%1").arg(index));
323 ret->action_item_button_.setText("Play");
324 ret->action_item_button_.setCheckable(true);
325 ret->action_item_button_.setStyleSheet(globalTreeItemStyle);
326
327 ret->channel_name_combobox_.setObjectName(tr("comboBox%1").arg(index));
328 ret->channel_name_combobox_.setStyleSheet(globalTreeItemStyle);
329
330 ret->root_item_.addChild(&ret->channel_name_item_);
331 ret->root_item_.addChild(&ret->action_item_);
332
333 ret->dynamic_texture_ = tex;
334 ret->video_image_viewer_.SetupDynamicTexture(tex);
335
336 ret->video_image_viewer_.setSizePolicy(QSizePolicy::Preferred,
337 QSizePolicy::Preferred);
338 ret->video_image_viewer_.addAction(ui_->actionDelImage);
339 ret->reader_mutex_.lock();
340 }
341 return ret;
342}
343
344MainWindow::RadarData* MainWindow::createRadarData(void) {
345 RadarData* ret = new RadarData();
346
347 if (ret) {
348 int index = radarData_list_.count();
349 QString radarName = tr("Radar%1").arg(index);
350
351 ret->root_item_.setHidden(true);
352 ret->root_item_.setText(0, radarName);
353
354 ret->channel_name_item_.setText(0, "ChannelName");
355 ret->action_item_.setText(0, "Action");
356 ret->enable_checkBox_.setChecked(true);
357
358 ret->action_item_button_.setText("Play");
359 ret->action_item_button_.setCheckable(true);
360 ret->action_item_button_.setStyleSheet(globalTreeItemStyle);
361
362 ret->channel_name_combobox_.setObjectName(tr("comboBox%1").arg(index));
363 ret->channel_name_combobox_.setStyleSheet(globalTreeItemStyle);
364
365 ret->root_item_.addChild(&ret->channel_name_item_);
366 ret->root_item_.addChild(&ret->action_item_);
367 ret->reader_mutex_.lock();
368 }
369 return ret;
370}
371
372void MainWindow::EnableGrid(bool b) { grid_->set_is_renderable(b); }
373
374void MainWindow::ActionAddGrid(void) {
375 if (grid_shader_ == nullptr) {
376 grid_shader_ = RenderableObject::CreateShaderProgram(tr(gridVertexPath),
377 tr(gridFragPath));
378 if (grid_shader_ != nullptr) {
379 ui_->sceneWidget->AddNewShaderProg("grid", grid_shader_);
380 }
381 }
382
383 if (grid_root_item_ == nullptr) {
384 QTreeWidgetItem* colorChild = nullptr;
385 QTreeWidgetItem* cellCountChild = nullptr;
386 QSpinBox* spinbox = nullptr;
387
388 grid_ = new Grid(6);
389 if (grid_ == nullptr) {
390 goto _ret1;
391 }
392
393 if (grid_shader_ == nullptr) {
394 goto _ret2;
395 }
396
397 enable_grid_checkBox_ = new QCheckBox(ui_->treeWidget);
398 if (enable_grid_checkBox_ == nullptr) {
399 goto _ret2;
400 }
401
402 grid_root_item_ = new QTreeWidgetItem(ui_->treeWidget);
403 if (grid_root_item_ == nullptr) {
404 goto _ret3;
405 }
406
407 colorChild = new QTreeWidgetItem(grid_root_item_);
408 if (colorChild == nullptr) {
409 goto _ret4;
410 }
411 grid_root_item_->addChild(colorChild);
412 colorChild->setText(0, "Color");
413 colorChild->setText(1, tr("%1;%2;%3")
414 .arg(grid_->red())
415 .arg(grid_->green())
416 .arg(grid_->blue()));
417
418 spinbox = new QSpinBox(ui_->treeWidget);
419 if (spinbox == nullptr) {
420 goto _ret5;
421 }
422 spinbox->setMinimum(1);
423 spinbox->setMaximum(100);
424 spinbox->setSingleStep(1);
425 spinbox->setValue(grid_->CellCount());
426 spinbox->setStyleSheet(globalTreeItemStyle);
427
428 cellCountChild = new QTreeWidgetItem(grid_root_item_);
429 if (cellCountChild == nullptr) {
430 goto _ret6;
431 }
432 grid_root_item_->addChild(cellCountChild);
433 cellCountChild->setText(0, "CellCount");
434
435 grid_->set_shader_program(grid_shader_);
436 if (!ui_->sceneWidget->AddPermanentRenderObj(grid_)) {
437 goto _ret7;
438 }
439
440 enable_grid_checkBox_->setText("Enable");
441 enable_grid_checkBox_->setChecked(true);
442 grid_root_item_->setText(0, "Grid");
443 grid_root_item_->setText(1, "");
444
445 ui_->treeWidget->addTopLevelItem(grid_root_item_);
446
447 ui_->treeWidget->setItemWidget(grid_root_item_, 1, enable_grid_checkBox_);
448 ui_->treeWidget->setItemWidget(cellCountChild, 1, spinbox);
449
450 connect(enable_grid_checkBox_, SIGNAL(clicked(bool)), this,
451 SLOT(EnableGrid(bool)));
452 connect(ui_->treeWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)),
453 this, SLOT(EditGridColor(QTreeWidgetItem*, int)));
454 connect(spinbox, SIGNAL(valueChanged(int)), this,
455 SLOT(ChangeGridCellCountBySize(int)));
456 return;
457
458 _ret7:
459 delete cellCountChild;
460 _ret6:
461 delete spinbox;
462 _ret5:
463 delete colorChild;
464 _ret4:
465 delete grid_root_item_;
466 _ret3:
467 delete enable_grid_checkBox_;
468 _ret2:
469 delete grid_;
470 _ret1:
471 QMessageBox::warning(this, tr("Error"),
472 tr("There is no enough memory for creating Grid!!!"),
473 QMessageBox::Ok);
474 return;
475 }
476}
477
478void MainWindow::ChangeGridCellCountBySize(int v) {
479 grid_->Destroy();
480 grid_->set_shader_program(grid_shader_);
481 grid_->SetCellCount(v);
482 grid_->set_is_renderable(true);
483}
484
485void MainWindow::EditGridColor(QTreeWidgetItem* item, int column) {
486 if (column && item != nullptr && grid_root_item_ != nullptr &&
487 item == grid_root_item_->child(0)) {
488 QStringList rgb = item->text(1).split(';');
489 QColor color(rgb.at(0).toInt(), rgb.at(1).toInt(), rgb.at(2).toInt());
490
491 color = QColorDialog::getColor(color, nullptr, tr("set grid color"));
492
493 if (color.isValid()) {
494 QString str =
495 tr("%1;%2;%3").arg(color.red()).arg(color.green()).arg(color.blue());
496 item->setText(1, str);
497
498 grid_->set_grid_color(color);
499 }
500 }
501}
502
503void MainWindow::EnableRadarPoints(bool b) {
504 QCheckBox* obj = static_cast<QCheckBox*>(sender());
505 RadarData* r = StructPtrByMemberPtr(obj, RadarData, enable_checkBox_);
506 ui_->sceneWidget->setTempObjGroupEnabled(r->root_item_.text(0).toStdString(),
507 b);
508}
509
510void MainWindow::ActionOpenRadarChannel(void) {
511 if (radar_points_shader_ == nullptr) {
512 radar_points_shader_ = RenderableObject::CreateShaderProgram(
513 tr(radarVertexPath), tr(radarFragPath));
514 if (radar_points_shader_ != nullptr) {
515 ui_->sceneWidget->AddNewShaderProg("radarpoints", radar_points_shader_);
516 } else {
517 QMessageBox::warning(
518 this, tr("NO Shader"),
519 tr("There is no suitable shader for Radar Points!!!"),
520 QMessageBox::Ok);
521 return;
522 }
523 }
524
525 RadarData* radarProxy;
526
527 if (closed_radarData_list_.empty()) {
528 radarProxy = createRadarData();
529
530 if (radarProxy == nullptr) {
531 QMessageBox::warning(this, tr("No Enough Memory"),
532 tr("There is no enough memory!!!\nCannot add new "
533 "image or video channel!"),
534 QMessageBox::Ok);
535 return;
536 }
537
538 ui_->treeWidget->addTopLevelItem(&radarProxy->root_item_);
539 ui_->treeWidget->setItemWidget(&radarProxy->root_item_, 1,
540 &radarProxy->enable_checkBox_);
541
542 ui_->treeWidget->setItemWidget(&radarProxy->channel_name_item_, 1,
543 &radarProxy->channel_name_combobox_);
544 ui_->treeWidget->setItemWidget(&radarProxy->action_item_, 1,
545 &radarProxy->action_item_button_);
546
547 for (int i = 0; i < all_channel_root_->childCount(); ++i) {
548 QTreeWidgetItem* child = all_channel_root_->child(i);
549 QString channel = child->text(0);
550 if (channel.contains("radar")) {
551 radarProxy->channel_name_combobox_.addItem(channel);
552 }
553 }
554 } else {
555 radarProxy = closed_radarData_list_.takeFirst();
556 }
557
558 connect(&radarProxy->action_item_button_, SIGNAL(clicked(bool)), this,
559 SLOT(openRadarChannel(bool)));
560 connect(&radarProxy->enable_checkBox_, SIGNAL(clicked(bool)), this,
561 SLOT(EnableRadarPoints(bool)));
562 connect(&radarProxy->channel_name_combobox_, SIGNAL(currentIndexChanged(int)),
563 this, SLOT(ChangeRadarChannel()));
564
565 radarData_list_.append(radarProxy);
566
567 radarProxy->root_item_.setHidden(false);
568
569 ui_->treeWidget->setVisible(true);
570 ui_->actionGlobal->setChecked(true);
571}
572
573void MainWindow::openRadarChannel(bool b) {
574 QPushButton* obj = static_cast<QPushButton*>(QObject::sender());
575 RadarData* theVideoImg =
576 StructPtrByMemberPtr(obj, RadarData, action_item_button_);
577 DoOpenRadarChannel(b, theVideoImg);
578}
579
580void MainWindow::DoOpenRadarChannel(bool b, RadarData* radarProxy) {
581 if (b) {
582 if (radarProxy->channel_name_combobox_.currentText().isEmpty()) {
583 QMessageBox::warning(
584 this, tr("Setup Channel Name"),
585 tr("Channel Name cannot be empty!!!\nPlease select one!"),
586 QMessageBox::Ok);
587 radarProxy->action_item_button_.setChecked(false);
588 return;
589 }
590
591 if (!radarProxy->channel_reader_) {
592 radarProxy->channel_reader_ =
594
595 if (!radarProxy->channel_reader_) {
596 QMessageBox::warning(this, tr("Create cyber Channel Reader"),
597 tr("There is no enough memory!!!\nCannot create "
598 "cyber channel reader!"),
599 QMessageBox::Ok);
600 return;
601 }
602
603 auto radarcallback =
604 [this, radarProxy](
605 const std::shared_ptr<apollo::drivers::RadarObstacles>& pdata) {
606 this->RadarRenderCallback(pdata, radarProxy);
607 };
608
609 std::string nodeName("Visualizer-");
610 nodeName.append(radarProxy->root_item_.text(0).toStdString());
611
612 if (!radarProxy->channel_reader_->InstallCallbackAndOpen(
613 radarcallback,
614 radarProxy->channel_name_combobox_.currentText().toStdString(),
615 nodeName)) {
616 QMessageBox::warning(
617 this, tr("Setup Channel Callback"),
618 tr("Channel Callback cannot be installed!!!\nPlease check it!"),
619 QMessageBox::Ok);
620 delete radarProxy->channel_reader_;
621 radarProxy->channel_reader_ = nullptr;
622
623 radarProxy->action_item_button_.setChecked(false);
624 return;
625 }
626 }
627
628 radarProxy->root_item_.setToolTip(
629 0, radarProxy->channel_name_combobox_.currentText());
630
631 radarProxy->action_item_button_.setText("Stop");
632 radarProxy->channel_name_combobox_.setEnabled(false);
633
634 radarProxy->reader_mutex_.unlock();
635 } else {
636 if (!radarProxy->channel_name_combobox_.isEnabled()) {
637 radarProxy->reader_mutex_.lock();
638 radarProxy->action_item_button_.setText("Play");
639 radarProxy->channel_name_combobox_.setEnabled(true);
640 }
641 }
642 ui_->treeWidget->setCurrentItem(nullptr);
643 ui_->treeWidget->clearFocus();
644}
645
646void MainWindow::RadarRenderCallback(
647 const std::shared_ptr<const apollo::drivers::RadarObstacles>& rawData,
648 RadarData* radar) {
649 radar->reader_mutex_.lock();
650 radar->reader_mutex_.unlock();
651
652 std::cout << "-------MainWindow::RadarRenderCallback()-------" << std::endl;
653
654 if (rawData != nullptr) {
655 RadarPoints* r = new RadarPoints(radar_points_shader_);
656 if (r) {
657 if (!r->FillData(rawData) ||
658 !ui_->sceneWidget->AddTempRenderableObj(
659 radar->root_item_.text(0).toStdString(), r)) {
660 delete r;
661 }
662 } else {
663 std::cerr << "cannot create RadarPoints Renderable Object" << std::endl;
664 }
665 }
666}
667
668void MainWindow::ActionOpenPointCloud(void) {
669 if (pointcloud_shader_ == nullptr) {
670 pointcloud_shader_ =
671 RenderableObject::CreateShaderProgram(tr(pcVertexPath), tr(pcFragPath));
672 if (pointcloud_shader_ != nullptr) {
673 ui_->sceneWidget->AddNewShaderProg("pointcloud", pointcloud_shader_);
674 } else {
675 QMessageBox::warning(this, tr("NO Shader"),
676 tr("There is no suitable shader for Pointcloud!!!"),
677 QMessageBox::Ok);
678 return;
679 }
680 }
681
682 if (pointcloud_top_item_ == nullptr) {
683 pointcloud_top_item_ = new QTreeWidgetItem(ui_->treeWidget);
684 if (pointcloud_top_item_ == nullptr) {
685 return;
686 }
687
688 pointcloud_top_item_->setText(0, "PointCloud2");
689 pointcloud_top_item_->setText(1, "");
690
691 QTreeWidgetItem* item = new QTreeWidgetItem(pointcloud_top_item_);
692 if (item == nullptr) {
693 QMessageBox::warning(this, tr("NO Enough Memory"),
694 tr("Cannot create tree item for channel name!!!"),
695 QMessageBox::Ok);
696 return;
697 }
698
699 item->setText(0, "ChannelName");
700 ui_->treeWidget->setItemWidget(item, 1, pointcloud_comboBox_);
701
702 item = new QTreeWidgetItem(pointcloud_top_item_);
703 if (item == nullptr) {
704 QMessageBox::warning(this, tr("NO Enough Memory"),
705 tr("Cannot create tree item for channel Action!!!"),
706 QMessageBox::Ok);
707 return;
708 }
709
710 item->setText(0, "Action");
711
712 pointcloud_button_->setText("Play");
713 ui_->treeWidget->setItemWidget(item, 1, pointcloud_button_);
714
715 ui_->treeWidget->setVisible(true);
716 ui_->actionGlobal->setChecked(true);
717 }
718}
719
720void MainWindow::ActionOpenImages(void) {
721 if (open_images_dialog_ == nullptr) {
722 open_images_dialog_ = new VideoImagesDialog(this);
723 if (open_images_dialog_ == nullptr) {
724 QMessageBox::warning(this, tr("No Enough Memory"),
725 tr("There is no enough memory!!!"), QMessageBox::Ok);
726 return;
727 } else {
728 connect(open_images_dialog_, SIGNAL(accepted()), this,
729 SLOT(AddVideoImages()));
730 }
731 }
732
733 open_images_dialog_->show();
734}
735
736void MainWindow::AddVideoImages(void) {
737 int count = open_images_dialog_->count();
738 while (count) {
739 ActionOpenImage();
740 --count;
741 }
742}
743
744void MainWindow::ActionOpenImage(void) {
745 VideoImgProxy* videoImgProxy;
746
747 if (closed_video_image_viewer_list_.empty()) {
748 videoImgProxy = AddVideoImgViewer();
749
750 if (videoImgProxy == nullptr) {
751 QMessageBox::warning(this, tr("No Enough Memory"),
752 tr("There is no enough memory!!!\nCannot add new "
753 "image or video channel!"),
754 QMessageBox::Ok);
755 return;
756 }
757
758 videoImgProxy->video_image_viewer_.setParent(ui_->videoImageWidget);
759
760 ui_->treeWidget->addTopLevelItem(&videoImgProxy->root_item_);
761 ui_->treeWidget->setItemWidget(&videoImgProxy->channel_name_item_, 1,
762 &videoImgProxy->channel_name_combobox_);
763 ui_->treeWidget->setItemWidget(&videoImgProxy->action_item_, 1,
764 &videoImgProxy->action_item_button_);
765
766 for (int i = 0; i < all_channel_root_->childCount(); ++i) {
767 QTreeWidgetItem* child = all_channel_root_->child(i);
768 QString channel = child->text(0);
769 if (channel.contains("camera")) {
770 videoImgProxy->channel_name_combobox_.addItem(channel);
771 }
772 }
773 } else {
774 videoImgProxy = closed_video_image_viewer_list_.takeFirst();
775 }
776
777 connect(&videoImgProxy->action_item_button_, SIGNAL(clicked(bool)), this,
778 SLOT(PlayVideoImage(bool)));
779 connect(&videoImgProxy->channel_name_combobox_,
780 SIGNAL(currentIndexChanged(int)), this,
781 SLOT(ChangeVideoImgChannel()));
782 connect(&videoImgProxy->video_image_viewer_,
783 SIGNAL(focusOnThis(FixedAspectRatioWidget*)), this,
784 SLOT(SelectCurrentTreeItem(FixedAspectRatioWidget*)));
785
786 video_image_viewer_list_.append(videoImgProxy);
787 videoImgProxy->video_image_viewer_.setVisible(true);
788
789 calculateWH();
790
791 videoImgProxy->video_image_viewer_.StartOrStopUpdate(true);
792 videoImgProxy->root_item_.setHidden(false);
793
794 ui_->videoImageWidget->setVisible(true);
795
796 ui_->treeWidget->setVisible(true);
797 ui_->actionGlobal->setChecked(true);
798
799 repaint();
800}
801
802void MainWindow::ActionDelVideoImage(void) {
803 QTreeWidgetItem* topItem = ui_->treeWidget->currentItem();
804 VideoImgProxy* proxy =
805 StructPtrByMemberPtr(topItem, VideoImgProxy, root_item_);
806
807 DoDeleteVideoImg(proxy);
808 ui_->actionDelImage->setEnabled(false);
809}
810
811void MainWindow::CloseVideoImgViewer(bool b) {
812 if (!b) {
813 VideoImgViewer* dock = static_cast<VideoImgViewer*>(sender());
814 DoDeleteVideoImg(
815 StructPtrByMemberPtr(dock, VideoImgProxy, video_image_viewer_));
816 }
817}
818
819void MainWindow::DoDeleteVideoImg(VideoImgProxy* proxy) {
820 disconnect(&proxy->action_item_button_, SIGNAL(clicked(bool)), this,
821 SLOT(PlayVideoImage(bool)));
822 disconnect(&proxy->channel_name_combobox_, SIGNAL(currentIndexChanged(int)),
823 this, SLOT(ChangeVideoImgChannel()));
824 disconnect(&proxy->video_image_viewer_,
825 SIGNAL(focusOnThis(FixedAspectRatioWidget*)), this,
826 SLOT(SelectCurrentTreeItem(FixedAspectRatioWidget*)));
827
828 proxy->action_item_button_.setChecked(false);
829 DoPlayVideoImage(false, proxy);
830
831 proxy->video_image_viewer_.StartOrStopUpdate(false);
832 proxy->root_item_.setHidden(true);
833 proxy->video_image_viewer_.setVisible(false);
834 ui_->videoImageGridLayout->removeWidget(&proxy->video_image_viewer_);
835
836 video_image_viewer_list_.removeOne(proxy);
837 closed_video_image_viewer_list_.append(proxy);
838
839 if (video_image_viewer_list_.count()) {
840 calculateWH();
841 } else {
842 ui_->videoImageWidget->setVisible(false);
843 }
844}
845
846void MainWindow::UpdateActions(void) {
847 QTreeWidgetItem* item = ui_->treeWidget->currentItem();
848 ui_->actionDelImage->setEnabled(false);
849 if (item) {
850 if (!item->parent() && item != pointcloud_top_item_ &&
851 item != all_channel_root_ && item != grid_root_item_) {
852 ui_->actionDelImage->setEnabled(true);
853 }
854 }
855}
856
857void MainWindow::PointCloudReaderCallback(
858 const std::shared_ptr<const apollo::drivers::PointCloud>& pdata) {
859 pointcloud_reader_mutex_.lock();
860 pointcloud_reader_mutex_.unlock();
861 PointCloud* pc = new PointCloud(pdata->point_size(), 4, pointcloud_shader_);
862 if (pc) {
863 if (!pc->FillData(pdata) ||
864 !ui_->sceneWidget->AddTempRenderableObj(pcTempObjGroupName, pc)) {
865 delete pc;
866 }
867 } else {
868 std::cerr << "-----Cannot create PointCloud----------" << std::endl;
869 }
870}
871
872void MainWindow::PlayRenderableObject(bool b) {
873 if (b) {
874 if (pointcloud_comboBox_->currentText().isEmpty()) {
875 QMessageBox::warning(
876 this, tr("Setup Channel Name"),
877 tr("Channel Name cannot be empty!!!\nPlease Select it!"),
878 QMessageBox::Ok);
879 pointcloud_button_->setChecked(false);
880 return;
881 }
882
883 if (!pointcloud_channel_Reader_) {
884 pointcloud_channel_Reader_ =
886
887 if (!pointcloud_channel_Reader_) {
888 QMessageBox::warning(this, tr("Create Cyber Channel Reader"),
889 tr("There is no enough memory!!!\nCannot create "
890 "cyber channel reader!"),
891 QMessageBox::Ok);
892 pointcloud_button_->setChecked(false);
893 return;
894 }
895
896 auto pointCallback =
897 [this](const std::shared_ptr<apollo::drivers::PointCloud>& pdata) {
898 this->PointCloudReaderCallback(pdata);
899 };
900 std::string nodeName("Visualizer-");
901 nodeName.append(pointcloud_top_item_->text(0).toStdString());
902 if (!pointcloud_channel_Reader_->InstallCallbackAndOpen(
903 pointCallback, pointcloud_comboBox_->currentText().toStdString(),
904 nodeName)) {
905 QMessageBox::warning(
906 this, tr("Setup Channel Callback"),
907 tr("Channel Callback cannot be installed!!!\nPlease check it!"),
908 QMessageBox::Ok);
909 delete pointcloud_channel_Reader_;
910 pointcloud_channel_Reader_ = nullptr;
911
912 pointcloud_button_->setChecked(false);
913 return;
914 }
915 }
916
917 ui_->sceneWidget->setToolTip(pointcloud_comboBox_->currentText());
918 pointcloud_top_item_->setToolTip(0, pointcloud_comboBox_->currentText());
919 pointcloud_comboBox_->setEnabled(false);
920 pointcloud_button_->setText(tr("Stop"));
921
922 pointcloud_reader_mutex_.unlock();
923 } else {
924 if (!pointcloud_comboBox_->isEnabled()) {
925 pointcloud_reader_mutex_.lock();
926 pointcloud_comboBox_->setEnabled(true);
927 pointcloud_button_->setText(tr("Show"));
928 }
929 }
930
931 ui_->treeWidget->setCurrentItem(nullptr);
932 ui_->treeWidget->clearFocus();
933}
934
935void MainWindow::ImageReaderCallback(
936 const std::shared_ptr<const apollo::drivers::Image>& imgData,
937 VideoImgProxy* theVideoImgProxy) {
938 theVideoImgProxy->reader_mutex_.lock();
939 if (theVideoImgProxy->dynamic_texture_ != nullptr && imgData != nullptr) {
940 if (theVideoImgProxy->dynamic_texture_->UpdateData(imgData)) {
941 theVideoImgProxy->video_image_viewer_.SetupDynamicTexture(
942 theVideoImgProxy->dynamic_texture_);
943 } else {
944 std::cerr << "--------Cannot update dynamic Texture Data--------"
945 << std::endl;
946 }
947 } else {
948 std::cerr
949 << "----Dynamic Texture is nullptr or apollo.drivers.Image is nullptr"
950 << std::endl;
951 }
952 theVideoImgProxy->reader_mutex_.unlock();
953}
954
955void MainWindow::ImageReaderCallback(
956 const std::shared_ptr<const apollo::drivers::CompressedImage>& imgData,
957 VideoImgProxy* theVideoImgProxy) {
958 theVideoImgProxy->reader_mutex_.lock();
959 if (theVideoImgProxy->dynamic_texture_ != nullptr && imgData != nullptr) {
960 QImage img;
961 const std::string& data = imgData->data();
962 if (img.loadFromData(reinterpret_cast<const unsigned char*>(data.c_str()),
963 static_cast<int>(data.size()))) {
964 if (theVideoImgProxy->dynamic_texture_->UpdateData(img)) {
965 theVideoImgProxy->video_image_viewer_.SetupDynamicTexture(
966 theVideoImgProxy->dynamic_texture_);
967 } else {
968 std::cerr << "--------Cannot update dynamic Texture Data--------"
969 << std::endl;
970 }
971 } else {
972 std::cerr
973 << "-----------Cannot load compressed image from data with QImage"
974 << std::endl;
975 }
976 } else {
977 std::cerr
978 << "----Dynamic Texture is nullptr or apollo.drivers.Image is nullptr"
979 << std::endl;
980 }
981 theVideoImgProxy->reader_mutex_.unlock();
982}
983
984void MainWindow::PlayVideoImage(bool b) {
985 QPushButton* obj = static_cast<QPushButton*>(QObject::sender());
986 VideoImgProxy* theVideoImg =
987 StructPtrByMemberPtr(obj, VideoImgProxy, action_item_button_);
988 DoPlayVideoImage(b, theVideoImg);
989}
990
991void MainWindow::DoPlayVideoImage(bool b, VideoImgProxy* theVideoImg) {
992 if (b) {
993 if (theVideoImg->channel_name_combobox_.currentText().isEmpty()) {
994 QMessageBox::warning(
995 this, tr("Setup Channel Name"),
996 tr("Channel Name cannot be empty!!!\nPlease select one!"),
997 QMessageBox::Ok);
998 theVideoImg->action_item_button_.setChecked(false);
999 return;
1000 }
1001
1002 const std::string channelName =
1003 theVideoImg->channel_name_combobox_.currentText().toStdString();
1004 if (_channelName2TypeMap[channelName] == CompressedImageType)
1005 theVideoImg->isCompressedImage_ = true;
1006
1007 if (!theVideoImg->image_reader_) {
1008 if (theVideoImg->isCompressedImage_) {
1009 theVideoImg->compressed_image_reader_ =
1011 } else {
1012 theVideoImg->image_reader_ =
1014 }
1015
1016 if (!theVideoImg->image_reader_) {
1017 QMessageBox::warning(this, tr("Create cyber Channel Reader"),
1018 tr("There is no enough memory!!!\nCannot create "
1019 "cyber channel reader!"),
1020 QMessageBox::Ok);
1021 return;
1022 }
1023
1024 std::string nodeName("Visualizer-");
1025 nodeName.append(theVideoImg->root_item_.text(0).toStdString());
1026
1027 bool ret = false;
1028
1029 if (theVideoImg->isCompressedImage_) {
1030 auto videoCallback =
1031 [this, theVideoImg](
1032 const std::shared_ptr<apollo::drivers::CompressedImage>&
1033 pdata) { this->ImageReaderCallback(pdata, theVideoImg); };
1034
1035 ret = theVideoImg->compressed_image_reader_->InstallCallbackAndOpen(
1036 videoCallback, channelName, nodeName);
1037 } else {
1038 auto videoCallback =
1039 [this, theVideoImg](
1040 const std::shared_ptr<apollo::drivers::Image>& pdata) {
1041 this->ImageReaderCallback(pdata, theVideoImg);
1042 };
1043 ret = theVideoImg->image_reader_->InstallCallbackAndOpen(
1044 videoCallback, channelName, nodeName);
1045 }
1046 if (!ret) {
1047 QMessageBox::warning(
1048 this, tr("Setup Channel Callback"),
1049 tr("Channel Callback cannot be installed!!!\nPlease check it!"),
1050 QMessageBox::Ok);
1051
1052 theVideoImg->deleteReader();
1053 theVideoImg->action_item_button_.setChecked(false);
1054 return;
1055 }
1056 }
1057
1058 theVideoImg->root_item_.setToolTip(
1059 0, theVideoImg->channel_name_combobox_.currentText());
1060 theVideoImg->video_image_viewer_.setToolTip(
1061 theVideoImg->channel_name_combobox_.currentText());
1062
1063 theVideoImg->action_item_button_.setText("Stop");
1064 theVideoImg->channel_name_combobox_.setEnabled(false);
1065
1066 theVideoImg->reader_mutex_.unlock();
1067 } else {
1068 if (!theVideoImg->channel_name_combobox_.isEnabled()) {
1069 theVideoImg->reader_mutex_.lock();
1070 theVideoImg->action_item_button_.setText("Play");
1071 theVideoImg->channel_name_combobox_.setEnabled(true);
1072 }
1073 }
1074 ui_->treeWidget->setCurrentItem(nullptr);
1075 ui_->treeWidget->clearFocus();
1076}
1077
1078void MainWindow::ChangePointCloudChannel() {
1079 if (pointcloud_channel_Reader_ != nullptr) {
1080 pointcloud_channel_Reader_->CloseChannel();
1081 std::string nodeName("Visualizer-");
1082 nodeName.append(pointcloud_top_item_->text(0).toStdString());
1083 pointcloud_channel_Reader_->OpenChannel(
1084 pointcloud_comboBox_->currentText().toStdString(), nodeName);
1085 }
1086}
1087
1088void MainWindow::ChangeVideoImgChannel() {
1089 QComboBox* obj = static_cast<QComboBox*>(QObject::sender());
1090 VideoImgProxy* theVideoImg =
1091 StructPtrByMemberPtr(obj, VideoImgProxy, channel_name_combobox_);
1092
1093 if (theVideoImg->image_reader_ != nullptr) {
1094 theVideoImg->deleteReader();
1095 }
1096}
1097
1098void MainWindow::ChangeRadarChannel(void) {
1099 QComboBox* obj = static_cast<QComboBox*>(QObject::sender());
1100 RadarData* radar =
1101 StructPtrByMemberPtr(obj, RadarData, channel_name_combobox_);
1102
1103 if (radar->channel_reader_ != nullptr) {
1104 radar->channel_reader_->CloseChannel();
1105 std::string nodeName("Visualizer-");
1106 nodeName.append(radar->root_item_.text(0).toStdString());
1107 radar->channel_reader_->OpenChannel(obj->currentText().toStdString(),
1108 nodeName);
1109 }
1110}
1111
1112void MainWindow::SelectCurrentTreeItem(FixedAspectRatioWidget* dock) {
1113 if (dock) {
1114 VideoImgProxy* theVideoImg =
1115 StructPtrByMemberPtr(dock, VideoImgProxy, video_image_viewer_);
1116 theVideoImg->root_item_.setExpanded(true);
1117 if (ui_->treeWidget->currentItem() == &theVideoImg->root_item_) {
1118 ui_->actionDelImage->setEnabled(true);
1119 } else {
1120 ui_->treeWidget->setCurrentItem(&theVideoImg->root_item_);
1121 }
1122 ui_->treeWidget->setFocus();
1123 }
1124}
1125
1135
1138 const std::string& channelName = role.channel_name();
1139 if (_channelName2TypeMap.find(channelName) != _channelName2TypeMap.end()) {
1140 return;
1141 }
1142 const std::string& msgTypeName = role.message_type();
1143 _channelName2TypeMap[channelName] = msgTypeName;
1144
1145 QTreeWidgetItem* child = new QTreeWidgetItem();
1146 if (child == nullptr) {
1147 QMessageBox::warning(this, tr("Error"), tr("No Enough for New Channel!!!"),
1148 QMessageBox::Ok);
1149 return;
1150 }
1151
1152 QString str(channelName.c_str());
1153 child->setText(0, str);
1154 child->setToolTip(0, str);
1155
1156 bool b = true;
1157 for (int i = 0; i < all_channel_root_->childCount(); ++i) {
1158 if (str < all_channel_root_->child(i)->text(0)) {
1159 all_channel_root_->insertChild(i, child);
1160 b = false;
1161 }
1162 }
1163
1164 if (b) {
1165 all_channel_root_->addChild(child);
1166 }
1167 ui_->treeWidget->setRootIsDecorated(true);
1168
1169 QString msgType(msgTypeName.c_str());
1170 if (msgType.contains("camera", Qt::CaseInsensitive)) {
1171 for (VideoImgProxy* item : video_image_viewer_list_) {
1172 item->channel_name_combobox_.addItem(str);
1173 }
1174
1175 for (VideoImgProxy* item : closed_video_image_viewer_list_) {
1176 item->channel_name_combobox_.addItem(str);
1177 }
1178 }
1179
1180 if (msgType.contains("pointcloud", Qt::CaseInsensitive)) {
1181 pointcloud_comboBox_->addItem(str);
1182 }
1183
1184 if (msgType.contains("radar", Qt::CaseInsensitive)) {
1185 for (RadarData* item : radarData_list_) {
1186 item->channel_name_combobox_.addItem(str);
1187 }
1188
1189 for (RadarData* item : closed_radarData_list_) {
1190 item->channel_name_combobox_.addItem(str);
1191 }
1192 }
1193}
1194
1195void MainWindow::PlayPause(void) {
1196 QObject* obj = QObject::sender();
1197 bool b = true;
1198 if (obj == ui_->actionPause) {
1199 b = false;
1200 }
1201 if (pointcloud_top_item_) {
1202 pointcloud_button_->setChecked(b);
1203 PlayRenderableObject(b);
1204 }
1205 for (VideoImgProxy* p : video_image_viewer_list_) {
1206 p->action_item_button_.setChecked(b);
1207 DoPlayVideoImage(b, p);
1208 }
1209 for (RadarData* item : radarData_list_) {
1210 item->action_item_button_.setChecked(b);
1211 DoOpenRadarChannel(b, item);
1212 }
1213}
1214
1215void MainWindow::resizeEvent(QResizeEvent* event) {
1216 QMainWindow::resizeEvent(event);
1217 calculateWH();
1218}
1219
1220void MainWindow::showMessage() {
1221 QObject* obj = QObject::sender();
1222
1223 if (obj == ui_->actionAbout) {
1224 msg_dialog_->setWindowTitle(tr("About"));
1225 msg_dialog_->setMessage(aboutMessage);
1226 goto showMsgLabel;
1227 }
1228
1229 if (obj == ui_->actionLicense) {
1230 msg_dialog_->setWindowTitle(tr("License"));
1231 msg_dialog_->setMessage(licenseMessage);
1232
1233 showMsgLabel:
1234 msg_dialog_->adjustSize();
1235 msg_dialog_->show();
1236 }
1237}
void CloseChannel(void)
bool InstallCallbackAndOpen(CyberChannelCallback< T > channelCallback, const std::string &channelName, const std::string &nodeName)
bool OpenChannel(const std::string &channelName, const std::string &nodeName)
Definition grid.h:23
int CellCount(void) const
Definition grid.h:48
int red(void) const
Definition grid.h:37
int green(void) const
Definition grid.h:38
void set_grid_color(const QColor &color)
Definition grid.h:42
void SetCellCount(int cellCount)
Definition grid.h:44
int blue(void) const
Definition grid.h:39
void resizeEvent(QResizeEvent *) override
void AddNewWriter(const apollo::cyber::proto::RoleAttributes &role)
MainWindow(QWidget *parent=nullptr)
void TopologyChanged(const apollo::cyber::proto::ChangeMsg &change_msg)
void setMessage(const QString &msg)
Definition msg_dialog.cc:27
bool FillData(const std::shared_ptr< const apollo::drivers::PointCloud > &pData)
Definition pointcloud.cc:47
bool FillData(const std::shared_ptr< const apollo::drivers::RadarObstacles > &pData)
void set_is_renderable(bool b)
void set_shader_program(const std::shared_ptr< QOpenGLShaderProgram > &shaderProgram)
static std::shared_ptr< QOpenGLShaderProgram > CreateShaderProgram(const QString &vertexShaderFileName, const QString &fragShaderFileName)
#define StructPtrByMemberPtr(MemberPtr, StructType, Member)
QTreeWidgetItem root_item_
QPushButton action_item_button_
QTreeWidgetItem channel_name_item_
QTreeWidgetItem action_item_
CyberChannReader< apollo::drivers::RadarObstacles > * channel_reader_
QComboBox channel_name_combobox_
CyberChannReader< apollo::drivers::CompressedImage > * compressed_image_reader_
FixedAspectRatioWidget video_image_viewer_
QTreeWidgetItem action_item_
CyberChannReader< apollo::drivers::Image > * image_reader_
QPushButton action_item_button_
std::shared_ptr< Texture > dynamic_texture_
QTreeWidgetItem root_item_
QTreeWidgetItem channel_name_item_
optional RoleAttributes role_attr