10 #include <QDialogButtonBox> 11 #include <QScrollArea> 12 #include <QPushButton> 14 #include <QRadioButton> 15 #include <unordered_map> 16 #include <QMessageBox> 17 #include <tf2_ros/qos.hpp> 18 #include <rosbag2_cpp/types.hpp> 20 #include <rmw/types.h> 25 _context = std::make_shared<rclcpp::Context>();
28 auto exec_args = rclcpp::executor::ExecutorArgs();
30 _executor = std::make_unique<rclcpp::executors::MultiThreadedExecutor>(exec_args, 2);
33 connect(_select_topics_to_publish, &QAction::triggered,
86 if (!
_node && to_enable)
88 auto node_opts = rclcpp::NodeOptions();
90 _node = std::make_shared<rclcpp::Node>(
"plotjuggler", node_opts);
103 const auto any_metadata = metadata_it->second[0].y;
104 _topics_info = std::any_cast<std::vector<TopicInfo>>(any_metadata);
116 _tf_broadcaster = std::make_unique<tf2_ros::TransformBroadcaster>(*_node);
140 const auto any_metadata = metadata_it->second[0].y;
141 _topics_info = std::any_cast<std::vector<TopicInfo>>(any_metadata);
145 dialog->setAttribute(Qt::WA_DeleteOnClose);
146 dialog->ui()->radioButtonClock->setHidden(
true);
147 dialog->ui()->radioButtonHeaderStamp->setHidden(
true);
149 std::map<std::string, QCheckBox*> checkbox;
153 const std::string topic_name = info.name;
154 auto cb =
new QCheckBox(dialog);
158 cb->setChecked(
true);
162 cb->setChecked(filter_it->second);
164 cb->setFocusPolicy(Qt::NoFocus);
165 dialog->ui()->formLayout->addRow(
new QLabel(QString::fromStdString(topic_name)), cb);
166 checkbox.insert(std::make_pair(topic_name, cb));
167 connect(dialog->ui()->pushButtonSelect, &QPushButton::pressed, [cb]() { cb->setChecked(
true); });
168 connect(dialog->ui()->pushButtonDeselect, &QPushButton::pressed, [cb]() { cb->setChecked(
false); });
173 if (dialog->result() == QDialog::Accepted)
176 for (
const auto&
it : checkbox)
187 rcutils_time_point_value_t
Convert(
const builtin_interfaces::msg::Time& stamp)
192 builtin_interfaces::msg::Time
Convert(
const rcutils_time_point_value_t& time_stamp)
194 builtin_interfaces::msg::Time stamp;
195 stamp.sec =
static_cast<int32_t
>(time_stamp /
NSEC_PER_SEC);
196 stamp.nanosec =
static_cast<int32_t
>(time_stamp - (
NSEC_PER_SEC * stamp.sec));
202 using StringPair = std::pair<std::string, std::string>;
204 std::map<StringPair, geometry_msgs::msg::TransformStamped> transforms;
205 std::map<StringPair, geometry_msgs::msg::TransformStamped> static_transforms;
209 const std::string& topic_name = data_it.first;
212 if (topic_name !=
"/tf_static" && topic_name !=
"/tf")
224 auto transforms_ptr = (topic_name ==
"/tf_static") ? & static_transforms : &transforms;
226 std::vector<uint8_t> raw_buffer;
228 int initial_index = tf_data->
getIndexFromX(current_time - 2.0);
230 if (_previous_play_index < last_index && _previous_play_index > initial_index)
235 for (
size_t index = std::max(0, initial_index);
index <= last_index;
index++)
237 const std::any& any_value = tf_data->
at(
index).y;
239 const bool isRosbagMessage = (any_value.type() ==
typeid(
MessageRefPtr));
241 if (!isRosbagMessage)
246 const auto& msg_instance = std::any_cast<
MessageRefPtr>(any_value);
248 auto tf_type_support = rosidl_typesupport_cpp::get_message_type_support_handle<tf2_msgs::msg::TFMessage>();
249 tf2_msgs::msg::TFMessage tf_msg;
250 if ( RMW_RET_OK != rmw_deserialize(msg_instance->serialized_data.get(), tf_type_support, &tf_msg) )
252 throw std::runtime_error(
"failed to deserialize TF message");
255 for (
const auto& stamped_transform : tf_msg.transforms)
257 const auto& parent_id = stamped_transform.header.frame_id;
258 const auto& child_id = stamped_transform.child_frame_id;
259 StringPair trans_id = std::make_pair(parent_id, child_id);
260 auto it = transforms_ptr->find(trans_id);
261 if (
it == transforms_ptr->end())
263 transforms_ptr->insert({ trans_id, stamped_transform });
265 else if (
Convert(
it->second.header.stamp) <=
266 Convert(stamped_transform.header.stamp))
268 it->second = stamped_transform;
274 std::vector<geometry_msgs::msg::TransformStamped> transforms_vector;
275 transforms_vector.reserve(transforms_ptr->size());
277 rcutils_time_point_value_t time_stamp;
278 int error = rcutils_system_time_now(&time_stamp);
280 if (error != RCUTILS_RET_OK)
282 qDebug() <<
"Error getting current time. Error:" << rcutils_get_error_string().str;
285 for (
auto& trans : *transforms_ptr)
287 trans.second.header.stamp =
Convert( time_stamp );
288 transforms_vector.emplace_back(std::move(trans.second));
290 if( transforms_ptr == &transforms ){
321 const std::string& topic_name = data_it.first;
324 if (topic_name ==
"/tf" || topic_name ==
"tf_static")
341 const auto& any_value = plot_any.
at(last_index).y;
345 const auto& msg_instance = std::any_cast<
MessageRefPtr>(any_value);
346 publisher_it->second->publish(msg_instance->serialized_data);
363 int current_index = continuous_msgs.
getIndexFromX(current_time);
376 const auto& any_value = consecutive_msg.
at(
index).y;
379 const auto& msg_instance = std::any_cast<
MessageRefPtr>(any_value);
381 auto publisher_it =
_publishers.find(msg_instance->topic_name);
387 publisher_it->second->publish(msg_instance->serialized_data);
const PlotDataMapRef * _datamap
void updateState(double current_time) override
std::unordered_map< std::string, std::shared_ptr< GenericPublisher > > _publishers
std::pair< std::string, std::string > StringPair
void play(double interval) override
std::unordered_map< std::string, bool > _topics_to_publish
std::shared_ptr< tf2_ros::TransformBroadcaster > _tf_broadcaster
int getIndexFromX(double x) const
std::shared_ptr< rosbag2_storage::SerializedBagMessage > MessageRefPtr
std::unique_ptr< rclcpp::executors::MultiThreadedExecutor > _executor
void setEnabled(bool enabled) override
std::shared_ptr< tf2_ros::StaticTransformBroadcaster > _tf_static_broadcaster
virtual ~TopicPublisherROS2() override
std::vector< TopicInfo > _topics_info
constexpr long NSEC_PER_SEC
std::shared_ptr< rclcpp::Context > _context
const std::vector< QAction * > & availableActions() override
const Point & at(size_t index) const
void broadcastTF(double current_time)
QAction * _select_topics_to_publish
AnySeriesMap user_defined
rcutils_time_point_value_t Convert(const builtin_interfaces::msg::Time &stamp)
std::vector< QAction * > _available_actions
static std::shared_ptr< GenericPublisher > create(rclcpp::Node &node, const std::string &topic_name, const std::string &topic_type)
std::shared_ptr< rclcpp::Node > _node