Program Listing for File mapviz_plugin.h
↰ Return to documentation for file (include/mapviz/mapviz_plugin.h
)
// *****************************************************************************
//
// Copyright (c) 2014, Southwest Research Institute® (SwRI®)
// 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/or other materials provided with the distribution.
// * Neither the name of Southwest Research Institute® (SwRI®) 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 <COPYRIGHT HOLDER> 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.
//
// *****************************************************************************
#ifndef MAPVIZ__MAPVIZ_PLUGIN_H_
#define MAPVIZ__MAPVIZ_PLUGIN_H_
// ROS libraries
#include <swri_transform_util/transform.h>
#include <swri_transform_util/transform_manager.h>
#include <rclcpp/rclcpp.hpp>
#include <tf2/transform_datatypes.h>
#include <tf2_ros/buffer.h>
#include <tf2_ros/transform_listener.h>
#include <mapviz/widgets.h>
#include <yaml-cpp/yaml.h>
// QT libraries
#include <QWidget>
#include <QGLWidget>
#include <QObject>
// C++ standard libraries
#include <memory>
#include <string>
#include "mapviz/stopwatch.h"
namespace mapviz
{
class MapvizPlugin : public QObject
{
Q_OBJECT
public:
~MapvizPlugin() override = default;
virtual bool Initialize(
std::shared_ptr<tf2_ros::Buffer> tf_buffer,
std::shared_ptr<tf2_ros::TransformListener> tf_listener,
swri_transform_util::TransformManagerPtr tf_manager,
QGLWidget* canvas)
{
tf_buf_ = tf_buffer;
tf_ = tf_listener;
tf_manager_ = tf_manager;
return Initialize(canvas);
}
virtual void Shutdown() = 0;
virtual void ClearHistory() {}
virtual void Draw(double x, double y, double scale) = 0;
virtual void Paint(QPainter* /* painter */, double /* x */,
double /* y */, double /* scale */) {}
void SetUseLatestTransforms(bool value)
{
if (value != use_latest_transforms_) {
use_latest_transforms_ = value;
Q_EMIT UseLatestTransformsChanged(use_latest_transforms_);
}
}
void SetName(const std::string& name) { name_ = name; }
std::string Name() const { return name_; }
void SetType(const std::string& type) { type_ = type; }
std::string Type() const { return type_; }
int DrawOrder() const { return draw_order_; }
void SetDrawOrder(int order)
{
if (draw_order_ != order) {
draw_order_ = order;
Q_EMIT DrawOrderChanged(draw_order_);
}
}
virtual void SetNode(rclcpp::Node& node)
{
// node_ = node;
node_ = node.shared_from_this();
}
void DrawPlugin(double x, double y, double scale)
{
if (visible_ && initialized_) {
meas_transform_.start();
Transform();
meas_transform_.stop();
meas_draw_.start();
Draw(x, y, scale);
meas_draw_.stop();
}
}
void PaintPlugin(QPainter* painter, double x, double y, double scale)
{
if (visible_ && initialized_) {
meas_transform_.start();
Transform();
meas_transform_.stop();
meas_paint_.start();
Paint(painter, x, y, scale);
meas_paint_.start();
}
}
void SetTargetFrame(const std::string& frame_id)
{
if (frame_id != target_frame_) {
target_frame_ = frame_id;
meas_transform_.start();
Transform();
meas_transform_.stop();
Q_EMIT TargetFrameChanged(target_frame_);
}
}
bool Visible() const { return visible_; }
void SetVisible(bool visible)
{
if (visible_ != visible) {
visible_ = visible;
Q_EMIT VisibleChanged(visible_);
}
}
bool GetTransform(
const rclcpp::Time& stamp,
swri_transform_util::Transform& transform,
bool use_latest_transforms = true)
{
return GetTransform(source_frame_, stamp, transform, use_latest_transforms);
}
bool GetTransform(const std::string& source,
const rclcpp::Time& stamp,
swri_transform_util::Transform& transform,
bool use_latest_transforms = true)
{
if (!initialized_) {
return false;
}
tf2::TimePoint time;
rclcpp::Time now = node_->now();
if (use_latest_transforms_ && use_latest_transforms) {
time = tf2::TimePointZero;
}
else
{
time = tf2::timeFromSec(stamp.seconds());
}
if (tf_manager_->GetTransform(
target_frame_,
source,
time,
transform))
{
return true;
} else if (time != tf2::TimePointZero) {
rclcpp::Duration elapsed = now - stamp;
if (elapsed.seconds() < 0.1)
{
// If the stamped transform failed because it is too recent, find the
// most recent transform in the cache instead.
if (tf_manager_->GetTransform(
target_frame_,
source,
tf2::TimePointZero,
transform))
{
return true;
}
}
}
return false;
}
virtual void Transform() = 0;
virtual void LoadConfig(const YAML::Node& load, const std::string& path) = 0;
virtual void SaveConfig(YAML::Emitter& emitter, const std::string& path) = 0;
virtual QWidget* GetConfigWidget(QWidget* /* parent */) { return nullptr; }
virtual void PrintError(const std::string& message) = 0;
virtual void PrintInfo(const std::string& message) = 0;
virtual void PrintWarning(const std::string& message) = 0;
void SetIcon(IconWidget* icon) { icon_ = icon; }
void PrintMeasurements()
{
std::string header = type_ + " (" + name_ + ")";
meas_transform_.printInfo(node_->get_logger(), header + " Transform()");
meas_paint_.printInfo(node_->get_logger(), header + " Paint()");
meas_draw_.printInfo(node_->get_logger(), header + " Draw()");
}
void PrintErrorHelper(
QLabel *status_label,
const std::string& message,
double throttle = 0.0);
void PrintInfoHelper(
QLabel *status_label,
const std::string& message,
double throttle = 0.0);
void PrintWarningHelper(
QLabel *status_label,
const std::string& message,
double throttle = 0.0);
public Q_SLOTS:
virtual void DrawIcon() {}
virtual bool SupportsPainting()
{
return false;
}
Q_SIGNALS:
void DrawOrderChanged(int draw_order);
void SizeChanged();
void TargetFrameChanged(const std::string& target_frame);
void UseLatestTransformsChanged(bool use_latest_transforms);
void VisibleChanged(bool visible);
protected:
bool initialized_;
bool visible_;
QGLWidget* canvas_;
IconWidget* icon_;
std::shared_ptr<rclcpp::Node> node_;
std::shared_ptr<tf2_ros::Buffer> tf_buf_;
std::shared_ptr<tf2_ros::TransformListener> tf_;
swri_transform_util::TransformManagerPtr tf_manager_;
std::string target_frame_;
std::string source_frame_;
std::string type_;
std::string name_;
bool use_latest_transforms_;
int draw_order_;
virtual bool Initialize(QGLWidget* canvas) = 0;
MapvizPlugin() :
initialized_(false),
visible_(true),
canvas_(nullptr),
icon_(nullptr),
node_(nullptr),
tf_(),
target_frame_(""),
source_frame_(""),
use_latest_transforms_(false),
draw_order_(0)
{}
void LoadQosConfig(const YAML::Node& node, rmw_qos_profile_t& qos, const std::string prefix = "") const
{
if (node[prefix + "qos_depth"])
{
qos.depth = node[prefix + "qos_depth"].as<int>();
}
if (node[prefix + "qos_history"])
{
qos.history = static_cast<rmw_qos_history_policy_e>(node[prefix + "qos_history"].as<int>());
}
if (node[prefix + "qos_reliability"])
{
qos.reliability = static_cast<rmw_qos_reliability_policy_e>(node[prefix + "qos_reliability"].as<int>());
}
if (node[prefix + "qos_durability"])
{
qos.durability = static_cast<rmw_qos_durability_policy_e>(node[prefix + "qos_durability"].as<int>());
}
}
void SaveQosConfig(YAML::Emitter& emitter, const rmw_qos_profile_t& qos, const std::string prefix = "") const
{
emitter << YAML::Key << prefix + "qos_depth" << YAML::Value << qos.depth;
emitter << YAML::Key << prefix + "qos_history" << YAML::Value << qos.history;
emitter << YAML::Key << prefix + "qos_reliability" << YAML::Value << qos.reliability;
emitter << YAML::Key << prefix + "qos_durability" << YAML::Value << qos.durability;
}
private:
// Collect basic profiling info to know how much time each plugin
// spends in Transform(), Paint(), and Draw().
Stopwatch meas_transform_;
Stopwatch meas_paint_;
Stopwatch meas_draw_;
};
typedef std::shared_ptr<MapvizPlugin> MapvizPluginPtr;
// Implementation
inline void MapvizPlugin::PrintErrorHelper(QLabel *status_label, const std::string &message,
double throttle)
{
if (message == status_label->text().toStdString()) {
return;
}
auto logger = node_ ? node_->get_logger() : rclcpp::get_logger("mapviz");
if (throttle > 0.0) {
RCLCPP_ERROR(logger, "Error: %s", message.c_str());
} else {
RCLCPP_ERROR(logger, "%s", message.c_str());
}
QPalette p(status_label->palette());
p.setColor(QPalette::Text, Qt::red);
status_label->setPalette(p);
status_label->setText(message.c_str());
}
inline void MapvizPlugin::PrintInfoHelper(QLabel *status_label, const std::string &message,
double throttle)
{
if (message == status_label->text().toStdString()) {
return;
}
auto logger = node_ ? node_->get_logger() : rclcpp::get_logger("mapviz");
if (throttle > 0.0) {
RCLCPP_INFO(logger, "%s", message.c_str());
} else {
RCLCPP_INFO(logger, "%s", message.c_str());
}
QPalette p(status_label->palette());
p.setColor(QPalette::Text, Qt::darkGreen);
status_label->setPalette(p);
status_label->setText(message.c_str());
}
inline void MapvizPlugin::PrintWarningHelper(QLabel *status_label, const std::string &message,
double throttle)
{
if (message == status_label->text().toStdString()) {
return;
}
auto logger = node_ ? node_->get_logger() : rclcpp::get_logger("mapviz");
if (throttle > 0.0) {
RCLCPP_WARN(logger, "%s", message.c_str());
} else {
RCLCPP_WARN(logger, "%s", message.c_str());
}
QPalette p(status_label->palette());
p.setColor(QPalette::Text, Qt::darkYellow);
status_label->setPalette(p);
status_label->setText(message.c_str());
}
} // namespace mapviz
#endif // MAPVIZ__MAPVIZ_PLUGIN_H_