moveit2
The MoveIt Motion Planning Framework for ROS 2.
Loading...
Searching...
No Matches
perception_widget.cpp
Go to the documentation of this file.
1/*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2018, Mohamad Ayman.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 * * The name of Mohamad Ayman may not be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 *********************************************************************/
33
34/* Author: Mohamad Ayman */
35
36// SA
39
40// Qt
41#include <QApplication>
42#include <QComboBox>
43#include <QFormLayout>
44#include <QGroupBox>
45#include <QLabel>
46#include <QLineEdit>
47#include <QVBoxLayout>
48
49namespace moveit_setup
50{
51namespace app
52{
54{
55 // Basic widget container
56 QVBoxLayout* layout = new QVBoxLayout();
57 layout->setAlignment(Qt::AlignTop);
58
59 // Top Header Area ------------------------------------------------
60
61 auto header = new HeaderWidget(
62 "Setup 3D Perception Sensors",
63 "Configure your 3D sensors to work with MoveIt. Please see <a "
64 "href='https://moveit.picknik.ai/galactic/doc/examples/perception_pipeline/perception_pipeline_tutorial.html"
65 "'>Perception Documentation</a> for more details.",
66 this);
67 layout->addWidget(header);
68
69 // Add spacing
70 QSpacerItem* blank_space = new QSpacerItem(1, 8);
71 layout->addSpacerItem(blank_space);
72
73 // Plugin type combo box
74 QLabel* plugin_field_title = new QLabel(this);
75 plugin_field_title->setText("Optionally choose a type of 3D sensor plugin to configure:");
76 layout->addWidget(plugin_field_title);
77
78 sensor_plugin_field_ = new QComboBox(this);
79 sensor_plugin_field_->setEditable(false);
80 sensor_plugin_field_->setMaximumWidth(600);
81 connect(sensor_plugin_field_, SIGNAL(currentIndexChanged(int)), this, SLOT(sensorPluginChanged(int)));
82 layout->addWidget(sensor_plugin_field_);
83
84 // Point Cloud group -------------------------------------------
85 point_cloud_group_ = new QGroupBox("Point Cloud");
86
87 QFormLayout* point_cloud_form_layout = new QFormLayout();
88 point_cloud_form_layout->setContentsMargins(0, 15, 0, 15);
89
90 // Point Cloud Topic
91 point_cloud_topic_field_ = new QLineEdit(this);
92 point_cloud_topic_field_->setMaximumWidth(400);
93 point_cloud_form_layout->addRow("Point Cloud Topic:", point_cloud_topic_field_);
94
95 // Max Range
96 max_range_field_ = new QLineEdit(this);
97 max_range_field_->setMaximumWidth(400);
98 max_range_field_->setValidator(new QDoubleValidator(this));
99 point_cloud_form_layout->addRow("Max Range:", max_range_field_);
100
101 // Point Subsample
102 point_subsample_field_ = new QLineEdit(this);
103 point_subsample_field_->setMaximumWidth(400);
104 point_subsample_field_->setValidator(new QIntValidator(this));
105 point_cloud_form_layout->addRow("Point Subsample:", point_subsample_field_);
106
107 // Padding Offset
108 padding_offset_field_ = new QLineEdit(this);
109 padding_offset_field_->setMaximumWidth(400);
110 padding_offset_field_->setValidator(new QDoubleValidator(this));
111 point_cloud_form_layout->addRow("Padding Offset:", padding_offset_field_);
112
113 // Padding Scale
114 padding_scale_field_ = new QLineEdit(this);
115 padding_scale_field_->setMaximumWidth(400);
116 padding_scale_field_->setValidator(new QDoubleValidator(this));
117 point_cloud_form_layout->addRow("Padding Scale:", padding_scale_field_);
118
119 // Filtered Cloud Topic
120 filtered_cloud_topic_field_ = new QLineEdit(this);
121 filtered_cloud_topic_field_->setMaximumWidth(400);
122 point_cloud_form_layout->addRow("Filtered Cloud Topic:", filtered_cloud_topic_field_);
123
124 // Max Update Rate
125 max_update_rate_field_ = new QLineEdit(this);
126 max_update_rate_field_->setMaximumWidth(400);
127 max_update_rate_field_->setValidator(new QDoubleValidator(this));
128 point_cloud_form_layout->addRow("Max Update Rate:", max_update_rate_field_);
129
130 // Point Cloud form layout
131 point_cloud_group_->setLayout(point_cloud_form_layout);
132 layout->addWidget(point_cloud_group_);
133
134 // Depth map group --------------------------------------------
135 depth_map_group_ = new QGroupBox("Depth Map");
136
137 // Depth Map form layout
138 QFormLayout* depth_map_form_layout = new QFormLayout();
139 depth_map_form_layout->setContentsMargins(0, 15, 0, 15);
140
141 // Image Topic
142 image_topic_field_ = new QLineEdit(this);
143 image_topic_field_->setMaximumWidth(400);
144 depth_map_form_layout->addRow("Image Topic:", image_topic_field_);
145
146 // Queue Size
147 queue_size_field_ = new QLineEdit(this);
148 queue_size_field_->setMaximumWidth(400);
149 queue_size_field_->setValidator(new QIntValidator(this));
150 depth_map_form_layout->addRow("Queue Size:", queue_size_field_);
151
152 // Near Clipping Plane Distance
153 near_clipping_field_ = new QLineEdit(this);
154 near_clipping_field_->setMaximumWidth(400);
155 near_clipping_field_->setValidator(new QDoubleValidator(this));
156 depth_map_form_layout->addRow("Near Clipping Plane Distance:", near_clipping_field_);
157
158 // Far Clipping Plane Distance
159 far_clipping_field_ = new QLineEdit(this);
160 far_clipping_field_->setMaximumWidth(400);
161 far_clipping_field_->setValidator(new QDoubleValidator(this));
162 depth_map_form_layout->addRow("Far Clipping Plane Distance:", far_clipping_field_);
163
164 // Shadow Threshold
165 shadow_threshold_field_ = new QLineEdit(this);
166 shadow_threshold_field_->setMaximumWidth(400);
167 shadow_threshold_field_->setValidator(new QDoubleValidator(this));
168 depth_map_form_layout->addRow("Shadow Threshold:", shadow_threshold_field_);
169
170 // Padding Offset
171 depth_padding_offset_field_ = new QLineEdit(this);
172 depth_padding_offset_field_->setMaximumWidth(400);
173 depth_padding_offset_field_->setValidator(new QDoubleValidator(this));
174 depth_map_form_layout->addRow("Padding Offset:", depth_padding_offset_field_);
175
176 // Padding Scale
177 depth_padding_scale_field_ = new QLineEdit(this);
178 depth_padding_scale_field_->setMaximumWidth(400);
179 depth_padding_scale_field_->setValidator(new QDoubleValidator(this));
180 depth_map_form_layout->addRow("Padding Scale:", depth_padding_scale_field_);
181
182 // Filtered Cloud Topic
183 depth_filtered_cloud_topic_field_ = new QLineEdit(this);
184 depth_filtered_cloud_topic_field_->setMaximumWidth(400);
185 depth_map_form_layout->addRow("Filtered Cloud Topic:", depth_filtered_cloud_topic_field_);
186
187 // Filtered Cloud Topic
188 depth_max_update_rate_field_ = new QLineEdit(this);
189 depth_max_update_rate_field_->setMaximumWidth(400);
190 depth_max_update_rate_field_->setValidator(new QDoubleValidator(this));
191 depth_map_form_layout->addRow("Max Update Rate:", depth_max_update_rate_field_);
192
193 depth_map_group_->setLayout(depth_map_form_layout);
194 layout->addWidget(depth_map_group_);
195
196 layout->setAlignment(Qt::AlignTop);
197
198 // Finish Layout --------------------------------------------------
199 setLayout(layout);
200}
201
202// ******************************************************************************************
203// Received when this widget is chosen from the navigation menu
204// ******************************************************************************************
209
210// ******************************************************************************************
211// Received when another widget is chosen from the navigation menu
212// ******************************************************************************************
214{
215 // Save the sensor plugin configuration to sensors_plugin_config data structure
216 if (sensor_plugin_field_->currentIndex() == 1)
217 {
218 // Point Cloud plugin fields
219 SensorParameters params;
220 params["sensor_plugin"] = "occupancy_map_monitor/PointCloudOctomapUpdater";
221 params["point_cloud_topic"] = point_cloud_topic_field_->text().trimmed().toStdString();
222 params["max_range"] = max_range_field_->text().trimmed().toStdString();
223 params["point_subsample"] = point_subsample_field_->text().trimmed().toStdString();
224 params["padding_offset"] = padding_offset_field_->text().trimmed().toStdString();
225 params["padding_scale"] = padding_scale_field_->text().trimmed().toStdString();
226 params["max_update_rate"] = max_update_rate_field_->text().trimmed().toStdString();
227 params["filtered_cloud_topic"] = filtered_cloud_topic_field_->text().trimmed().toStdString();
228
229 setup_step_.setConfig(params);
230 }
231 else if (sensor_plugin_field_->currentIndex() == 2)
232 {
233 // Depth Map plugin fields
234 SensorParameters params;
235 params["sensor_plugin"] = "occupancy_map_monitor/DepthImageOctomapUpdater";
236 params["image_topic"] = image_topic_field_->text().trimmed().toStdString();
237 params["queue_size"] = queue_size_field_->text().trimmed().toStdString();
238 params["near_clipping_plane_distance"] = near_clipping_field_->text().trimmed().toStdString();
239 params["far_clipping_plane_distance"] = far_clipping_field_->text().trimmed().toStdString();
240 params["shadow_threshold"] = shadow_threshold_field_->text().trimmed().toStdString();
241 params["padding_scale"] = depth_padding_scale_field_->text().trimmed().toStdString();
242 params["padding_offset"] = depth_padding_offset_field_->text().trimmed().toStdString();
243 params["filtered_cloud_topic"] = depth_filtered_cloud_topic_field_->text().trimmed().toStdString();
244 params["max_update_rate"] = depth_max_update_rate_field_->text().trimmed().toStdString();
245
246 setup_step_.setConfig(params);
247 }
248 else
249 {
250 // Clear the sensors_plugin_config data structure
251 setup_step_.clearSensorPluginConfig();
252 }
253 return true;
254}
255
256void PerceptionWidget::sensorPluginChanged(int index)
257{
258 if (index == 1)
259 {
260 // Point cloud form visible, depth map form invisible
261 point_cloud_group_->setVisible(true);
262 depth_map_group_->setVisible(false);
263 }
264 else if (index == 2)
265 {
266 // Depth map form visible, point cloud form invisible
267 point_cloud_group_->setVisible(false);
268 depth_map_group_->setVisible(true);
269 }
270 else
271 {
272 // All forms invisible
273 point_cloud_group_->setVisible(false);
274 depth_map_group_->setVisible(false);
275 }
276}
277
279{
280 // Only load this combo box once
281 static bool has_loaded = false;
282 if (has_loaded)
283 return;
284 has_loaded = true;
285
286 // Add None option, the default
287 sensor_plugin_field_->addItem("None");
288 sensor_plugin_field_->setCurrentIndex(0);
289
290 // Add the two available plugins to combo box
291 sensor_plugin_field_->addItem("Point Cloud");
292 sensor_plugin_field_->addItem("Depth Map");
293
294 const auto& sensors_vec_map = setup_step_.getSensorPluginConfig();
295 for (auto& sensor_plugin_config : sensors_vec_map)
296 {
297 if (sensor_plugin_config.at("sensor_plugin") == std::string("occupancy_map_monitor/PointCloudOctomapUpdater"))
298 {
299 sensor_plugin_field_->setCurrentIndex(1);
300 point_cloud_topic_field_->setText(QString(sensor_plugin_config.at("point_cloud_topic").c_str()));
301 max_range_field_->setText(QString(sensor_plugin_config.at("max_range").c_str()));
302 point_subsample_field_->setText(QString(sensor_plugin_config.at("point_subsample").c_str()));
303 padding_offset_field_->setText(QString(sensor_plugin_config.at("padding_offset").c_str()));
304 padding_scale_field_->setText(QString(sensor_plugin_config.at("padding_scale").c_str()));
305 max_update_rate_field_->setText(QString(sensor_plugin_config.at("max_update_rate").c_str()));
306 filtered_cloud_topic_field_->setText(QString(sensor_plugin_config.at("filtered_cloud_topic").c_str()));
307 }
308 else if (sensor_plugin_config.at("sensor_plugin") == std::string("occupancy_map_monitor/DepthImageOctomapUpdater"))
309 {
310 sensor_plugin_field_->setCurrentIndex(2);
311 image_topic_field_->setText(QString(sensor_plugin_config.at("image_topic").c_str()));
312 queue_size_field_->setText(QString(sensor_plugin_config.at("queue_size").c_str()));
313 near_clipping_field_->setText(QString(sensor_plugin_config.at("near_clipping_plane_distance").c_str()));
314 far_clipping_field_->setText(QString(sensor_plugin_config.at("far_clipping_plane_distance").c_str()));
315 shadow_threshold_field_->setText(QString(sensor_plugin_config.at("shadow_threshold").c_str()));
316 depth_padding_scale_field_->setText(QString(sensor_plugin_config.at("padding_scale").c_str()));
317 depth_padding_offset_field_->setText(QString(sensor_plugin_config.at("padding_offset").c_str()));
318 depth_filtered_cloud_topic_field_->setText(QString(sensor_plugin_config.at("filtered_cloud_topic").c_str()));
319 depth_max_update_rate_field_->setText(QString(sensor_plugin_config.at("max_update_rate").c_str()));
320 }
321 }
322}
323
324} // namespace app
325} // namespace moveit_setup
326
327#include <pluginlib/class_list_macros.hpp> // NOLINT
PLUGINLIB_EXPORT_CLASS(cached_ik_kinematics_plugin::CachedIKKinematicsPlugin< kdl_kinematics_plugin::KDLKinematicsPlugin >, kinematics::KinematicsBase)
The GUI code for one SetupStep.
void loadSensorPluginsComboBox()
Populate the combo dropdown box with sensor plugins.
void focusGiven() override
Received when this widget is chosen from the navigation menu.
bool focusLost() override
Received when another widget is chosen from the navigation menu.
void clearSensorPluginConfig()
Clear the sensor plugin configuration parameter list.
void setConfig(const SensorParameters &parameters)
const std::vector< SensorParameters > & getSensorPluginConfig()
std::map< std::string, std::string > SensorParameters