46 #include "nav2_rviz_plugins/particle_cloud_display/particle_cloud_display.hpp"
51 #include <OgreManualObject.h>
52 #include <OgreMaterialManager.h>
53 #include <OgreTechnique.h>
55 #include "rviz_common/logging.hpp"
56 #include "rviz_common/msg_conversions.hpp"
57 #include "rviz_common/properties/enum_property.hpp"
58 #include "rviz_common/properties/color_property.hpp"
59 #include "rviz_common/properties/float_property.hpp"
60 #include "rviz_common/validate_floats.hpp"
62 #include "rviz_rendering/objects/arrow.hpp"
63 #include "rviz_rendering/objects/axes.hpp"
65 #include "nav2_rviz_plugins/particle_cloud_display/flat_weighted_arrows_array.hpp"
67 namespace nav2_rviz_plugins
83 ParticleCloudDisplay::ParticleCloudDisplay(
84 rviz_common::DisplayContext * display_context,
85 Ogre::SceneNode * scene_node)
86 : ParticleCloudDisplay()
88 context_ = display_context;
89 scene_node_ = scene_node;
90 scene_manager_ = context_->getSceneManager();
92 arrows2d_ = std::make_unique<FlatWeightedArrowsArray>(scene_manager_);
93 arrows2d_->createAndAttachManualObject(scene_node);
94 arrow_node_ = scene_node_->createChildSceneNode();
95 axes_node_ = scene_node_->createChildSceneNode();
99 ParticleCloudDisplay::ParticleCloudDisplay()
100 : min_length_(0.02f), max_length_(0.3f)
102 initializeProperties();
104 shape_property_->addOption(
"Arrow (Flat)", ShapeType::Arrow2d);
105 shape_property_->addOption(
"Arrow (3D)", ShapeType::Arrow3d);
106 shape_property_->addOption(
"Axes", ShapeType::Axes);
107 arrow_alpha_property_->setMin(0);
108 arrow_alpha_property_->setMax(1);
109 arrow_min_length_property_->setMax(max_length_);
110 arrow_max_length_property_->setMin(min_length_);
113 void ParticleCloudDisplay::initializeProperties()
115 shape_property_ =
new rviz_common::properties::EnumProperty(
116 "Shape",
"Arrow (Flat)",
"Shape to display the pose as.",
this, SLOT(updateShapeChoice()));
118 arrow_color_property_ =
new rviz_common::properties::ColorProperty(
119 "Color", QColor(255, 25, 0),
"Color to draw the arrows.",
this, SLOT(updateArrowColor()));
121 arrow_alpha_property_ =
new rviz_common::properties::FloatProperty(
124 "Amount of transparency to apply to the displayed poses.",
126 SLOT(updateArrowColor()));
128 arrow_min_length_property_ =
new rviz_common::properties::FloatProperty(
129 "Min Arrow Length", min_length_,
"Minimum length of the arrows.",
this, SLOT(updateGeometry()));
131 arrow_max_length_property_ =
new rviz_common::properties::FloatProperty(
132 "Max Arrow Length", max_length_,
"Maximum length of the arrows.",
this, SLOT(updateGeometry()));
135 length_scale_ = max_length_ - min_length_;
136 shaft_radius_scale_ = 0.0435;
137 head_length_scale_ = 0.3043;
138 head_radius_scale_ = 0.1304;
141 ParticleCloudDisplay::~ParticleCloudDisplay()
147 void ParticleCloudDisplay::onInitialize()
149 MFDClass::onInitialize();
150 arrows2d_ = std::make_unique<FlatWeightedArrowsArray>(scene_manager_);
151 arrows2d_->createAndAttachManualObject(scene_node_);
152 arrow_node_ = scene_node_->createChildSceneNode();
153 axes_node_ = scene_node_->createChildSceneNode();
157 void ParticleCloudDisplay::processMessage(
const nav2_msgs::msg::ParticleCloud::ConstSharedPtr msg)
159 if (!validateFloats(*msg)) {
161 rviz_common::properties::StatusProperty::Error,
163 "Message contained invalid floating point values (nans or infs)");
167 if (!setTransform(msg->header)) {
171 poses_.resize(msg->particles.size());
173 for (std::size_t i = 0; i < msg->particles.size(); ++i) {
174 poses_[i].position = rviz_common::pointMsgToOgre(msg->particles[i].pose.position);
175 poses_[i].orientation = rviz_common::quaternionMsgToOgre(msg->particles[i].pose.orientation);
176 poses_[i].weight =
static_cast<float>(msg->particles[i].weight);
181 context_->queueRender();
184 bool ParticleCloudDisplay::validateFloats(
const nav2_msgs::msg::ParticleCloud & msg)
186 for (
auto & particle : msg.particles) {
187 if (!rviz_common::validateFloats(particle.pose) ||
188 !rviz_common::validateFloats(particle.weight))
196 bool ParticleCloudDisplay::setTransform(std_msgs::msg::Header
const & header)
198 Ogre::Vector3 position;
199 Ogre::Quaternion orientation;
200 if (!context_->getFrameManager()->getTransform(header, position, orientation)) {
201 setMissingTransformToFixedFrame(header.frame_id);
206 scene_node_->setPosition(position);
207 scene_node_->setOrientation(orientation);
211 void ParticleCloudDisplay::updateDisplay()
213 int shape = shape_property_->getOptionInt();
215 case ShapeType::Arrow2d:
220 case ShapeType::Arrow3d:
225 case ShapeType::Axes:
233 void ParticleCloudDisplay::updateArrows2d()
235 arrows2d_->updateManualObject(
236 arrow_color_property_->getOgreColor(),
237 arrow_alpha_property_->getFloat(),
243 void ParticleCloudDisplay::updateArrows3d()
245 while (arrows3d_.size() < poses_.size()) {
246 arrows3d_.push_back(makeArrow3d());
248 while (arrows3d_.size() > poses_.size()) {
249 arrows3d_.pop_back();
252 Ogre::Quaternion adjust_orientation(Ogre::Degree(-90), Ogre::Vector3::UNIT_Y);
254 for (std::size_t i = 0; i < poses_.size(); ++i) {
255 shaft_length = std::min(
257 poses_[i].weight * length_scale_ + min_length_,
258 min_length_), max_length_);
261 shaft_length * shaft_radius_scale_,
262 shaft_length * head_length_scale_,
263 shaft_length * head_radius_scale_
265 arrows3d_[i]->setPosition(poses_[i].position);
266 arrows3d_[i]->setOrientation(poses_[i].orientation * adjust_orientation);
270 void ParticleCloudDisplay::updateAxes()
272 while (axes_.size() < poses_.size()) {
273 axes_.push_back(makeAxes());
275 while (axes_.size() > poses_.size()) {
279 for (std::size_t i = 0; i < poses_.size(); ++i) {
280 shaft_length = std::min(
282 poses_[i].weight * length_scale_ + min_length_,
283 min_length_), max_length_);
284 axes_[i]->set(shaft_length, shaft_length * shaft_radius_scale_);
285 axes_[i]->setPosition(poses_[i].position);
286 axes_[i]->setOrientation(poses_[i].orientation);
290 std::unique_ptr<rviz_rendering::Arrow> ParticleCloudDisplay::makeArrow3d()
292 Ogre::ColourValue color = arrow_color_property_->getOgreColor();
293 color.a = arrow_alpha_property_->getFloat();
295 auto arrow = std::make_unique<rviz_rendering::Arrow>(
299 min_length_ * shaft_radius_scale_,
300 min_length_ * head_length_scale_,
301 min_length_ * head_radius_scale_
304 arrow->setColor(color);
308 std::unique_ptr<rviz_rendering::Axes> ParticleCloudDisplay::makeAxes()
310 return std::make_unique<rviz_rendering::Axes>(
314 min_length_ * shaft_radius_scale_
318 void ParticleCloudDisplay::reset()
326 void ParticleCloudDisplay::updateShapeChoice()
328 int shape = shape_property_->getOptionInt();
329 bool use_axes = shape == ShapeType::Axes;
331 arrow_color_property_->setHidden(use_axes);
332 arrow_alpha_property_->setHidden(use_axes);
339 void ParticleCloudDisplay::updateArrowColor()
341 int shape = shape_property_->getOptionInt();
342 Ogre::ColourValue color = arrow_color_property_->getOgreColor();
343 color.a = arrow_alpha_property_->getFloat();
345 if (shape == ShapeType::Arrow2d) {
347 }
else if (shape == ShapeType::Arrow3d) {
348 for (
const auto & arrow : arrows3d_) {
349 arrow->setColor(color);
352 context_->queueRender();
355 void ParticleCloudDisplay::updateGeometry()
357 min_length_ = arrow_min_length_property_->getFloat();
358 max_length_ = arrow_max_length_property_->getFloat();
359 length_scale_ = max_length_ - min_length_;
361 arrow_min_length_property_->setMax(max_length_);
362 arrow_max_length_property_->setMin(min_length_);
364 int shape = shape_property_->getOptionInt();
366 case ShapeType::Arrow2d:
371 case ShapeType::Arrow3d:
372 updateArrow3dGeometry();
376 case ShapeType::Axes:
377 updateAxesGeometry();
383 context_->queueRender();
386 void ParticleCloudDisplay::updateArrow3dGeometry()
389 for (std::size_t i = 0; i < poses_.size() && i < arrows3d_.size(); ++i) {
390 shaft_length = std::min(
392 poses_[i].weight * length_scale_ + min_length_,
393 min_length_), max_length_);
396 shaft_length * shaft_radius_scale_,
397 shaft_length * head_length_scale_,
398 shaft_length * head_radius_scale_
403 void ParticleCloudDisplay::updateAxesGeometry()
406 for (std::size_t i = 0; i < poses_.size() && i < axes_.size(); ++i) {
407 shaft_length = std::min(
409 poses_[i].weight * length_scale_ + min_length_,
410 min_length_), max_length_);
411 axes_[i]->set(shaft_length, shaft_length * shaft_radius_scale_);
415 void ParticleCloudDisplay::setShape(QString shape)
417 shape_property_->setValue(shape);
422 #include <pluginlib/class_list_macros.hpp>
Displays a nav2_msgs/ParticleCloud message as a bunch of line-drawn weighted arrows.