Newer
Older
#include <OGRE/OgreSceneNode.h>
#include <OGRE/OgreSceneManager.h>
#include <tf/transform_listener.h>
#include <rviz/visualization_manager.h>
#include <rviz/properties/color_property.h>
#include <rviz/properties/float_property.h>
#include <rviz/default_plugin/covariance_property.h>
#include <rviz/ogre_helpers/arrow.h>
#include <rviz/ogre_helpers/movable_text.h>
#include <rviz/ogre_helpers/billboard_line.h>
#include "perceptions_display.h"
namespace rviz_multiception
{
PerceptionsDisplay::PerceptionsDisplay()
{
color_property_ = new rviz::ColorProperty( "Color", QColor( 10, 10, 10 ),
"Color to draw the arrows.",
this, SLOT( updateColorAndAlpha() ));
alpha_property_ = new rviz::FloatProperty( "Alpha", 1.0,
"State transparency, 0 is fully transparent, 1.0 is fully opaque.",
this, SLOT( updateColorAndAlpha() ));
shape_alpha_property_ = new rviz::FloatProperty( "Shape Alpha", 0.4,
"Shape transparency, 0 is fully transparent, 1.0 is fully opaque.",
trace_duration_property_ = new rviz::FloatProperty( "Trace Duration (s)", 1,
"Duration of state traces, in seconds.",
this, SLOT( filterTraceBuffer() ));
text_color_property_ = new rviz::ColorProperty( "Debug Text Color", QColor( 10, 10, 10 ),
"Color of the debug text.",
this, SLOT( updateColorAndAlpha() ));
covariance_property_ = new rviz::CovarianceProperty( "Covariance", true, "Whether or not the covariances of the messages should be shown.",
this, SLOT( queueRender() ));
}
void PerceptionsDisplay::onInitialize()
{
MFDClass::onInitialize();
frame_node_ = scene_node_->createChildSceneNode();
}
PerceptionsDisplay::~PerceptionsDisplay()
{
scene_manager_->destroySceneNode(frame_node_);
}
// Clear the visuals by deleting their objects.
void PerceptionsDisplay::reset()
{
MFDClass::reset();
resetVectors();
}
void PerceptionsDisplay::resetVectors(size_t N)
{
pose_visuals_.clear(); pose_visuals_.reserve(N);
shape_visuals_.clear(); shape_visuals_.reserve(N);
cov_visuals_.clear(); cov_visuals_.reserve(N);
text_visuals_.clear(); text_visuals_.reserve(N);
for(Ogre::SceneNode* textNode: text_nodes_) scene_manager_->destroySceneNode(textNode);
text_nodes_.clear(); text_nodes_.reserve(N);
frame_node_->detachAllObjects();
frame_node_->removeAndDestroyAllChildren();
}
// Set the current color and alpha values for each visual.
void PerceptionsDisplay::updateColorAndAlpha()
{
const float alpha = alpha_property_->getFloat();
const float shape_alpha = shape_alpha_property_->getFloat();
const Ogre::ColourValue color = color_property_->getOgreColor();
const Ogre::ColourValue textColor = text_color_property_->getOgreColor();
for(size_t i=0; i<pose_visuals_.size(); i++)
pose_visuals_[i]->setColor(color.r, color.g, color.b, alpha);
shape_visuals_[i]->setColor(color.r, color.g, color.b, alpha*shape_alpha);
// cov_visuals_[i]->setColor(color.r, color.g, color.b, alpha*shape_alpha);
for(size_t i=0; i<text_visuals_.size(); i++)
text_visuals_[i]->setColor(textColor);
}
}
void PerceptionsDisplay::filterTraceBuffer()
{
float duration = trace_duration_property_->getFloat();
double oldestTimePossible = ros::Time::now().toSec() - duration;
auto newEnd = std::remove_if(trace_buffer_.begin(), trace_buffer_.end(), [oldestTimePossible](const multiception::Perceptions::ConstPtr& s)
{
return !s || s->header.stamp.toSec()<oldestTimePossible;
});
trace_buffer_.erase(newEnd, trace_buffer_.end());
std::sort(trace_buffer_.begin(), trace_buffer_.end(), [](const multiception::Perceptions::ConstPtr& a, const multiception::Perceptions::ConstPtr& b)
{
return a->header.stamp<b->header.stamp;
});
}
void PerceptionsDisplay::processMessage(const multiception::Perceptions::ConstPtr& msg)
{
if(msg->perceptions.size()>0)
{
resetVectors(msg->perceptions.size());
}
else
Ogre::Vector3 position;
Ogre::Quaternion orientation;
if(context_->getFrameManager()->getTransform(msg->header.frame_id, msg->header.stamp, position, orientation))
{
frame_node_->setPosition(position);
frame_node_->setOrientation(orientation);
}
else
{
ROS_DEBUG("Error transforming from frame '%s' to frame '%s'", msg->header.frame_id.c_str(), qPrintable(fixed_frame_));
return;
}
// Process the perceptions in the message
for(const multiception::Perception& perception : msg->perceptions)
{
boost::shared_ptr<rviz::Arrow> arrowVis { new rviz::Arrow(scene_manager_, frame_node_) };
boost::shared_ptr<rviz::Shape> shapeVis { new rviz::Shape(rviz::Shape::Cube, scene_manager_, frame_node_) };
boost::shared_ptr<rviz::CovarianceVisual> covVis = covariance_property_->createAndPushBackVisual(scene_manager_, frame_node_);
computeStateObjects(perception.state, *arrowVis, *covVis);
// Process the shape
const float z = (perception.height>0.1) ? perception.height/2+.1 : 1;
shapeVis->setScale( Ogre::Vector3(perception.length, perception.width, std::max(0.1f, perception.height)) );
shapeVis->setPosition( Ogre::Vector3(perception.state.x, perception.state.y, z) );
shapeVis->setOrientation( Ogre::Quaternion(Ogre::Radian(perception.state.yaw), Ogre::Vector3::UNIT_Z) );
// Process the debug text
if(!perception.debug.empty())
{
Ogre::SceneNode* childNode = frame_node_->createChildSceneNode();
boost::shared_ptr<rviz::MovableText> debugText { new rviz::MovableText(perception.debug, "Liberation Sans", .7) };
debugText->setTextAlignment(rviz::MovableText::H_CENTER, rviz::MovableText::V_CENTER);
childNode->setPosition(Ogre::Vector3(perception.state.x, perception.state.y, z+perception.height/2+.1+1) );
childNode->attachObject(debugText.get());
text_visuals_.push_back(debugText);
text_nodes_.push_back(childNode);
}
// Process the buffered trace
trace_buffer_.push_back(msg); filterTraceBuffer(); trace_visuals_.clear();
for(const auto& perceptions : trace_buffer_)
{
for(const auto& p : perceptions->perceptions)
{
// ID 0 represent untracked perception, thus a perception trace is not relevant
if(p.object_id!=0)
{
// Create the visual for this object if non-existent
if(trace_visuals_.count(p.object_id)==0)
{
trace_visuals_[p.object_id] = boost::make_shared<rviz::BillboardLine>(scene_manager_, scene_node_);
}
trace_visuals_[p.object_id]->addPoint(Ogre::Vector3(p.state.x, p.state.y, 0), color);
}
}
pose_visuals_.push_back(arrowVis);
shape_visuals_.push_back(shapeVis);
cov_visuals_.push_back(covVis);
updateColorAndAlpha();
}
} // end namespace rviz_multiception
#include <pluginlib/class_list_macros.h>
PLUGINLIB_EXPORT_CLASS(rviz_multiception::PerceptionsDisplay,rviz::Display)