32 #include <OgreSceneManager.h> 33 #include <OgreSceneNode.h> 34 #include <OgreWireBoundingBox.h> 69 return ((uint)iam.
index) + ((uint)(iam.
message >> 32)) + ((uint)(iam.
message & 0xffffffff));
87 QHash<IndexAndMessage, Property*>::const_iterator iter;
121 Ogre::Vector3
pointFromCloud(
const sensor_msgs::PointCloud2ConstPtr& cloud, uint32_t index)
127 const uint32_t xoff = cloud->fields[xi].offset;
128 const uint32_t yoff = cloud->fields[yi].offset;
129 const uint32_t zoff = cloud->fields[zi].offset;
130 const uint8_t type = cloud->fields[xi].datatype;
131 const uint32_t point_step = cloud->point_step;
132 float x = valueFromCloud<float>(cloud, xoff, type, point_step, index);
133 float y = valueFromCloud<float>(cloud, yoff, type, point_step, index);
134 float z = valueFromCloud<float>(cloud, zoff, type, point_step, index);
135 return Ogre::Vector3(x, y, z);
140 typedef std::set<int> S_int;
145 for (; it != end; ++it)
147 uint64_t handle = *it;
148 indices.insert((handle & 0xffffffff) - 1);
153 S_int::iterator it = indices.begin();
154 S_int::iterator end = indices.end();
155 for (; it != end; ++it)
164 new Property(QString(
"Point %1 [cloud 0x%2]").arg(index).arg((uint64_t)message.get()),
165 QVariant(),
"", parent_property);
174 for (
size_t field = 0; field < message->fields.size(); ++field)
176 const sensor_msgs::PointField&
f = message->fields[field];
177 const std::string& name = f.name;
179 if (name ==
"x" || name ==
"y" || name ==
"z" || name ==
"X" || name ==
"Y" || name ==
"Z")
183 if (name ==
"rgb" || name ==
"rgba")
186 valueFromCloud<float>(message, f.offset, f.datatype, message->point_step, index);
189 uint32_t val = *((uint32_t*)&float_val);
191 new ColorProperty(QString(
"%1: %2").arg(field).arg(QString::fromStdString(name)),
192 QColor((val >> 16) & 0xff, (val >> 8) & 0xff, val & 0xff),
"", cat);
200 float val = valueFromCloud<float>(message, f.offset, f.datatype, message->point_step, index);
202 QString(
"%1: %2").arg(field).arg(QString::fromStdString(name)), val,
"", cat);
203 prop->setReadOnly(
true);
213 typedef std::set<int> S_int;
218 for (; it != end; ++it)
220 uint64_t handle = *it;
221 indices.insert((handle & 0xffffffff) - 1);
226 S_int::iterator it = indices.begin();
227 S_int::iterator end = indices.end();
228 for (; it != end; ++it)
245 for (; it != end; ++it)
247 M_HandleToBox::iterator find_it =
boxes_.find(std::make_pair(obj.
handle, *it - 1));
248 if (find_it !=
boxes_.end())
250 Ogre::WireBoundingBox* box = find_it->second.second;
252 aabbs.push_back(box->getWorldBoundingBox());
261 for (; it != end; ++it)
263 int index = (*it & 0xffffffff) - 1;
272 Ogre::AxisAlignedBox aabb(pos - size, pos + size);
282 for (; it != end; ++it)
284 int global_index = (*it & 0xffffffff) - 1;
318 "Whether or not the points in this point cloud are selectable.",
display_,
322 "Rendering mode to use, in order of computational complexity.",
339 "Amount of transparency to apply to the points. " 340 "Note that this is experimental and does not always look correct.",
347 "Duration, in seconds, to keep the incoming points. 0 means only show the latest points.",
353 "Set the transformer to use to set the position of the points.",
display_,
360 "Set the transformer to use to set the color of the points.",
display_,
392 std::vector<std::string>::iterator ci;
394 for (ci = classes.begin(); ci != classes.end(); ci++)
396 const std::string& lookup_name = *ci;
401 ROS_ERROR(
"Transformer type [%s] is already loaded.", name.c_str());
407 connect(trans.get(), SIGNAL(needRetransform()),
this, SLOT(
causeRetransform()));
411 info.readable_name = name;
412 info.lookup_name = lookup_name;
462 cloud_infos_[i]->cloud_->setPickColor(Ogre::ColourValue(0.0
f, 0.0
f, 0.0
f, 0.0
f));
501 cloud_infos_[i]->cloud_->setDimensions(size, size, size);
543 now_sec -
cloud_infos_.front()->receive_time_.toSec() >= point_decay_time)
556 for (; it != end; ++it)
558 if (!(*it)->selection_handler_.get() || !(*it)->selection_handler_->hasSelections())
580 for (; it != end; ++it)
584 V_CloudInfo::iterator next = it;
587 if (next != end && now_sec - cloud_info->receive_time_.toSec() >= point_decay_time)
592 bool per_point_alpha =
findChannelIndex(cloud_info->message_,
"rgba") != -1;
595 cloud_info->cloud_->setRenderMode(mode);
596 cloud_info->cloud_->addPoints(&(cloud_info->transformed_points_.front()),
597 cloud_info->transformed_points_.size());
599 cloud_info->cloud_->setDimensions(size, size, size);
604 cloud_info->scene_node_ =
605 scene_node_->createChildSceneNode(cloud_info->position_, cloud_info->orientation_);
607 cloud_info->scene_node_->attachObject(cloud_info->cloud_.get());
609 cloud_info->selection_handler_.reset(
622 if (lock.owns_lock())
628 for (; it != end; ++it)
630 const std::string& name = it->first;
648 for (
int i = 0; i < props.size(); i++)
650 props[i]->setHidden(hide);
663 typedef std::set<std::pair<uint8_t, std::string> >
S_string;
664 S_string valid_xyz, valid_color;
665 bool cur_xyz_valid =
false;
666 bool cur_color_valid =
false;
667 bool has_rgb_transformer =
false;
668 M_TransformerInfo::iterator trans_it =
transformers_.begin();
670 for (; trans_it != trans_end; ++trans_it)
672 const std::string& name = trans_it->first;
674 uint32_t mask = trans->supports(cloud);
677 valid_xyz.insert(std::make_pair(trans->score(cloud), name));
678 if (name == xyz_name)
680 cur_xyz_valid =
true;
687 valid_color.insert(std::make_pair(trans->score(cloud), name));
688 if (name == color_name)
690 cur_color_valid =
true;
694 has_rgb_transformer =
true;
702 if (!valid_xyz.empty())
708 if (!cur_color_valid)
710 if (!valid_color.empty())
712 if (has_rgb_transformer)
726 std::stringstream ss;
734 info->message_ = cloud;
808 for (; it != end; ++it)
812 cloud_info->cloud_->clear();
813 cloud_info->cloud_->addPoints(&cloud_info->transformed_points_.front(),
814 cloud_info->transformed_points_.size());
820 if (!cloud_info->scene_node_)
823 cloud_info->orientation_))
825 std::stringstream ss;
826 ss <<
"Failed to transform from frame [" << cloud_info->message_->header.frame_id <<
"] to frame [" 833 Ogre::Matrix4 transform;
834 transform.makeTransform(cloud_info->position_, Ogre::Vector3(1, 1, 1), cloud_info->orientation_);
837 cloud_points.clear();
839 size_t size = cloud_info->message_->width * cloud_info->message_->height;
841 default_pt.
color = Ogre::ColourValue(1, 1, 1);
842 default_pt.
position = Ogre::Vector3::ZERO;
843 cloud_points.resize(size, default_pt);
847 if (update_transformers)
856 std::stringstream ss;
857 ss <<
"No position transformer available for cloud";
864 std::stringstream ss;
865 ss <<
"No color transformer available for cloud";
876 for (V_PointCloudPoint::iterator cloud_point = cloud_points.begin(); cloud_point != cloud_points.end();
881 cloud_point->position.x = 999999.0f;
882 cloud_point->position.y = 999999.0f;
883 cloud_point->position.z = 999999.0f;
891 sensor_msgs::PointCloud2& output)
893 output.header = input.header;
894 output.width = input.points.size();
896 output.fields.resize(3 + input.channels.size());
898 output.fields[0].name =
"x";
899 output.fields[1].name =
"y";
900 output.fields[2].name =
"z";
903 for (
size_t d = 0;
d < output.fields.size(); ++
d, offset += 4)
905 output.fields[
d].offset = offset;
906 output.fields[
d].datatype = sensor_msgs::PointField::FLOAT32;
908 output.point_step = offset;
909 output.row_step = output.point_step * output.width;
911 for (
size_t d = 0;
d < input.channels.size(); ++
d)
912 output.fields[3 +
d].name = input.channels[
d].name;
913 output.data.resize(input.points.size() * output.point_step);
914 output.is_bigendian =
false;
915 output.is_dense =
false;
918 for (
size_t cp = 0; cp < input.points.size(); ++cp)
920 memcpy(&output.data[cp * output.point_step + output.fields[0].offset], &input.points[cp].x,
922 memcpy(&output.data[cp * output.point_step + output.fields[1].offset], &input.points[cp].y,
924 memcpy(&output.data[cp * output.point_step + output.fields[2].offset], &input.points[cp].z,
926 for (
size_t d = 0;
d < input.channels.size(); ++
d)
928 if (input.channels[
d].values.size() == input.points.size())
930 memcpy(&output.data[cp * output.point_step + output.fields[3 +
d].offset],
931 &input.channels[
d].values[cp],
sizeof(
float));
940 sensor_msgs::PointCloud2Ptr out(
new sensor_msgs::PointCloud2);
976 const sensor_msgs::PointCloud2ConstPtr& msg =
cloud_infos_.front()->message_;
980 for (; it != end; ++it)
983 if ((trans->supports(msg) & mask) == mask)
985 prop->
addOption(QString::fromStdString(it->first));
float getSelectionBoxSize()
void setXyzTransformerOptions(EnumProperty *prop)
void setStatusStd(StatusProperty::Level level, const std::string &name, const std::string &text)
Show status level and text, using a std::string. Convenience function which converts std::string to Q...
FloatProperty * alpha_property_
void setStringStd(const std::string &str)
Set the value of this property to the given std::string. Does not force the value to be one of the li...
pluginlib::ClassLoader< PointCloudTransformer > * transformer_class_loader_
std::set< std::string > S_string
void setPropertiesHidden(const QList< Property *> &props, bool hide)
void destroyBox(const std::pair< CollObjectHandle, uint64_t > &handles)
Destroy the box associated with the given handle-int pair, if there is one.
void updateTransformers(const sensor_msgs::PointCloud2ConstPtr &cloud)
CollObjectHandle getHandle() const
~PointCloudSelectionHandler() override
uint qHash(IndexAndMessage iam)
PointCloudTransformerPtr getColorTransformer(const sensor_msgs::PointCloud2ConstPtr &cloud)
PointCloudTransformerPtr getXYZTransformer(const sensor_msgs::PointCloud2ConstPtr &cloud)
std::vector< PointCloud::Point > transformed_points_
void createBox(const std::pair< CollObjectHandle, uint64_t > &handles, const Ogre::AxisAlignedBox &aabb, const std::string &material_name)
Create or update a box for the given handle-int pair, with the box specified by aabb.
boost::mutex new_clouds_mutex_
void updateXyzTransformer()
void emitTimeSignal(ros::Time time)
Emit a time signal that other Displays can synchronize to.
FloatProperty * point_world_size_property_
FloatProperty * decay_time_property_
A single element of a property tree, with a name, value, description, and possibly children...
IndexAndMessage(int _index, const void *_message)
Ogre::SceneNode * scene_node_
virtual void clearOptions()
Clear the list of options.
void postRenderPass(uint32_t pass) override
EnumProperty * xyz_transformer_property_
bool new_xyz_transformer_
void initialize(DisplayContext *context, Ogre::SceneNode *scene_node)
virtual void preRenderPass(uint32_t pass)
static Ogre::ColourValue handleToColor(CollObjectHandle handle)
void onSelect(const Picked &obj) override
friend class PointCloudSelectionHandler
Property specialized to enforce floating point max/min.
bool convertPointCloudToPointCloud2(const sensor_msgs::PointCloud &input, sensor_msgs::PointCloud2 &output)
QHash< IndexAndMessage, Property * > property_hash_
boost::shared_ptr< PointCloudTransformer > PointCloudTransformerPtr
void setReadOnly(bool read_only) override
Overridden from Property to propagate read-only-ness to children.
boost::recursive_mutex transformers_mutex_
Ogre::SceneManager * manager_
std::string getStdString()
PointCloudCommon(Display *display)
Pure-virtual base class for objects which give Display subclasses context in which to work...
std::vector< Ogre::AxisAlignedBox > V_AABB
bool validateFloats(const sensor_msgs::CameraInfo &msg)
void addMessage(const sensor_msgs::PointCloudConstPtr &cloud)
~PointCloudCommon() override
virtual void addOption(const QString &option, int value=0)
EnumProperty * style_property_
void fillTransformerOptions(EnumProperty *prop, uint32_t mask)
EnumProperty * color_transformer_property_
void show()
Show this Property in any PropertyTreeWidgets.
bool new_color_transformer_
Representation of a point, with x/y/z position and r/g/b color.
BoolProperty * selectable_property_
PointCloudCommon::CloudInfo * cloud_info_
std::vector< PointCloud::Point > V_PointCloudPoint
M_TransformerInfo transformers_
virtual FrameManager * getFrameManager() const =0
Return the FrameManager instance.
void destroyProperties(const Picked &obj, Property *parent_property) override
Destroy all properties for the given picked object(s).
void addOptionStd(const std::string &option, int value=0)
void setColorTransformerOptions(EnumProperty *prop)
FloatProperty * point_pixel_size_property_
DisplayContext * context_
L_CloudInfo obsolete_cloud_infos_
bool operator==(IndexAndMessage a, IndexAndMessage b)
const std::string & getFixedFrame()
Return the current fixed frame name.
void getAABBs(const Picked &obj, V_AABB &aabbs) override
void onDeselect(const Picked &obj) override
virtual Ogre::SceneManager * getSceneManager() const =0
Returns the Ogre::SceneManager used for the main RenderPanel.
void createProperties(const Picked &obj, Property *parent_property) override
Override to create properties of the given picked object(s).
virtual void queueRender()=0
Queues a render. Multiple calls before a render happens will only cause a single render.
int32_t findChannelIndex(const sensor_msgs::PointCloud2ConstPtr &cloud, const std::string &channel)
boost::shared_ptr< PointCloud > cloud_
Property specialized to provide getter for booleans.
A visual representation of a set of points.
virtual float getFloat() const
void processMessage(const sensor_msgs::PointCloud2ConstPtr &cloud)
Ogre::Vector3 pointFromCloud(const sensor_msgs::PointCloud2ConstPtr &cloud, uint32_t index)
virtual void postRenderPass(uint32_t pass)
bool getTransform(const Header &header, Ogre::Vector3 &position, Ogre::Quaternion &orientation)
Return the pose for a header, relative to the fixed frame, in Ogre classes.
void preRenderPass(uint32_t pass) override
void setAutoSize(bool auto_size)
Ogre::SceneNode * scene_node_
V_CloudInfo new_cloud_infos_
bool transformCloud(const CloudInfoPtr &cloud, bool fully_update_transformers)
Transforms the cloud into the correct frame, and sets up our renderable cloud.
void hide()
Hide this Property in any PropertyTreeWidgets.
sensor_msgs::PointCloud2ConstPtr message_
void updateColorTransformer()
virtual bool getBool() const
virtual void setReadOnly(bool read_only)
Prevent or allow users to edit this property from a PropertyTreeWidget.
virtual int getOptionInt()
Return the int value of the currently-chosen option, or 0 if the current option string does not have ...
PointCloudSelectionHandler(float box_size, PointCloudCommon::CloudInfo *cloud_info, DisplayContext *context)
void updateBillboardSize()
void update(float wall_dt, float ros_dt)