diff --git a/crane_robot_skills/include/crane_robot_skills/skill_base.hpp b/crane_robot_skills/include/crane_robot_skills/skill_base.hpp
index fffe99c5f..98cc8ed03 100644
--- a/crane_robot_skills/include/crane_robot_skills/skill_base.hpp
+++ b/crane_robot_skills/include/crane_robot_skills/skill_base.hpp
@@ -149,6 +149,8 @@ class SkillInterface
command_base->latest_msg.skill_name = name;
}
+ virtual ~SkillInterface() { visualizer->clearBuffer(); }
+
const std::string name;
virtual Status run(
diff --git a/crane_world_model_publisher/src/visualization_data_handler.cpp b/crane_world_model_publisher/src/visualization_data_handler.cpp
index c2d841df0..a6d005f90 100644
--- a/crane_world_model_publisher/src/visualization_data_handler.cpp
+++ b/crane_world_model_publisher/src/visualization_data_handler.cpp
@@ -27,24 +27,19 @@ struct SvgRobotBuilder : public SvgPathBuilder
std::string getSvgString() const override
{
- SvgPathDefinitionBuilder path_builder;
- path_builder
+ SvgPathBuilder path_builder;
+ path_builder.definition
.moveTo(robot_position.x() + botRightX(theta), robot_position.y() + botRightY(theta))
.arcTo(
{radius, radius}, 0, true, true,
{robot_position.x() + botLeftX(theta), robot_position.y() + botLeftY(theta)})
.lineTo(robot_position.x() + botRightX(theta), robot_position.y() + botRightY(theta));
- SvgPathBuilder builder = path_builder.build();
- builder.fill(fill_color, fill_opacity)
+ path_builder.fill(fill_color, fill_opacity)
.stroke(stroke_color, stroke_opacity)
.strokeWidth(stroke_width);
- std::ostringstream oss;
- oss << "";
- return oss.str();
+ return path_builder.getSvgString();
}
SvgRobotBuilder & position(Point p, double theta)
diff --git a/crane_world_model_publisher/src/world_model_publisher.cpp b/crane_world_model_publisher/src/world_model_publisher.cpp
index a73bfde8c..3eea8b171 100644
--- a/crane_world_model_publisher/src/world_model_publisher.cpp
+++ b/crane_world_model_publisher/src/world_model_publisher.cpp
@@ -440,48 +440,62 @@ void WorldModelPublisherComponent::publishWorldModel()
pub_world_model->publish(wm);
constexpr int SAMPLING_NUM = 4;
- for (const auto & history : friend_history) {
- if (history.size() > SAMPLING_NUM + 1) {
- for (int index = 0; index < history.size() - SAMPLING_NUM; index += SAMPLING_NUM) {
- Point p1;
- Point p2;
- p1 << history.at(index).x, history.at(index).y;
- p2 << history.at(index + SAMPLING_NUM).x, history.at(index + SAMPLING_NUM).y;
- SvgLineBuilder line_builder;
- line_builder.start(p1)
- .end(p2)
- .stroke("yellow", index / static_cast(history.size()))
- .strokeWidth(30);
- visualizer->add(line_builder.getSvgString());
+ for (const auto & [robot_id, history] : friend_history | ranges::views::enumerate) {
+ if (
+ history.size() > SAMPLING_NUM + 1 &&
+ robot_info[static_cast(our_color)].at(robot_id).detected) {
+ for (int i = 0; i < 10; i++) {
+ SvgPolyLineBuilder polyline_builder;
+ int start = static_cast((history.size() / 10.) * i);
+ int end = static_cast((history.size() / 10.) * (i + 1));
+ for (int index = start; index < end; index += SAMPLING_NUM) {
+ polyline_builder.addPoint(history.at(index).x, history.at(index).y);
+ }
+ if (i != 9) {
+ polyline_builder.addPoint(history.at(end).x, history.at(end).y);
+ }
+ polyline_builder.stroke("yellow", start / static_cast(history.size()))
+ .strokeWidth(15);
+ visualizer->add(polyline_builder.getSvgString());
}
}
}
- for (const auto & history : enemy_history) {
- if (history.size() > SAMPLING_NUM + 1) {
- for (int index = 0; index < history.size() - SAMPLING_NUM; index += SAMPLING_NUM) {
- Point p1;
- Point p2;
- p1 << history.at(index).x, history.at(index).y;
- p2 << history.at(index + SAMPLING_NUM).x, history.at(index + SAMPLING_NUM).y;
- SvgLineBuilder line_builder;
- line_builder.start(p1)
- .end(p2)
- .stroke("blue", index / static_cast(history.size()))
- .strokeWidth(30);
- visualizer->add(line_builder.getSvgString());
+ for (const auto & [robot_id, history] : enemy_history | ranges::views::enumerate) {
+ if (
+ history.size() > SAMPLING_NUM + 1 &&
+ robot_info[static_cast(their_color)].at(robot_id).detected) {
+ for (int i = 0; i < 10; i++) {
+ SvgPolyLineBuilder polyline_builder;
+ int start = static_cast((history.size() / 10.) * i);
+ int end = static_cast((history.size() / 10.) * (i + 1));
+ for (int index = start; index < end; index += SAMPLING_NUM) {
+ polyline_builder.addPoint(history.at(index).x, history.at(index).y);
+ }
+ if (i != 9) {
+ polyline_builder.addPoint(history.at(end).x, history.at(end).y);
+ }
+ polyline_builder.stroke("blue", start / static_cast(history.size()))
+ .strokeWidth(15);
+ visualizer->add(polyline_builder.getSvgString());
}
}
}
if (ball_history.size() > SAMPLING_NUM + 1) {
- for (int index = 0; index < ball_history.size() - SAMPLING_NUM; index += SAMPLING_NUM) {
- SvgLineBuilder line_builder;
- line_builder.start(ball_history.at(index))
- .end(ball_history.at(index + SAMPLING_NUM))
- .stroke("orange", index / static_cast(ball_history.size()))
+ for (int i = 0; i < 10; i++) {
+ SvgPolyLineBuilder polyline_builder;
+ int start = static_cast((ball_history.size() / 10.) * i);
+ int end = static_cast((ball_history.size() / 10.) * (i + 1));
+ for (int index = start; index < end; index += SAMPLING_NUM) {
+ polyline_builder.addPoint(ball_history.at(index));
+ }
+ if (i != 9) {
+ polyline_builder.addPoint(ball_history.at(end));
+ }
+ polyline_builder.stroke("orange", start / static_cast(ball_history.size()))
.strokeWidth(30);
- visualizer->add(line_builder.getSvgString());
+ visualizer->add(polyline_builder.getSvgString());
}
}
visualizer->flush();
diff --git a/session/crane_planner_plugins/include/crane_planner_plugins/planner_base.hpp b/session/crane_planner_plugins/include/crane_planner_plugins/planner_base.hpp
index d3516fe91..f43bb02f3 100644
--- a/session/crane_planner_plugins/include/crane_planner_plugins/planner_base.hpp
+++ b/session/crane_planner_plugins/include/crane_planner_plugins/planner_base.hpp
@@ -54,6 +54,8 @@ class PlannerBase
{
}
+ virtual ~PlannerBase() { visualizer->clearBuffer(); }
+
crane_msgs::srv::RobotSelect::Response doRobotSelect(
const crane_msgs::srv::RobotSelect::Request::SharedPtr request,
const std::unordered_map & prev_roles, PlannerContext & context)
diff --git a/utility/crane_msg_wrappers/include/crane_msg_wrappers/crane_visualizer_wrapper.hpp b/utility/crane_msg_wrappers/include/crane_msg_wrappers/crane_visualizer_wrapper.hpp
index 172069f43..4418426f2 100644
--- a/utility/crane_msg_wrappers/include/crane_msg_wrappers/crane_visualizer_wrapper.hpp
+++ b/utility/crane_msg_wrappers/include/crane_msg_wrappers/crane_visualizer_wrapper.hpp
@@ -8,8 +8,9 @@
#define CRANE_MSG_WRAPPERS__CRANE_VISUALIZER_WRAPPER_HPP_
#include
-#include
+#include
#include
+#include
#include
#include
@@ -311,7 +312,11 @@ struct SvgPolyLineBuilder
for (const auto & p : points) {
oss << p.x() * 1000. << "," << p.y() * 1000. << " ";
}
- oss << "\" stroke=\"" << stroke_color << "\" stroke-width=\"" << stroke_width << "\" />";
+ oss << "\" stroke=\"" << stroke_color << "\" stroke-width=\"" << stroke_width;
+ if (stroke_opacity != 1.) {
+ oss << "\" stroke-opacity=\"" << stroke_opacity;
+ }
+ oss << "\" fill=\"none\" />";
return oss.str();
}
@@ -327,7 +332,7 @@ struct SvgPolyLineBuilder
return *this;
}
- SvgPolyLineBuilder & strokeColor(const std::string & color, double alpha = 1.0)
+ SvgPolyLineBuilder & stroke(const std::string & color, double alpha = 1.0)
{
stroke_color = color;
stroke_opacity = alpha;
@@ -404,8 +409,6 @@ struct SvgPolygonBuilder
struct SvgPathBuilder
{
- std::string path;
-
std::string fill_color = "none";
double fill_opacity = 1.;
@@ -421,17 +424,11 @@ struct SvgPathBuilder
virtual std::string getSvgString() const
{
std::ostringstream oss;
- oss << "";
+ oss << "";
return oss.str();
}
- SvgPathBuilder & pathString(const std::string & path)
- {
- this->path = path;
- return *this;
- }
-
SvgPathBuilder & fill(const std::string & color, double alpha = 1.0)
{
fill_color = color;
@@ -555,29 +552,22 @@ struct SvgPathBuilder
{
return arcTo(r.x(), r.y(), x_axis_rotation, large_arc_flag, sweep_flag, p.x(), p.y());
}
-
- SvgPathBuilder build()
- {
- SvgPathBuilder builder;
- builder.path = path;
- return builder;
- }
- };
+ } definition;
};
struct CraneVisualizerBuffer
{
- using SvgPrimitiveArray = crane_visualization_interfaces::msg::SvgPrimitiveArray;
+ using SvgLayerArray = crane_visualization_interfaces::msg::SvgLayerArray;
static inline std::unique_ptr buffer = nullptr;
- rclcpp::Publisher::SharedPtr publisher;
+ rclcpp::Publisher::SharedPtr publisher;
- SvgPrimitiveArray message_buffer;
+ SvgLayerArray message_buffer;
template
CraneVisualizerBuffer(Node & node, const std::string topic)
{
- publisher = node.template create_publisher(topic, rclcpp::SensorDataQoS());
+ publisher = node.template create_publisher(topic, rclcpp::SensorDataQoS());
}
template
@@ -601,12 +591,29 @@ struct CraneVisualizerBuffer
{
if (active()) {
buffer->publisher->publish(buffer->message_buffer);
- buffer->message_buffer.svg_primitives.clear();
+ buffer->message_buffer.svg_primitive_arrays.clear();
+ }
+ }
+
+ static auto clear(std::string layer = "") -> void
+ {
+ if (CraneVisualizerBuffer::active()) {
+ if (layer == "") {
+ CraneVisualizerBuffer::buffer->message_buffer.svg_primitive_arrays.clear();
+ } else {
+ for (auto & svg_layer : CraneVisualizerBuffer::buffer->message_buffer.svg_primitive_arrays |
+ ranges::views::filter([&](auto svg_primitive_array) {
+ return svg_primitive_array.layer == layer;
+ })) {
+ svg_layer.svg_primitives.clear();
+ }
+ }
}
}
struct MessageBuilder
{
+ using SvgPrimitiveArray = crane_visualization_interfaces::msg::SvgPrimitiveArray;
using SharedPtr = std::shared_ptr;
using UniquePtr = std::unique_ptr;
@@ -617,15 +624,23 @@ struct CraneVisualizerBuffer
void flush()
{
if (CraneVisualizerBuffer::active()) {
- CraneVisualizerBuffer::buffer->message_buffer.layer = layer;
- CraneVisualizerBuffer::buffer->message_buffer.svg_primitives.insert(
- CraneVisualizerBuffer::buffer->message_buffer.svg_primitives.end(),
- message_buffer.begin(), message_buffer.end());
+ SvgPrimitiveArray layer_msg;
+ layer_msg.layer = layer;
+ layer_msg.svg_primitives = message_buffer;
+ CraneVisualizerBuffer::buffer->message_buffer.svg_primitive_arrays.push_back(layer_msg);
message_buffer.clear();
}
}
- using SvgPrimitiveArray = crane_visualization_interfaces::msg::SvgPrimitiveArray;
+ void clear() { message_buffer.clear(); }
+
+ void clearBuffer()
+ {
+ clear();
+ if (CraneVisualizerBuffer::active()) {
+ CraneVisualizerBuffer::clear(layer);
+ }
+ }
std::vector message_buffer;
diff --git a/utility/crane_visualization_aggregator/src/crane_visualization_aggregator_node.cpp b/utility/crane_visualization_aggregator/src/crane_visualization_aggregator_node.cpp
index c79777ecc..81c2ffe25 100644
--- a/utility/crane_visualization_aggregator/src/crane_visualization_aggregator_node.cpp
+++ b/utility/crane_visualization_aggregator/src/crane_visualization_aggregator_node.cpp
@@ -21,11 +21,13 @@ class VisualizationAggregator : public rclcpp::Node
public:
VisualizationAggregator() : Node("visualization_aggregator")
{
- subscriber = create_subscription(
+ subscriber = create_subscription(
"/visualizer_svgs", rclcpp::SensorDataQoS(),
- [&](const crane_visualization_interfaces::msg::SvgPrimitiveArray::ConstSharedPtr & msg) {
+ [&](const crane_visualization_interfaces::msg::SvgLayerArray::ConstSharedPtr & msg) {
// store into layers
- layers[msg->layer] = msg->svg_primitives;
+ for (const auto & layer_msg : msg->svg_primitive_arrays) {
+ layers[layer_msg.layer] = layer_msg.svg_primitives;
+ }
});
publisher =
create_publisher("/aggregated_svgs", 10);
@@ -43,8 +45,7 @@ class VisualizationAggregator : public rclcpp::Node
}
private:
- rclcpp::Subscription::SharedPtr
- subscriber;
+ rclcpp::Subscription::SharedPtr subscriber;
rclcpp::Publisher::SharedPtr publisher;
std::unordered_map> layers;