Why custom Rviz displays need stamped messages?
Hi,
I am trying to create a custom Rviz display which would show a fading-out path of the robot. I wanted to use Pose2D
message because it posess all the data I need. But it appears that I cannot inherit on rviz::MessageFilterDisplay<geometry_msgs::Pose2D>
because it doesn't have header
member. It just freaks me out to prepare the tf broadcaster with quaternions and time stamp when I could get all the info just from this simple Pose2D
message.
When I call the processMessage()
function, the frame manager looks for the transformation based on the header of the message. In my case it make no sense, because I could get the transformation from the message. I could even easily prepare a fake tf here and get the position and orientation for a displayed element from the message. But the problem is that the compiler throws errors that the Pose2D
doesn't have header
.
Is there a way to display non-stamped messages in Rviz?
--- EDIT ---
Thank you so much for your answer ahendrix. I did as you recommended and it worked but I am now having problems in creating a proper class for the display. I am getting the following error when I load the display in Rviz:
Error: MultiLibraryClassLoader: Could not create class of type mtracker_gui::PoseDisplay
When using rviz::Display as base class, how can I handle the subscription for a specific messages (topic)? The MessageFilterDisplay<T>
class seems to handle this problem on its own. Below is the structure of my class:
class PoseDisplay : public rviz::Display
{
Q_OBJECT
public:
PoseDisplay();
virtual ~PoseDisplay();
virtual void onInitialize();
virtual void reset();
private Q_SLOTS:
void updateTopic();
void updateColorAndAlpha();
void updateHistoryLength();
private:
void processMessage(const geometry_msgs::Pose2D::ConstPtr& msg);
boost::circular_buffer<boost::shared_ptr <PoseVisual> > visuals_;
rviz::ColorProperty* color_property_;
rviz::FloatProperty* alpha_property_;
rviz::IntProperty* history_length_property_;
rviz::RosTopicProperty* topic_property_;
};
And further below is its implementation:
PoseDisplay::PoseDisplay() : Display()
{
topic_property_ = new rviz::RosTopicProperty( "Topic", "",
QString::fromStdString( ros::message_traits::datatype<geometry_msgs::Pose2D>() ),
"geometry_msgs::Pose2D topic to subscribe to.",
this, SLOT( updateTopic() ));
color_property_ = new rviz::ColorProperty( "Color", QColor( 204, 51, 204 ),
"Color to draw the pose arrows.",
this, SLOT( updateColorAndAlpha() ));
alpha_property_ = new rviz::FloatProperty( "Alpha", 1.0,
"0 is fully transparent, 1.0 is fully opaque.",
this, SLOT( updateColorAndAlpha() ));
history_length_property_ = new rviz::IntProperty( "History Length", 1,
"Number of prior measurements to display.",
this, SLOT( updateHistoryLength() ));
history_length_property_->setMin( 1 );
history_length_property_->setMax( 100000 );
}
PoseDisplay::~PoseDisplay()
{
}
void PoseDisplay::onInitialize()
{
updateHistoryLength();
}
void PoseDisplay::reset()
{
visuals_.clear();
}
void PoseDisplay::updateTopic()
{
// ???
}
void PoseDisplay::updateColorAndAlpha()
{
float alpha = alpha_property_->getFloat();
Ogre::ColourValue color = color_property_->getOgreColor();
for (size_t i = 0; i < visuals_.size(); i++)
{
visuals_[i]->setColor(color.r, color.g, color.b, alpha);
}
}
void PoseDisplay::updateHistoryLength()
{
visuals_.rset_capacity(history_length_property_->getInt());
}
void PoseDisplay::processMessage(const geometry_msgs::Pose2D::ConstPtr& msg)
{
boost::shared_ptr<PoseVisual> visual;
if (visuals_.full())
{
visual = visuals_.front();
}
else
{
visual.reset(new PoseVisual(context_->getSceneManager(), scene_node_));
}
visual->setMessage(msg);
float alpha = alpha_property_->getFloat();
Ogre::ColourValue color = color_property_->getOgreColor();
visual->setColor(color.r, color.g, color.b, alpha);
visuals_.push_back(visual);
}
This is off-topic. Please ask a new question instead of continuing this thread.