pal_statistics.cpp
Go to the documentation of this file.
1 /*
2  @file
3 
4  @author victor
5 
6  @copyright (c) 2018 PAL Robotics SL. All Rights Reserved
7 */
8 
11 namespace pal_statistics
12 {
13 
14 StatisticsRegistry::StatisticsRegistry(const std::string &topic)
15 {
16  pub_ = nh_.advertise<pal_statistics_msgs::Statistics>(topic + "/full", 10000);
17  pub_names_ = nh_.advertise<pal_statistics_msgs::StatisticsNames>(topic + "/names", 10000, true);
18  pub_values_ = nh_.advertise<pal_statistics_msgs::StatisticsValues>(topic + "/values", 10000);
22  interrupt_thread_ = false;
23  is_data_ready_ = false;
24 
25  customRegister(*this, "topic_stats." + topic + ".publish_async_attempts", &publish_async_attempts_, &internal_stats_raii_);
26  customRegister(*this, "topic_stats." + topic + ".publish_async_failures", &publish_async_failures_, &internal_stats_raii_);
27  customRegister(*this, "topic_stats." + topic + ".publish_buffer_full_errors", &registration_list_.overwritten_data_count_, &internal_stats_raii_);
28  customRegister(*this, "topic_stats." + topic + ".last_async_pub_duration", &last_async_pub_duration_, &internal_stats_raii_);
29 }
30 
32 {
33  is_data_ready_ = true; //To let the thread exit nicely
34 
36  {
37  interrupt_thread_ = true;
38  publisher_thread_->join();
39  }
41  ROS_INFO_STREAM("publish_async_failures_ " << publish_async_failures_);
42 }
43 
45  const boost::function<double()> &funct,
46  RegistrationsRAII *bookkeeping, bool enabled)
47 {
48  return registerInternal(name, VariableHolder(funct), bookkeeping, enabled);
49 }
50 
52 {
53  if (bookkeeping)
54  {
55  bookkeeping->remove(id);
56  }
57 
58  boost::unique_lock<boost::mutex> data_lock(data_mutex_);
60 }
61 
62 void StatisticsRegistry::unregisterVariable(const std::string &name, RegistrationsRAII *bookkeeping)
63 {
64  if (bookkeeping)
65  {
66  bookkeeping->remove(name);
67  }
68 
69  boost::unique_lock<boost::mutex> data_lock(data_mutex_);
71 }
72 
73 
75 {
76  boost::unique_lock<boost::mutex> data_lock(data_mutex_);
77  handlePendingDisables(data_lock);
79 
80  boost::unique_lock<boost::mutex> pub_lock(pub_mutex_);
81  bool minor_changes = updateMsg(names_msg_, values_msg_, true);
82  data_lock.unlock(); //msg_ is covered by pub_mutex_
83  doPublish(!minor_changes);
84 }
85 
87 {
88  double begin = ros::SteadyTime::now().toSec();
90  if (data_mutex_.try_lock())
91  {
92  if (!publisher_thread_.get())
93  {
94  ROS_WARN_STREAM_ONCE("Called publishAsync but publisher thread has not been started, THIS IS NOT RT safe. You should start it yourself.");
96  }
97 
98  {
99  boost::unique_lock<boost::mutex> data_lock(data_mutex_, boost::adopt_lock);
100  handlePendingDisables(data_lock);
101 
103  }
104  is_data_ready_ = true;
105 
107  return true;
108  }
110  // Commented for RT safety
111  // ROS_DEBUG("Missed publishRT opportunity because lock could not be acquired.");
112  return false;
113 }
114 
116 {
117  boost::unique_lock<boost::mutex> data_lock(data_mutex_);
119 }
121 {
122  publisher_thread_.reset(new boost::thread(&StatisticsRegistry::publisherThreadCycle, this));
123 }
124 
125 IdType StatisticsRegistry::registerInternal(const std::string &name, VariableHolder &&variable,
126  RegistrationsRAII *bookkeeping, bool enabled)
127 {
128  IdType id;
129  {
130  boost::unique_lock<boost::mutex> data_lock(data_mutex_);
131  id = registration_list_.registerVariable(name, std::move(variable), enabled);
132  enabled_ids_.set_capacity(registration_list_.size());
133  }
134 
135  if (bookkeeping)
136  bookkeeping->add(Registration(name, id, weak_from_this()));
137  return id;
138 }
139 
140 bool StatisticsRegistry::setEnabledmpl(const IdType &id, bool enabled)
141 {
142  EnabledId aux;
143  aux.enabled = enabled;
144  aux.id = id;
145 
146  return enabled_ids_.bounded_push(aux);
147 }
148 
149 void StatisticsRegistry::handlePendingDisables(const boost::unique_lock<boost::mutex> &data_lock)
150 {
151  if (!data_lock.owns_lock() || data_lock.mutex() != &data_mutex_)
152  {
153  throw ros::Exception("Called handlePendingDisables without proper lock");
154  }
155 
156  EnabledId elem;
157  while (enabled_ids_.pop(elem))
158  {
160  }
161 }
162 
163 void StatisticsRegistry::doPublish(bool publish_names_msg)
164 {
165  if (pub_.getNumSubscribers() > 0)
166  {
169  }
170 
171  // We don't check subscribers here, because this topic is latched and we
172  // always want the latest version published
173  if (publish_names_msg) //only publish strings if changed
174  {
176  }
177  if (pub_values_.getNumSubscribers() > 0 ) //only publish strings if changed
178  {
180  }
181 }
182 
183 pal_statistics_msgs::Statistics StatisticsRegistry::createMsg()
184 {
185  boost::unique_lock<boost::mutex> data_lock(data_mutex_);
186  handlePendingDisables(data_lock);
188  GeneratedStatistics gen_sts;
189  pal_statistics_msgs::StatisticsNames names;
190  pal_statistics_msgs::StatisticsValues values;
191 
192  updateMsg(names, values, false);
193  gen_sts.update(names, values);
194  return gen_sts.msg_;
195 }
196 
198 {
199  return setEnabledmpl(id, true);
200 }
201 
203 {
204  return setEnabledmpl(id, false);
205 }
206 
207 bool StatisticsRegistry::updateMsg(pal_statistics_msgs::StatisticsNames &names,
208  pal_statistics_msgs::StatisticsValues &values,
209  bool smart_fill)
210 {
211  if (smart_fill)
212  return registration_list_.smartFillMsg(names, values);
213  else
214  {
215  registration_list_.fillMsg(names, values);
216  return false;
217  }
218 }
219 
221 {
222  //wait until the variable is set
223  while (!publisher_thread_.get())
224  ros::WallDuration(5e-4).sleep();
225 
226 
227  while (ros::ok() && !interrupt_thread_)
228  {
229  while (!is_data_ready_ && !interrupt_thread_)
230  ros::WallDuration(5e-4).sleep();
231 
232  boost::unique_lock<boost::mutex> data_lock(data_mutex_);
233 
235  {
236  bool minor_changes = updateMsg(names_msg_, values_msg_, true);
237 
238  boost::unique_lock<boost::mutex> pub_lock(pub_mutex_);
239  data_lock.unlock();
240  doPublish(!minor_changes);
241  pub_lock.unlock();
242  data_lock.lock();
243  }
244  is_data_ready_ = false;
245  }
246 }
247 
249  const pal_statistics_msgs::StatisticsNames &names,
250  const pal_statistics_msgs::StatisticsValues &values)
251 {
252  msg_.header = values.header;
253  if (last_names_version_ == names.names_version && !msg_.statistics.empty())
254  {
255  // only need to update the values
256  for (size_t i = 0; i < values.values.size(); ++i)
257  {
258  msg_.statistics[i].value = values.values[i];
259  }
260  }
261  else
262  {
263  msg_.statistics.clear();
264  for (size_t i = 0; i < names.names.size(); ++i)
265  {
266  pal_statistics_msgs::Statistic s;
267  s.name = names.names[i];
268  s.value = values.values[i];
269  msg_.statistics.push_back(s);
270  }
271  last_names_version_ = names.names_version;
272  }
273 }
274 }
pal_statistics::StatisticsRegistry::internal_stats_raii_
RegistrationsRAII internal_stats_raii_
Definition: pal_statistics.h:238
pal_statistics::StatisticsRegistry::enable
bool enable(const IdType &id)
Definition: pal_statistics.cpp:197
pal_statistics::StatisticsRegistry::startPublishThreadImpl
void startPublishThreadImpl()
Definition: pal_statistics.cpp:120
pal_statistics::StatisticsRegistry::EnabledId::id
IdType id
Definition: pal_statistics.h:191
ros::WallDuration::sleep
bool sleep() const
pal_statistics::StatisticsRegistry::publish
void publish()
publish Reads the values of all registered variables and publishes them to the topic associated to th...
Definition: pal_statistics.cpp:74
pal_statistics::StatisticsRegistry::disable
bool disable(const IdType &id)
Definition: pal_statistics.cpp:202
pal_statistics::RegistrationList::setEnabled
void setEnabled(const IdType &id, bool enabled)
Definition: pal_statistics_utils.cpp:51
pal_statistics::customRegister
IdType customRegister(StatisticsRegistry &registry, const std::string &name, const T *variable, RegistrationsRAII *bookkeeping=NULL, bool enabled=true)
Default implementation that accepts anything variable that can be casted to a double.
Definition: registration_utils.h:38
pal_statistics::StatisticsRegistry::EnabledId::enabled
bool enabled
Definition: pal_statistics.h:192
pal_statistics::StatisticsRegistry::publishAsync
bool publishAsync()
publishAsync Capture data and flag it to be published by the publisher thread. Real-Time safe.
Definition: pal_statistics.cpp:86
pal_statistics::StatisticsRegistry::doPublish
void doPublish(bool publish_names_msg=true)
doPublish publishes the subscribed topics, requires mutex
Definition: pal_statistics.cpp:163
pal_statistics::RegistrationsRAII::remove
bool remove(const std::string &name)
Definition: pal_statistics_utils.cpp:278
pal_statistics::RegistrationList::doUpdate
void doUpdate()
Definition: pal_statistics_utils.cpp:88
pal_statistics::StatisticsRegistry::StatisticsRegistry
StatisticsRegistry(const std::string &topic)
Definition: pal_statistics.cpp:14
s
XmlRpcServer s
pal_statistics::StatisticsRegistry::pub_mutex_
boost::mutex pub_mutex_
Definition: pal_statistics.h:209
pal_statistics::StatisticsRegistry::setEnabledmpl
bool setEnabledmpl(const IdType &id, bool enabled)
Definition: pal_statistics.cpp:140
registration_utils.h
pal_statistics::RegistrationList::unregisterVariable
void unregisterVariable(const IdType &id)
Definition: pal_statistics_utils.cpp:39
pal_statistics::StatisticsRegistry::startPublishThread
void startPublishThread()
startPublishThread creates and starts the publisherThread. The user still has to call publishAsync ea...
Definition: pal_statistics.cpp:115
TimeBase< SteadyTime, WallDuration >::toSec
double toSec() const
pal_statistics::StatisticsRegistry::publish_async_failures_
unsigned int publish_async_failures_
Definition: pal_statistics.h:236
pal_statistics::StatisticsRegistry::unregisterVariable
void unregisterVariable(const std::string &name, RegistrationsRAII *bookkeeping=NULL)
Definition: pal_statistics.cpp:62
pal_statistics::StatisticsRegistry::GeneratedStatistics::msg_
pal_statistics_msgs::Statistics msg_
This message is generated using an updated StatiticsNames and StatisticsValues.
Definition: pal_statistics.h:227
ros::Exception
pal_statistics::StatisticsRegistry::pub_values_
ros::Publisher pub_values_
Definition: pal_statistics.h:212
pal_statistics::StatisticsRegistry::last_async_pub_duration_
double last_async_pub_duration_
Definition: pal_statistics.h:237
ros::Publisher::publish
void publish(const boost::shared_ptr< M > &message) const
ros::NodeHandle::advertise
Publisher advertise(AdvertiseOptions &ops)
ros::ok
ROSCPP_DECL bool ok()
ROS_WARN_STREAM_ONCE
#define ROS_WARN_STREAM_ONCE(args)
pal_statistics::StatisticsRegistry::GeneratedStatistics
Definition: pal_statistics.h:218
pal_statistics::StatisticsRegistry::generated_statistics_
GeneratedStatistics generated_statistics_
Definition: pal_statistics.h:233
pal_statistics::RegistrationsRAII::add
void add(Registration &&registration)
Definition: pal_statistics_utils.cpp:272
ros::SteadyTime::now
static SteadyTime now()
pal_statistics::StatisticsRegistry::nh_
ros::NodeHandle nh_
Definition: pal_statistics.h:183
pal_statistics::Registration
The Registration class is a handle to a registered variable, when out of scope unregisters the variab...
Definition: pal_statistics_utils.h:94
pal_statistics::StatisticsRegistry::createMsg
pal_statistics_msgs::Statistics createMsg()
createMsg creates a Statistics message from the registered variables, useful for debugging
Definition: pal_statistics.cpp:183
pal_statistics::RegistrationList::overwritten_data_count_
unsigned int overwritten_data_count_
Definition: pal_statistics_utils.h:241
pal_statistics.h
pal_statistics
Definition: extract_rosbag_signals.h:14
pal_statistics::StatisticsRegistry::is_data_ready_
std::atomic< bool > is_data_ready_
Definition: pal_statistics.h:214
pal_statistics::StatisticsRegistry::names_msg_
pal_statistics_msgs::StatisticsNames names_msg_
Definition: pal_statistics.h:231
pal_statistics::StatisticsRegistry::GeneratedStatistics::last_names_version_
unsigned int last_names_version_
Definition: pal_statistics.h:228
pal_statistics::StatisticsRegistry::~StatisticsRegistry
virtual ~StatisticsRegistry()
Definition: pal_statistics.cpp:31
pal_statistics::StatisticsRegistry::updateMsg
bool updateMsg(pal_statistics_msgs::StatisticsNames &names, pal_statistics_msgs::StatisticsValues &values, bool smart_fill=false)
updateMsg update names and values, optionally using smartfill to minimize copying
Definition: pal_statistics.cpp:207
pal_statistics::StatisticsRegistry::publisherThreadCycle
void publisherThreadCycle()
Definition: pal_statistics.cpp:220
ROS_INFO_STREAM
#define ROS_INFO_STREAM(args)
pal_statistics::StatisticsRegistry::GeneratedStatistics::update
void update(const pal_statistics_msgs::StatisticsNames &names, const pal_statistics_msgs::StatisticsValues &values)
Definition: pal_statistics.cpp:248
pal_statistics::StatisticsRegistry::values_msg_
pal_statistics_msgs::StatisticsValues values_msg_
Definition: pal_statistics.h:232
pal_statistics::StatisticsRegistry::EnabledId
Definition: pal_statistics.h:188
pal_statistics::RegistrationList::smartFillMsg
bool smartFillMsg(pal_statistics_msgs::StatisticsNames &names, pal_statistics_msgs::StatisticsValues &values)
smartFillMsg Attempts to minimize the amount of string copies
Definition: pal_statistics_utils.cpp:155
pal_statistics::StatisticsRegistry::handlePendingDisables
void handlePendingDisables(const boost::unique_lock< boost::mutex > &data_lock)
handlePendingDisables Empties by handling the queue of disabled/enabled ids.
Definition: pal_statistics.cpp:149
pal_statistics::StatisticsRegistry::registerFunction
IdType registerFunction(const std::string &name, const boost::function< double()> &funct, RegistrationsRAII *bookkeeping=NULL, bool enabled=true)
registerFunction Adds a function that returns double with the specified name
Definition: pal_statistics.cpp:44
pal_statistics::StatisticsRegistry::pub_names_
ros::Publisher pub_names_
Definition: pal_statistics.h:211
pal_statistics::RegistrationList::fillMsg
void fillMsg(pal_statistics_msgs::StatisticsNames &names, pal_statistics_msgs::StatisticsValues &value)
fills message with the last captured values.
Definition: pal_statistics_utils.cpp:132
pal_statistics::StatisticsRegistry::publish_async_attempts_
unsigned int publish_async_attempts_
Definition: pal_statistics.h:235
pal_statistics::StatisticsRegistry::enabled_ids_
LockFreeQueue< EnabledId > enabled_ids_
disabled_ids_ this is used to keep track of enabled/disabled variables in a lock free way
Definition: pal_statistics.h:205
pal_statistics::RegistrationList::registerVariable
int registerVariable(const std::string &name, VariableHolder &&holder, bool enabled=true)
Definition: pal_statistics_utils.cpp:219
pal_statistics::StatisticsRegistry::interrupt_thread_
std::atomic< bool > interrupt_thread_
Definition: pal_statistics.h:215
pal_statistics::RegistrationList::hasPendingData
bool hasPendingData() const
Definition: pal_statistics_utils.cpp:186
pal_statistics::StatisticsRegistry::publisher_thread_
boost::shared_ptr< boost::thread > publisher_thread_
Definition: pal_statistics.h:216
ros::Publisher::getNumSubscribers
uint32_t getNumSubscribers() const
ros::WallDuration
pal_statistics::StatisticsRegistry::pub_
ros::Publisher pub_
Definition: pal_statistics.h:210
pal_statistics::StatisticsRegistry::registerInternal
IdType registerInternal(const std::string &name, VariableHolder &&variable, RegistrationsRAII *bookkeeping, bool enabled)
Definition: pal_statistics.cpp:125
pal_statistics::RegistrationList::size
size_t size() const
Definition: pal_statistics_utils.cpp:181
pal_statistics::VariableHolder
Definition: pal_statistics_utils.h:147
pal_statistics::RegistrationsRAII
The RegistrationsRAII class holds handles to registered variables and when it is destroyed,...
Definition: pal_statistics_utils.h:117
pal_statistics::StatisticsRegistry::registration_list_
RegistrationList registration_list_
Definition: pal_statistics.h:186
pal_statistics::IdType
unsigned int IdType
Definition: pal_statistics_utils.h:46
pal_statistics::StatisticsRegistry::data_mutex_
boost::mutex data_mutex_
Definition: pal_statistics.h:185


pal_statistics
Author(s):
autogenerated on Fri Aug 2 2024 08:29:35