Skip to content

Commit

Permalink
Adds text label toggling. #114
Browse files Browse the repository at this point in the history
  • Loading branch information
agalbachicar committed Jul 7, 2018
1 parent 60cc606 commit 5ab8999
Show file tree
Hide file tree
Showing 8 changed files with 218 additions and 39 deletions.
47 changes: 47 additions & 0 deletions visualizer/layer_selection_widget.cc
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,50 @@ void LayerSelectionWidget::onGrayedLaneValueChanged(int state) {
void LayerSelectionWidget::onGrayedMarkerValueChanged(int state) {
emit valueChanged("grayed_marker", this->grayedMarkerCheckBox->isChecked());
}

///////////////////////////////////////////////////////
LabelSelectionWidget::LabelSelectionWidget(QWidget* parent) : QWidget(parent) {
// Build the widget.
this->Build();
// Connects all the check box events.
QObject::connect(this->laneCheckBox, SIGNAL(stateChanged(int)), this,
SLOT(onLaneValueChanged(int)));
QObject::connect(this->branchPointCheckBox, SIGNAL(stateChanged(int)), this,
SLOT(onBranchPointValueChanged(int)));
}

///////////////////////////////////////////////////////
LabelSelectionWidget::~LabelSelectionWidget() {}

///////////////////////////////////////////////////////
void LabelSelectionWidget::onLaneValueChanged(int state) {
emit valueChanged("lane_text_label", this->laneCheckBox->isChecked());
}

///////////////////////////////////////////////////////
void LabelSelectionWidget::onBranchPointValueChanged(int state) {
emit valueChanged("branchpoint_text_label",
this->branchPointCheckBox->isChecked());
}

///////////////////////////////////////////////////////
void LabelSelectionWidget::Build() {
this->laneCheckBox = new QCheckBox("Lane", this);
this->branchPointCheckBox = new QCheckBox("BranchPoint", this);

// Sets all the check boxes as activated.
this->laneCheckBox->setChecked(true);
this->branchPointCheckBox->setChecked(true);

auto *layout = new QVBoxLayout(this);
layout->addWidget(laneCheckBox);
layout->addWidget(branchPointCheckBox);

auto *groupBox = new QGroupBox("Labels", this);
groupBox->setLayout(layout);

auto *widgetLayout = new QVBoxLayout(this);
widgetLayout->addWidget(groupBox);
widgetLayout->addStretch();
this->setLayout(widgetLayout);
}
26 changes: 26 additions & 0 deletions visualizer/layer_selection_widget.hh
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,32 @@ class LayerSelectionWidget : public QWidget {
QCheckBox* grayedMarkerCheckBox{nullptr};
};

/// \brief Widget with checkboxes to enable / disable label visualization.
class LabelSelectionWidget : public QWidget {
Q_OBJECT

public:
/// \brief Default constructor.
explicit LabelSelectionWidget(QWidget* parent = 0);

/// \brief Default Destructor.
virtual ~LabelSelectionWidget();

public slots:
void onLaneValueChanged(int state);
void onBranchPointValueChanged(int state);

signals:
void valueChanged(const std::string& key, bool newValue);

private:
/// \brief Builds the GUI with all the check boxes for label toggling.
void Build();

QCheckBox* branchPointCheckBox{nullptr};
QCheckBox* laneCheckBox{nullptr};
};

}
}
#endif
22 changes: 22 additions & 0 deletions visualizer/maliput_viewer_model.cc
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ ignition::math::Vector3d LaneEndWorldPosition(
MaliputLabel LabelFor(const drake::maliput::api::BranchPoint& bp) {
MaliputLabel label;
label.text = bp.id().string();
label.enabled = true;
label.visible = true;
if (bp.GetASide() && bp.GetASide()->size() != 0) {
label.position = LaneEndWorldPosition(bp.GetASide()->get(0));
Expand All @@ -150,6 +151,7 @@ MaliputLabel LabelFor(const drake::maliput::api::BranchPoint& bp) {
MaliputLabel LabelFor(const drake::maliput::api::Lane& lane) {
MaliputLabel label;
label.text = lane.id().string();
label.enabled = true;
label.visible = true;
const drake::maliput::api::GeoPosition position =
lane.ToGeoPosition({lane.length() / 2., 0., 0.});
Expand Down Expand Up @@ -190,3 +192,23 @@ void MaliputViewerModel::SetLayerState(const std::string& _key, bool _isVisible)
}
this->maliputMeshes[_key]->visible = _isVisible;
}

///////////////////////////////////////////////////////
void MaliputViewerModel::SetTextLabelState(
const std::string& _key, bool _isVisible) {
if (_key == "lane_text_label") {
std::vector<MaliputLabel>& lane_labels = labels[MaliputLabelType::kLane];
for (MaliputLabel& label : lane_labels) {
label.visible = _isVisible;
}
} else if ("branchpoint_text_label") {
std::vector<MaliputLabel>& branchpoint_labels =
labels[MaliputLabelType::kBranchPoint];
for (MaliputLabel& label : branchpoint_labels) {
label.visible = _isVisible;
}
} else {
ignerr << "_key = [" << _key << " ] is not \"lane_text_label\" nor "
"\"branchpoint_text_label\"." << std::endl;
}
}
5 changes: 5 additions & 0 deletions visualizer/maliput_viewer_model.hh
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ class MaliputViewerModel {
/// \param[in] _newVisualState The new visualization status of the mesh.
void SetLayerState(const std::string& _key, bool _isVisible);

/// \brief Modifies the visualization state of @p key text label.
/// \param[in] _key The name of the label.
/// \param[in] _newVisualState The new visualization status of the text label.
void SetTextLabelState(const std::string& _key, bool _isVisible);

private:
/// \brief Loads a maliput RoadGeometry of either monolane or multilane from
/// @p _maliputFilePath.
Expand Down
30 changes: 26 additions & 4 deletions visualizer/maliput_viewer_widget.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ MaliputViewerWidget::MaliputViewerWidget(QWidget* parent)
QObject::connect(this->layerSelectionWidget,
SIGNAL(valueChanged(const std::string&, bool)), this,
SLOT(OnLayerMeshChanged(const std::string&, bool)));

QObject::connect(this->labelSelectionWidget,
SIGNAL(valueChanged(const std::string&, bool)), this,
SLOT(OnTextLabelChanged(const std::string&, bool)));
}

/////////////////////////////////////////////////
Expand All @@ -28,6 +32,15 @@ void MaliputViewerWidget::OnLayerMeshChanged(const std::string& key,
this->renderWidget->RenderRoadMeshes(this->model->Meshes());
}

/////////////////////////////////////////////////
void MaliputViewerWidget::OnTextLabelChanged(
const std::string& key, bool newValue) {
// Updates the model.
this->model->SetTextLabelState(key, newValue);
// Replicates into the GUI.
this->renderWidget->RenderLabels(this->model->Labels());
}

/////////////////////////////////////////////////
QPaintEngine* MaliputViewerWidget::paintEngine() const { return nullptr; }

Expand All @@ -42,11 +55,20 @@ void MaliputViewerWidget::BuildGUI() {
this->setMinimumHeight(100);

this->layerSelectionWidget = new LayerSelectionWidget(this);
this->labelSelectionWidget = new LabelSelectionWidget(this);
this->renderWidget = new RenderMaliputWidget(this);
auto layout = new QHBoxLayout(this);
layout->addWidget(this->renderWidget);
layout->addWidget(this->layerSelectionWidget);
this->setLayout(layout);

auto verticalLayout = new QVBoxLayout(this);
verticalLayout->addWidget(this->layerSelectionWidget);
verticalLayout->addWidget(this->labelSelectionWidget);
auto controlGroup = new QGroupBox("Control panel", this);
controlGroup->setLayout(verticalLayout);

auto horizontalLayout = new QHBoxLayout(this);
horizontalLayout->addWidget(this->renderWidget);
horizontalLayout->addWidget(controlGroup);

this->setLayout(horizontalLayout);
}

/////////////////////////////////////////////////
Expand Down
13 changes: 11 additions & 2 deletions visualizer/maliput_viewer_widget.hh
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,19 @@ class MaliputViewerWidget : public ignition::gui::Plugin {
/// \return NULL.
virtual QPaintEngine* paintEngine() const;


protected slots:
/// \brief Updates the model based on the @p key mesh name and @p newValue and
/// the mesh on the GUI.
/// \param[in] key Name of the mesh.
/// \param[in] newValue New mesh visualization status.
protected slots: void OnLayerMeshChanged(const std::string& key,
bool newValue);
void OnLayerMeshChanged(const std::string& key, bool newValue);

/// \brief Updates the model based on the @p key text label group name and
/// @p newValue and the label group on the GUI.
/// \param[in] key Name of the label group.
/// \param[in] newValue New label group visualization status.
void OnTextLabelChanged(const std::string& key, bool newValue);

protected:
/// \brief Overridden method to receive Qt paint event.
Expand All @@ -57,6 +64,8 @@ class MaliputViewerWidget : public ignition::gui::Plugin {
/// \brief Widget to hold and modify the visualization status of each layer.
LayerSelectionWidget* layerSelectionWidget{nullptr};

LabelSelectionWidget* labelSelectionWidget{nullptr};

/// \brief World render widget.
RenderMaliputWidget* renderWidget{nullptr};

Expand Down
88 changes: 59 additions & 29 deletions visualizer/render_maliput_widget.cc
Original file line number Diff line number Diff line change
Expand Up @@ -260,9 +260,9 @@ bool RenderMaliputWidget::FillMaterial(
/////////////////////////////////////////////////
void RenderMaliputWidget::CreateTransparentMaterial(
ignition::rendering::MaterialPtr& _material) const {
_material->SetDiffuse(0., 0., 0.);
_material->SetAmbient(0., 0., 0.);
_material->SetSpecular(0., 0., 0.);
_material->SetDiffuse(0., 0., 0., 0.);
_material->SetAmbient(0., 0., 0., 0.);
_material->SetSpecular(0., 0., 0., 0.);
_material->SetShininess(0.);
_material->SetTransparency(1.);
}
Expand Down Expand Up @@ -350,37 +350,67 @@ void RenderMaliputWidget::RenderLabels(
const std::map<MaliputLabelType, std::vector<MaliputLabel>>& _labels) {
for (const auto& it : _labels) {
for (const MaliputLabel& label : it.second) {
ignition::rendering::VisualPtr visual = this->scene->CreateVisual();
visual->SetLocalPose(ignition::math::Pose3d(
label.position, ignition::math::Quaterniond()));
// Creates the text geometry.
ignition::rendering::TextPtr textGeometry = this->scene->CreateText();
textGeometry->SetFontName("Liberation Sans");
textGeometry->SetTextString(label.text);
textGeometry->SetShowOnTop(true);
textGeometry->SetTextAlignment(
ignition::rendering::TextHorizontalAlign::CENTER,
ignition::rendering::TextVerticalAlign::CENTER);
visual->AddGeometry(textGeometry);

// Creates a material for the visual.
ignition::rendering::MaterialPtr material = this->scene->CreateMaterial();
if (label.visible) {
if (it.first == MaliputLabelType::kLane) {
CreateLaneLabelMaterial(material);
} else if (it.first == MaliputLabelType::kBranchPoint) {
CreateBranchPointLabelMaterial(material);
} else {
ignerr << "Unsuported label type for: " << label.text << std::endl;
if (!material) {
ignerr << "Failed to create material.\n";
return;
}
// Checks if the text labels to be rendered already exists or not.
const auto labelExists = this->textLabels.find(label.text);
// If the text label is disabled, there is no visual for it so it must be
// set to transparent.
if (!label.enabled) {
// If the text label already exits, a new transparent material is set.
if (labelExists != this->meshes.end()) {
this->CreateTransparentMaterial(material);
this->textLabels[label.text]->SetMaterial(material);
}
} else {
CreateTransparentMaterial(material);
}
// If the text label doesn't exist, it creates new one. Otherwise, just
// it gathers the pointer to set the correct material.
ignition::rendering::VisualPtr visual;
if (labelExists == this->textLabels.end()) {
visual = this->scene->CreateVisual();
if (!visual) {
ignerr << "Failed to create visual.\n";
return;
}
// Adds the visual to the map for later reference.
this->textLabels[label.text] = visual;
visual->SetLocalPose(ignition::math::Pose3d(
label.position, ignition::math::Quaterniond()));
// Creates the text geometry.
ignition::rendering::TextPtr textGeometry = this->scene->CreateText();
textGeometry->SetFontName("Liberation Sans");
textGeometry->SetTextString(label.text);
textGeometry->SetShowOnTop(true);
textGeometry->SetTextAlignment(
ignition::rendering::TextHorizontalAlign::CENTER,
ignition::rendering::TextVerticalAlign::CENTER);
visual->AddGeometry(textGeometry);
// Adds the mesh to the parent root visual.
this->rootVisual->AddChild(visual);
} else {
visual = this->textLabels[label.text];
}

// Applies the correct material to the mesh.
visual->SetMaterial(material);
// Adds the mesh to the parent root visual.
this->rootVisual->AddChild(visual);
// Assigns a material for the visual.
if (label.visible) {
if (it.first == MaliputLabelType::kLane) {
CreateLaneLabelMaterial(material);
} else if (it.first == MaliputLabelType::kBranchPoint) {
CreateBranchPointLabelMaterial(material);
} else {
ignerr << "Unsupported label type for: " << label.text
<< std::endl;
}
} else {
CreateTransparentMaterial(material);
}
// Applies the correct material to the mesh.
visual->SetMaterial(material);
}
}
}
}
Expand Down
26 changes: 22 additions & 4 deletions visualizer/render_maliput_widget.hh
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,12 @@ class RenderMaliputWidget : public QWidget {
/// \brief Destructor.
virtual ~RenderMaliputWidget();

/// \brief Builds visuals for each mesh inside @p _maliputMeshes whose state
/// is State::kOn.
/// \brief Builds visuals for each mesh inside @p _maliputMeshes that is
/// enabled.
/// \details When meshes are disabled but were previously created, their
/// material are set to transparent. The same happens to those which
/// are both enabled and visibility flag is false. Otherwise, the mesh is
/// created (if necessary) with its appropriate material.
/// \param[in] _maliputMeshes A map of meshes to render.
// TODO(agalbachicar): In order to properly modify the visibility of the
// meshes, we should query visuals for their mesh rather than creating a new
Expand All @@ -51,9 +55,19 @@ class RenderMaliputWidget : public QWidget {
void RenderRoadMeshes(
const std::map<std::string, std::unique_ptr<MaliputMesh>>& _maliputMeshes);

/// \brief Builds visuals for each label inside @p _labels whose state
/// is State::kOn.
/// \brief Builds visuals for each label inside @p _labels that is enabled.
/// \details When labels are disabled but were previously created, their
/// materials are set to transparent. The same happens to those which are
/// both enabled and visibility flag is false. Otherwise, the text visual is
/// created (if necessary) and its appropriate material is assigned.
/// \param[in] _labels A map of labels to render.
// TODO(agalbachicar): In order to properly modify the visibility of the
// meshes, we should query visuals for their mesh rather than creating a new
// one each time. That API is available on this commit:
// https://bitbucket.org/ignitionrobotics/ign-rendering/commits/5accdc88afc557afc03c811d9e892ccb7f99951a
// ign-cmake dependency should be switched to 'Components' branch. So, once
// everything is stable on default or in a release branch, we should modify
// this method to properly set the transparency.
void RenderLabels(
const std::map<MaliputLabelType, std::vector<MaliputLabel>>& _labels);

Expand Down Expand Up @@ -186,6 +200,10 @@ class RenderMaliputWidget : public QWidget {

/// \brief Map of mesh visual pointers.
std::map<std::string, ignition::rendering::VisualPtr> meshes;

/// \brief Map of text labels visual pointers.
std::map<std::string, ignition::rendering::VisualPtr>
textLabels;
};

}
Expand Down

0 comments on commit 5ab8999

Please sign in to comment.