Program Listing for File pie_chart_display.cpp
↰ Return to documentation for file (src/pie_chart_display.cpp
)
// -*- mode: c++; -*-
/*********************************************************************
* Software License Agreement (BSD License)
*
* Copyright (c) 2022, Team Spatzenhirn
* Copyright (c) 2014, JSK Lab
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/o2r other materials provided
* with the distribution.
* * Neither the name of the JSK Lab nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*********************************************************************/
#include "pie_chart_display.h"
#include <OgreMaterialManager.h>
#include <OgreTextureManager.h>
#include <OgreTexture.h>
#include <OgreTechnique.h>
#include <OgreHardwarePixelBuffer.h>
#include <rviz_rendering/render_system.hpp>
#include <QPainter>
namespace rviz_2d_overlay_plugins
{
PieChartDisplay::PieChartDisplay() : data_(0.0), update_required_(false), first_time_(true) {
size_property_ = new rviz_common::properties::IntProperty("size", 128,
"size of the plotter window",
this, SLOT(updateSize()));
left_property_ = new rviz_common::properties::IntProperty("left", 128,
"left of the plotter window",
this, SLOT(updateLeft()));
top_property_ = new rviz_common::properties::IntProperty("top", 128,
"top of the plotter window",
this, SLOT(updateTop()));
fg_color_property_ = new rviz_common::properties::ColorProperty("foreground color",
QColor(25, 255, 240),
"color to draw line",
this, SLOT(updateFGColor()));
fg_alpha_property_
= new rviz_common::properties::FloatProperty("foreground alpha", 0.7,
"alpha belnding value for foreground",
this, SLOT(updateFGAlpha()));
fg_alpha2_property_
= new rviz_common::properties::FloatProperty("foreground alpha 2", 0.4,
"alpha belnding value for foreground for indicator",
this, SLOT(updateFGAlpha2()));
bg_color_property_ = new rviz_common::properties::ColorProperty("background color",
QColor(0, 0, 0),
"background color",
this, SLOT(updateBGColor()));
bg_alpha_property_
= new rviz_common::properties::FloatProperty("backround alpha", 0.0,
"alpha belnding value for background",
this, SLOT(updateBGAlpha()));
text_size_property_
= new rviz_common::properties::IntProperty("text size", 14,
"text size",
this, SLOT(updateTextSize()));
show_caption_property_
= new rviz_common::properties::BoolProperty("show caption", true,
"show caption",
this, SLOT(updateShowCaption()));
max_value_property_
= new rviz_common::properties::FloatProperty("max value", 1.0,
"max value of pie chart",
this, SLOT(updateMaxValue()));
min_value_property_
= new rviz_common::properties::FloatProperty("min value", 0.0,
"min value of pie chart",
this, SLOT(updateMinValue()));
auto_color_change_property_
= new rviz_common::properties::BoolProperty("auto color change",
false,
"change the color automatically",
this, SLOT(updateAutoColorChange()));
max_color_property_
= new rviz_common::properties::ColorProperty("max color",
QColor(255, 0, 0),
"only used if auto color change is set to True.",
this, SLOT(updateMaxColor()));
med_color_property_
= new rviz_common::properties::ColorProperty("med color",
QColor(255, 0, 0),
"only used if auto color change is set to True.",
this, SLOT(updateMedColor()));
max_color_threshold_property_
= new rviz_common::properties::FloatProperty("max color change threthold", 0,
"change the max color at threshold",
this, SLOT(updateMaxColorThreshold()));
med_color_threshold_property_
= new rviz_common::properties::FloatProperty("med color change threthold", 0,
"change the med color at threshold ",
this, SLOT(updateMedColorThreshold()));
clockwise_rotate_property_
= new rviz_common::properties::BoolProperty("clockwise rotate direction",
false,
"change the rotate direction",
this, SLOT(updateClockwiseRotate()));
}
PieChartDisplay::~PieChartDisplay()
{
if (overlay_->isVisible()) {
overlay_->hide();
}
}
void PieChartDisplay::onInitialize()
{
RTDClass::onInitialize();
rviz_rendering::RenderSystem::get()->prepareOverlays(scene_manager_);
static int count = 0;
std::stringstream ss;
ss << "PieChartDisplayObject" << count++;
overlay_.reset(new rviz_2d_overlay_plugins::OverlayObject(ss.str()));
onEnable();
updateSize();
updateLeft();
updateTop();
updateFGColor();
updateBGColor();
updateFGAlpha();
updateFGAlpha2();
updateBGAlpha();
updateMinValue();
updateMaxValue();
updateTextSize();
updateShowCaption();
updateAutoColorChange();
updateMaxColor();
updateMedColor();
updateMaxColorThreshold();
updateMedColorThreshold();
updateClockwiseRotate();
overlay_->updateTextureSize(texture_size_, texture_size_ + caption_offset_);
overlay_->hide();
}
void PieChartDisplay::update(float /* wall_dt */, float /* ros_dt */) {
if (update_required_) {
update_required_ = false;
overlay_->updateTextureSize(texture_size_, texture_size_ + caption_offset_);
overlay_->setPosition(left_, top_);
overlay_->setDimensions(overlay_->getTextureWidth(), overlay_->getTextureHeight());
drawPlot(data_);
}
}
void PieChartDisplay::processMessage(std_msgs::msg::Float32::ConstSharedPtr msg)
{
std::lock_guard lock(mutex_);
if (!overlay_->isVisible()) {
return;
}
if (data_ != msg->data || first_time_) {
first_time_ = false;
data_ = msg->data;
update_required_ = true;
}
}
void PieChartDisplay::drawPlot(double val)
{
QColor fg_color(fg_color_);
if (auto_color_change_) {
double r
= std::min(1.0, fabs((val - min_value_) / (max_value_ - min_value_)));
if (r > 0.6) {
double r2 = (r - 0.6) / 0.4;
fg_color.setRed((max_color_.red() - fg_color_.red()) * r2
+ fg_color_.red());
fg_color.setGreen((max_color_.green() - fg_color_.green()) * r2
+ fg_color_.green());
fg_color.setBlue((max_color_.blue() - fg_color_.blue()) * r2
+ fg_color_.blue());
}
if (max_color_threshold_ != 0) {
if (r > max_color_threshold_) {
fg_color.setRed(max_color_.red());
fg_color.setGreen(max_color_.green());
fg_color.setBlue(max_color_.blue());
}
}
if (med_color_threshold_ != 0) {
if (max_color_threshold_ > r and r > med_color_threshold_ ) {
fg_color.setRed(med_color_.red());
fg_color.setGreen(med_color_.green());
fg_color.setBlue(med_color_.blue());
}
}
}
QColor fg_color2(fg_color);
QColor bg_color(bg_color_);
fg_color.setAlpha(fg_alpha_);
fg_color2.setAlpha(fg_alpha2_);
bg_color.setAlpha(bg_alpha_);
int width = overlay_->getTextureWidth();
int height = overlay_->getTextureHeight();
{
rviz_2d_overlay_plugins::ScopedPixelBuffer buffer = overlay_->getBuffer();
QImage Hud = buffer.getQImage(*overlay_, bg_color);
QPainter painter( &Hud );
painter.setRenderHint(QPainter::Antialiasing, true);
const int outer_line_width = 5;
const int value_line_width = 10;
const int value_indicator_line_width = 2;
const int value_padding = 5;
const int value_aabb_offset
= outer_line_width + value_padding + value_line_width / 2;
painter.setPen(QPen(fg_color, outer_line_width, Qt::SolidLine));
painter.drawEllipse(outer_line_width / 2, outer_line_width / 2,
width - outer_line_width ,
height - outer_line_width - caption_offset_);
painter.setPen(QPen(fg_color2, value_indicator_line_width, Qt::SolidLine));
painter.drawEllipse(value_aabb_offset, value_aabb_offset,
width - value_aabb_offset * 2,
height - value_aabb_offset * 2 - caption_offset_);
const double ratio = (val - min_value_) / (max_value_ - min_value_);
const double rotate_direction = clockwise_rotate_ ? -1.0 : 1.0;
const double ratio_angle = ratio * 360.0 * rotate_direction;
const double start_angle_offset = -90;
painter.setPen(QPen(fg_color, value_line_width, Qt::SolidLine));
painter.drawArc(QRectF(value_aabb_offset, value_aabb_offset,
width - value_aabb_offset * 2,
height - value_aabb_offset * 2 - caption_offset_),
start_angle_offset * 16 ,
ratio_angle * 16);
QFont font = painter.font();
font.setPointSize(text_size_);
font.setBold(true);
painter.setFont(font);
painter.setPen(QPen(fg_color, value_line_width, Qt::SolidLine));
std::ostringstream s;
s << std::fixed << std::setprecision(2) << val;
painter.drawText(0, 0, width, height - caption_offset_,
Qt::AlignCenter | Qt::AlignVCenter,
s.str().c_str());
// caption
if (show_caption_) {
painter.drawText(0, height - caption_offset_, width, caption_offset_,
Qt::AlignCenter | Qt::AlignVCenter,
getName());
}
// done
painter.end();
// Unlock the pixel buffer
}
}
void PieChartDisplay::onEnable()
{
subscribe();
overlay_->show();
first_time_ = true;
}
void PieChartDisplay::onDisable()
{
unsubscribe();
overlay_->hide();
}
void PieChartDisplay::updateSize()
{
std::lock_guard lock(mutex_);
texture_size_ = size_property_->getInt();
update_required_ = true;
}
void PieChartDisplay::updateTop()
{
top_ = top_property_->getInt();
update_required_ = true;
}
void PieChartDisplay::updateLeft()
{
left_ = left_property_->getInt();
update_required_ = true;
}
void PieChartDisplay::updateBGColor()
{
bg_color_ = bg_color_property_->getColor();
update_required_ = true;
}
void PieChartDisplay::updateFGColor()
{
fg_color_ = fg_color_property_->getColor();
update_required_ = true;
}
void PieChartDisplay::updateFGAlpha()
{
fg_alpha_ = fg_alpha_property_->getFloat() * 255.0;
update_required_ = true;
}
void PieChartDisplay::updateFGAlpha2()
{
fg_alpha2_ = fg_alpha2_property_->getFloat() * 255.0;
update_required_ = true;
}
void PieChartDisplay::updateBGAlpha()
{
bg_alpha_ = bg_alpha_property_->getFloat() * 255.0;
update_required_ = true;
}
void PieChartDisplay::updateMinValue()
{
min_value_ = min_value_property_->getFloat();
update_required_ = true;
}
void PieChartDisplay::updateMaxValue()
{
max_value_ = max_value_property_->getFloat();
update_required_ = true;
}
void PieChartDisplay::updateTextSize()
{
std::lock_guard lock(mutex_);
text_size_ = text_size_property_->getInt();
QFont font;
font.setPointSize(text_size_);
caption_offset_ = QFontMetrics(font).height();
update_required_ = true;
}
void PieChartDisplay::updateShowCaption()
{
show_caption_ = show_caption_property_->getBool();
update_required_ = true;
}
void PieChartDisplay::updateAutoColorChange()
{
auto_color_change_ = auto_color_change_property_->getBool();
if (auto_color_change_) {
max_color_property_->show();
med_color_property_->show();
max_color_threshold_property_->show();
med_color_threshold_property_->show();
}
else {
max_color_property_->hide();
med_color_property_->hide();
max_color_threshold_property_->hide();
med_color_threshold_property_->hide();
}
update_required_ = true;
}
void PieChartDisplay::updateMaxColor()
{
max_color_ = max_color_property_->getColor();
update_required_ = true;
}
void PieChartDisplay::updateMedColor()
{
med_color_ = med_color_property_->getColor();
update_required_ = true;
}
void PieChartDisplay::updateMaxColorThreshold()
{
max_color_threshold_ = max_color_threshold_property_->getFloat();
update_required_ = true;
}
void PieChartDisplay::updateMedColorThreshold()
{
med_color_threshold_ = med_color_threshold_property_->getFloat();
update_required_ = true;
}
void PieChartDisplay::updateClockwiseRotate()
{
clockwise_rotate_ = clockwise_rotate_property_->getBool();
update_required_ = true;
}
bool PieChartDisplay::isInRegion(int x, int y)
{
return (top_ < y && top_ + texture_size_ > y &&
left_ < x && left_ + texture_size_ > x);
}
void PieChartDisplay::movePosition(int x, int y)
{
top_ = y;
left_ = x;
}
void PieChartDisplay::setPosition(int x, int y)
{
top_property_->setValue(y);
left_property_->setValue(x);
}
}
#include <pluginlib/class_list_macros.hpp>
PLUGINLIB_EXPORT_CLASS( rviz_2d_overlay_plugins::PieChartDisplay, rviz_common::Display )