41 #include <boost/algorithm/string.hpp> 44 #include <QColorDialog> 49 #include "ui_topic_select.h" 65 PointCloud2Plugin::PointCloud2Plugin() :
66 config_widget_(new QWidget()),
83 p.setColor(QPalette::Background, Qt::white);
87 QPalette p3(
ui_.status->palette());
88 p3.setColor(QPalette::Text, Qt::red);
89 ui_.status->setPalette(p3);
92 ui_.min_color->setColor(Qt::white);
93 ui_.max_color->setColor(Qt::black);
95 ui_.color_transformer->addItem(QString(
"Flat Color"), QVariant(0));
97 QObject::connect(
ui_.selecttopic,
101 QObject::connect(
ui_.buttonResetBuffer,
105 QObject::connect(
ui_.topic,
106 SIGNAL(editingFinished()),
109 QObject::connect(
ui_.alpha,
110 SIGNAL(valueChanged(
double)),
113 QObject::connect(
ui_.color_transformer,
114 SIGNAL(currentIndexChanged(
int)),
117 QObject::connect(
ui_.max_color,
118 SIGNAL(colorEdited(
const QColor &)),
121 QObject::connect(
ui_.min_color,
122 SIGNAL(colorEdited(
const QColor &)),
125 QObject::connect(
ui_.minValue,
126 SIGNAL(valueChanged(
double)),
129 QObject::connect(
ui_.maxValue,
130 SIGNAL(valueChanged(
double)),
133 QObject::connect(
ui_.bufferSize,
134 SIGNAL(valueChanged(
int)),
137 QObject::connect(
ui_.pointSize,
138 SIGNAL(valueChanged(
int)),
141 QObject::connect(
ui_.use_rainbow,
142 SIGNAL(stateChanged(
int)),
145 QObject::connect(
ui_.unpack_rgb,
146 SIGNAL(stateChanged(
int)),
149 QObject::connect(
ui_.use_automaxmin,
150 SIGNAL(stateChanged(
int)),
153 QObject::connect(
ui_.max_color,
154 SIGNAL(colorEdited(
const QColor &)),
157 QObject::connect(
ui_.min_color,
158 SIGNAL(colorEdited(
const QColor &)),
161 QObject::connect(
this,
165 QObject::connect(
this,
170 PrintInfo(
"Constructed PointCloud2Plugin");
179 ROS_DEBUG(
"PointCloud2Plugin::ClearHistory()");
187 QPixmap icon(16, 16);
188 icon.fill(Qt::transparent);
190 QPainter painter(&icon);
191 painter.setRenderHint(QPainter::Antialiasing,
true);
195 pen.setCapStyle(Qt::RoundCap);
197 pen.setColor(
ui_.min_color->color());
199 painter.drawPoint(2, 13);
201 pen.setColor(
ui_.min_color->color());
203 painter.drawPoint(4, 6);
205 pen.setColor(
ui_.max_color->color());
207 painter.drawPoint(12, 9);
209 pen.setColor(
ui_.max_color->color());
211 painter.drawPoint(13, 2);
222 scan.transformed =
false;
223 scan.gl_color.clear();
224 scan.gl_point.clear();
238 if (subscribe && !
topic_.empty())
251 unsigned int color_transformer =
static_cast<unsigned int>(
ui_.color_transformer->currentIndex());
252 unsigned int transformer_index = color_transformer -1;
255 val = point.
features[transformer_index];
258 if (val >
max_[transformer_index])
260 max_[transformer_index] = val;
263 if (val <
min_[transformer_index])
265 min_[transformer_index] = val;
271 return ui_.min_color->color();
274 if (
ui_.unpack_rgb->isChecked())
276 uint8_t* pixelColor =
reinterpret_cast<uint8_t*
>(&val);
277 return QColor(pixelColor[2], pixelColor[1], pixelColor[0], 255);
284 val = std::max(0.0
f, std::min(val, 1.0
f));
286 if (
ui_.use_automaxmin->isChecked())
292 if (
ui_.use_rainbow->isChecked())
295 int hue = (int)(val * 255.0);
296 return QColor::fromHsl(hue, 255, 127, 255);
300 const QColor min_color =
ui_.min_color->color();
301 const QColor max_color =
ui_.max_color->color();
303 int red, green, blue;
304 red = (int)(val * max_color.red() + ((1.0 - val) * min_color.red()));
305 green = (int)(val * max_color.green() + ((1.0 - val) * min_color.green()));
306 blue = (int)(val * max_color.blue() + ((1.0 - val) * min_color.blue()));
307 return QColor(red, green, blue, 255);
311 inline int32_t
findChannelIndex(
const sensor_msgs::PointCloud2ConstPtr& cloud,
const std::string& channel)
313 for (int32_t i = 0;
static_cast<size_t>(i) < cloud->fields.size(); ++i)
315 if (cloud->fields[i].name == channel)
330 scan.gl_color.clear();
331 scan.gl_color.reserve(scan.points.size()*4);
335 scan.gl_color.push_back( color.red());
336 scan.gl_color.push_back( color.green());
337 scan.gl_color.push_back( color.blue());
338 scan.gl_color.push_back( static_cast<uint8_t>(
alpha_ * 255.0 ) );
348 "sensor_msgs/PointCloud2");
350 if (!topic.
name.empty())
352 ui_.topic->setText(QString::fromStdString(topic.
name));
360 std::string topic =
ui_.topic->text().trimmed().toStdString();
432 scan = std::move(
scans_.front() );
445 scan.
stamp = msg->header.stamp;
446 scan.
color = QColor::fromRgbF(1.0
f, 0.0
f, 0.0
f, 1.0
f);
461 if (xi == -1 || yi == -1 || zi == -1)
468 for (
size_t i = 0; i < msg->fields.size(); ++i)
471 std::string
name = msg->fields[i].name;
473 uint32_t offset_value = msg->fields[i].offset;
474 uint8_t datatype_value = msg->fields[i].datatype;
475 input.
offset = offset_value;
477 scan.
new_features.insert(std::pair<std::string, FieldInfo>(name, input));
489 int new_feature_index =
ui_.color_transformer->currentIndex();
490 std::map<std::string, FieldInfo>::const_iterator it;
499 std::string
const field = it->first;
505 new_feature_index = label;
509 ui_.color_transformer->addItem(QString::fromStdString(field), QVariant(label));
514 ui_.color_transformer->setCurrentIndex(new_feature_index);
519 if (!msg->data.empty())
521 const uint8_t* ptr = &msg->data.front();
522 const uint32_t point_step = msg->point_step;
523 const uint32_t xoff = msg->fields[xi].offset;
524 const uint32_t yoff = msg->fields[yi].offset;
525 const uint32_t zoff = msg->fields[zi].offset;
526 const size_t num_points = msg->data.size() / point_step;
528 scan.
points.resize(num_points);
530 std::vector<FieldInfo> field_infos;
531 field_infos.reserve(num_features);
534 field_infos.push_back(it->second);
538 scan.
gl_point.reserve(num_points*2);
540 scan.
gl_color.reserve(num_points*4);
542 for (
size_t i = 0; i < num_points; i++, ptr += point_step)
544 float x = *
reinterpret_cast<const float*
>(ptr + xoff);
545 float y = *
reinterpret_cast<const float*
>(ptr + yoff);
546 float z = *
reinterpret_cast<const float*
>(ptr + zoff);
551 point.
features.resize(num_features);
553 for (
int count=0; count < field_infos.size(); count++)
564 scan.
gl_color.push_back( color.red());
565 scan.
gl_color.push_back( color.green());
566 scan.
gl_color.push_back( color.blue());
573 scans_.push_back( std::move(scan) );
584 return *
reinterpret_cast<const int8_t*
>(data + feature_info.
offset);
586 return *(data + feature_info.
offset);
588 return *
reinterpret_cast<const int16_t*
>(data + feature_info.
offset);
590 return *
reinterpret_cast<const uint16_t*
>(data + feature_info.
offset);
592 return *
reinterpret_cast<const int32_t*
>(data + feature_info.
offset);
594 return *
reinterpret_cast<const uint32_t*
>(data + feature_info.
offset);
596 return *
reinterpret_cast<const float*
>(data + feature_info.
offset);
598 return *
reinterpret_cast<const double*
>(data + feature_info.
offset);
640 glEnableClientState(GL_VERTEX_ARRAY);
641 glEnableClientState(GL_COLOR_ARRAY);
648 if (scan.transformed && !scan.gl_color.empty())
650 glBindBuffer(GL_ARRAY_BUFFER, scan.point_vbo);
651 glBufferData(GL_ARRAY_BUFFER, scan.gl_point.size() *
sizeof(float), scan.gl_point.data(), GL_STATIC_DRAW);
652 glVertexPointer( 2, GL_FLOAT, 0, 0);
654 glBindBuffer(GL_ARRAY_BUFFER, scan.color_vbo);
655 glBufferData(GL_ARRAY_BUFFER, scan.gl_color.size() *
sizeof(uint8_t), scan.gl_color.data(), GL_STATIC_DRAW);
656 glColorPointer( 4, GL_UNSIGNED_BYTE, 0, 0);
658 glDrawArrays(GL_POINTS, 0, scan.gl_point.size() / 2 );
662 glDisableClientState(GL_VERTEX_ARRAY);
663 glDisableClientState(GL_COLOR_ARRAY);
664 glBindBuffer(GL_ARRAY_BUFFER, 0);
697 if (!scan.transformed)
700 if (
GetTransform(scan.source_frame, scan.stamp, transform))
702 scan.gl_point.clear();
703 scan.gl_point.reserve(scan.points.size()*2);
705 scan.transformed =
true;
709 scan.gl_point.push_back( transformed_point.
getX() );
710 scan.gl_point.push_back( transformed_point.
getY() );
715 ROS_WARN(
"Unable to get transform.");
716 scan.transformed =
false;
724 if (
ui_.color_transformer->currentIndex() ==
COLOR_Z)
731 const std::string& path)
736 node[
"topic"] >> topic;
737 ui_.topic->setText(boost::trim_copy(topic).c_str());
744 ui_.pointSize->setValue(static_cast<int>(point_size_));
747 if (node[
"buffer_size"])
750 ui_.bufferSize->setValue(static_cast<int>(buffer_size_));
753 if (node[
"color_transformer"])
758 if (node[
"min_color"])
760 std::string min_color_str;
761 node[
"min_color"] >> min_color_str;
762 ui_.min_color->setColor(QColor(min_color_str.c_str()));
765 if (node[
"max_color"])
767 std::string max_color_str;
768 node[
"max_color"] >> max_color_str;
769 ui_.max_color->setColor(QColor(max_color_str.c_str()));
772 if (node[
"value_min"])
775 ui_.minValue->setValue(min_value_);
778 if (node[
"value_max"])
781 ui_.maxValue->setValue(max_value_);
787 ui_.alpha->setValue(alpha_);
790 if (node[
"use_rainbow"])
793 node[
"use_rainbow"] >> use_rainbow;
794 ui_.use_rainbow->setChecked(use_rainbow);
797 if (node[
"unpack_rgb"])
800 node[
"unpack_rgb"] >> unpack_rgb;
801 ui_.unpack_rgb->setChecked(unpack_rgb);
807 if (node[
"use_automaxmin"])
810 node[
"use_automaxmin"] >> use_automaxmin;
811 ui_.use_automaxmin->setChecked(use_automaxmin);
821 ROS_DEBUG(
"Color transformer changed to %d", index);
828 bool color_is_flat =
ui_.color_transformer->currentIndex() ==
COLOR_FLAT;
832 ui_.maxColorLabel->hide();
833 ui_.max_color->hide();
834 ui_.minColorLabel->hide();
835 ui_.min_max_color_widget->show();
836 ui_.min_max_value_widget->hide();
837 ui_.use_automaxmin->hide();
838 ui_.use_rainbow->hide();
842 ui_.maxColorLabel->show();
843 ui_.max_color->show();
844 ui_.minColorLabel->show();
845 ui_.min_max_color_widget->setVisible(!
ui_.use_rainbow->isChecked());
846 ui_.min_max_value_widget->setVisible(!
ui_.use_automaxmin->isChecked());
847 ui_.use_automaxmin->show();
848 ui_.use_rainbow->show();
862 alpha_ = std::max(0.0
f, std::min((
float)value, 1.0
f));
866 const std::string& path)
868 emitter << YAML::Key <<
"topic" <<
869 YAML::Value << boost::trim_copy(
ui_.topic->text().toStdString());
870 emitter << YAML::Key <<
"size" <<
871 YAML::Value <<
ui_.pointSize->value();
872 emitter << YAML::Key <<
"buffer_size" <<
873 YAML::Value <<
ui_.bufferSize->value();
874 emitter << YAML::Key <<
"alpha" <<
876 emitter << YAML::Key <<
"color_transformer" <<
877 YAML::Value <<
ui_.color_transformer->currentText().toStdString();
878 emitter << YAML::Key <<
"min_color" <<
879 YAML::Value <<
ui_.min_color->color().name().toStdString();
880 emitter << YAML::Key <<
"max_color" <<
881 YAML::Value <<
ui_.max_color->color().name().toStdString();
882 emitter << YAML::Key <<
"value_min" <<
883 YAML::Value <<
ui_.minValue->value();
884 emitter << YAML::Key <<
"value_max" <<
885 YAML::Value <<
ui_.maxValue->value();
886 emitter << YAML::Key <<
"use_rainbow" <<
887 YAML::Value <<
ui_.use_rainbow->isChecked();
888 emitter << YAML::Key <<
"use_automaxmin" <<
889 YAML::Value <<
ui_.use_automaxmin->isChecked();
890 emitter << YAML::Key <<
"unpack_rgb" <<
891 YAML::Value <<
ui_.unpack_rgb->isChecked();
bool GetTransform(const ros::Time &stamp, swri_transform_util::Transform &transform, bool use_latest_transforms=true)
std::vector< float > gl_point
static ros::master::TopicInfo selectTopic(const std::string &datatype, QWidget *parent=0)
void ResetTransformedPointClouds()
void AlphaEdited(double new_value)
void transform(Route &route, const swri_transform_util::Transform &transform, const std::string &target_frame)
bool Initialize(QGLWidget *canvas)
std::vector< double > max_
QColor CalculateColor(const StampedPoint &point)
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
void Draw(double x, double y, double scale)
void UpdateMinMaxWidgets()
int32_t findChannelIndex(const sensor_msgs::PointCloud2ConstPtr &cloud, const std::string &channel)
void PointCloud2Callback(const sensor_msgs::PointCloud2ConstPtr &scan)
void ColorTransformerChanged(int index)
static void PrintWarningHelper(QLabel *status_label, const std::string &message, double throttle=0.0)
std::vector< uint8_t > gl_color
static void PrintErrorHelper(QLabel *status_label, const std::string &message, double throttle=0.0)
TFSIMD_FORCE_INLINE const tfScalar & getY() const
std::string target_frame_
TFSIMD_FORCE_INLINE const tfScalar & y() const
void MaxValueChanged(double value)
void BufferSizeChanged(int value)
static void PrintInfoHelper(QLabel *status_label, const std::string &message, double throttle=0.0)
void PrintError(const std::string &message)
void SaveConfig(YAML::Emitter &emitter, const std::string &path)
void PrintInfo(const std::string &message)
void LoadConfig(const YAML::Node &node, const std::string &path)
void PointSizeChanged(int value)
void MinValueChanged(double value)
void TargetFrameChanged(const std::string &target_frame)
virtual ~PointCloud2Plugin()
TFSIMD_FORCE_INLINE const tfScalar & x() const
std::vector< float > features
QWidget * GetConfigWidget(QWidget *parent)
std::vector< StampedPoint > points
TFSIMD_FORCE_INLINE const tfScalar & z() const
void VisibleChanged(bool visible)
void SetSubscription(bool subscribe)
std::map< std::string, FieldInfo > new_features
float PointFeature(const uint8_t *, const FieldInfo &)
TFSIMD_FORCE_INLINE const tfScalar & getX() const
Ui::PointCloud2_config ui_
std::vector< double > min_
void UseAutomaxminChanged(int check_state)
std::deque< Scan > scans_
#define PLUGINLIB_EXPORT_CLASS(class_type, base_class_type)
void UseRainbowChanged(int check_state)
void PrintWarning(const std::string &message)
bool use_latest_transforms_
std::string saved_color_transformer_