bt_file_logger_v2.cpp
Go to the documentation of this file.
3 #include "flatbuffers/base.h"
4 
5 namespace BT
6 {
7 
8 int64_t ToUsec(Duration ts)
9 {
10  return std::chrono::duration_cast<std::chrono::microseconds>(ts).count();
11 }
12 
14 {
15  std::ofstream file_stream;
16 
18 
19  std::deque<Transition> transitions_queue;
20  std::condition_variable queue_cv;
22 
23  std::thread writer_thread;
24  std::atomic_bool loop = true;
25 };
26 
27 FileLogger2::FileLogger2(const BT::Tree& tree, std::filesystem::path const& filepath)
28  : StatusChangeLogger(tree.rootNode()), _p(new PImpl)
29 {
30  if(filepath.filename().extension() != ".btlog")
31  {
32  throw RuntimeError("FileLogger2: the file extension must be [.btlog]");
33  }
34 
36 
37  //-------------------------------------
38  _p->file_stream.open(filepath, std::ofstream::binary | std::ofstream::out);
39 
40  if(!_p->file_stream.is_open())
41  {
42  throw RuntimeError("problem opening file in FileLogger2");
43  }
44 
45  _p->file_stream << "BTCPP4-FileLogger2";
46 
47  const uint8_t protocol = 1;
48 
49  _p->file_stream << protocol;
50 
51  std::string const xml = WriteTreeToXML(tree, true, true);
52 
53  // serialize the length of the buffer in the first 4 bytes
54  char write_buffer[8];
55  flatbuffers::WriteScalar(write_buffer, static_cast<int32_t>(xml.size()));
56  _p->file_stream.write(write_buffer, 4);
57 
58  // write the XML definition
59  _p->file_stream.write(xml.data(), int(xml.size()));
60 
61  _p->first_timestamp = std::chrono::system_clock::now().time_since_epoch();
62 
63  // save the first timestamp in the next 8 bytes (microseconds)
64  int64_t timestamp_usec = ToUsec(_p->first_timestamp);
65  flatbuffers::WriteScalar(write_buffer, timestamp_usec);
66  _p->file_stream.write(write_buffer, 8);
67 
68  _p->writer_thread = std::thread(&FileLogger2::writerLoop, this);
69 }
70 
72 {
73  _p->loop = false;
74  _p->queue_cv.notify_one();
75  _p->writer_thread.join();
76  _p->file_stream.close();
77 }
78 
79 void FileLogger2::callback(Duration timestamp, const TreeNode& node,
80  NodeStatus /*prev_status*/, NodeStatus status)
81 {
82  Transition trans;
83  trans.timestamp_usec = uint64_t(ToUsec(timestamp - _p->first_timestamp));
84  trans.node_uid = node.UID();
85  trans.status = static_cast<uint64_t>(status);
86  {
87  std::scoped_lock lock(_p->queue_mutex);
88  _p->transitions_queue.push_back(trans);
89  }
90  _p->queue_cv.notify_one();
91 }
92 
94 {
95  _p->file_stream.flush();
96 }
97 
99 {
100  // local buffer in this thread
101  std::deque<Transition> transitions;
102 
103  while(_p->loop)
104  {
105  transitions.clear();
106  {
107  std::unique_lock lock(_p->queue_mutex);
108  _p->queue_cv.wait_for(lock, std::chrono::milliseconds(10), [this]() {
109  return !_p->transitions_queue.empty() && _p->loop;
110  });
111  // simple way to pop all the transitions from _p->transitions_queue into transitions
112  std::swap(transitions, _p->transitions_queue);
113  }
114  while(!transitions.empty())
115  {
116  const auto trans = transitions.front();
117  std::array<char, 9> write_buffer;
118  std::memcpy(write_buffer.data(), &trans.timestamp_usec, 6);
119  std::memcpy(write_buffer.data() + 6, &trans.node_uid, 2);
120  std::memcpy(write_buffer.data() + 8, &trans.status, 1);
121 
122  _p->file_stream.write(write_buffer.data(), 9);
123  transitions.pop_front();
124  }
125  _p->file_stream.flush();
126  }
127 }
128 
129 } // namespace BT
BT
Definition: ex01_wrap_legacy.cpp:29
BT::FileLogger2::PImpl::queue_cv
std::condition_variable queue_cv
Definition: bt_file_logger_v2.cpp:20
BT::TreeNode::UID
uint16_t UID() const
Definition: tree_node.cpp:330
BT::FileLogger2::Transition::timestamp_usec
uint64_t timestamp_usec
Definition: bt_file_logger_v2.h:50
BT::FileLogger2::PImpl::first_timestamp
Duration first_timestamp
Definition: bt_file_logger_v2.cpp:17
BT::StatusChangeLogger::enableTransitionToIdle
void enableTransitionToIdle(bool enable)
Definition: abstract_logger.h:53
BT::TreeNode
Abstract base class for Behavior Tree Nodes.
Definition: tree_node.h:118
BT::Tree
Struct used to store a tree. If this object goes out of scope, the tree is destroyed.
Definition: bt_factory.h:91
BT::FileLogger2::Transition
Definition: bt_file_logger_v2.h:46
BT::FileLogger2::PImpl::file_stream
std::ofstream file_stream
Definition: bt_file_logger_v2.cpp:15
BT::StatusChangeLogger
Definition: abstract_logger.h:15
base.h
BT::Duration
std::chrono::high_resolution_clock::duration Duration
Definition: basic_types.h:628
BT::WriteTreeToXML
std::string WriteTreeToXML(const Tree &tree, bool add_metadata, bool add_builtin_models)
WriteTreeToXML create a string that contains the XML that corresponds to a given tree....
Definition: xml_parsing.cpp:1497
mutex
static pthread_mutex_t mutex
Definition: minitrace.cpp:77
BT::FileLogger2::PImpl::writer_thread
std::thread writer_thread
Definition: bt_file_logger_v2.cpp:23
BT::FileLogger2::Transition::node_uid
uint16_t node_uid
Definition: bt_file_logger_v2.h:52
BT::FileLogger2::~FileLogger2
virtual ~FileLogger2() override
Definition: bt_file_logger_v2.cpp:71
BT::FileLogger2::_p
std::unique_ptr< PImpl > _p
Definition: bt_file_logger_v2.h:60
bt_file_logger_v2.h
BT::FileLogger2::PImpl::transitions_queue
std::deque< Transition > transitions_queue
Definition: bt_file_logger_v2.cpp:19
BT::RuntimeError
Definition: exceptions.h:58
BT::FileLogger2::flush
void flush() override
Definition: bt_file_logger_v2.cpp:93
BT::FileLogger2::FileLogger2
FileLogger2(const Tree &tree, std::filesystem::path const &filepath)
To correctly read this log with Groot2, you must use the suffix ".btlog". Constructor will throw othe...
Definition: bt_file_logger_v2.cpp:27
BT::FileLogger2::Transition::status
uint8_t status
Definition: bt_file_logger_v2.h:54
xml_parsing.h
BT::FileLogger2::PImpl::loop
std::atomic_bool loop
Definition: bt_file_logger_v2.cpp:24
BT::FileLogger2::PImpl::queue_mutex
std::mutex queue_mutex
Definition: bt_file_logger_v2.cpp:21
lexyd::binary
_d< 2 > binary
Definition: digit.hpp:54
BT::ToUsec
int64_t ToUsec(Duration ts)
Definition: bt_file_logger_v2.cpp:8
std::swap
NLOHMANN_BASIC_JSON_TPL_DECLARATION void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL &j1, nlohmann::NLOHMANN_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp) is_nothrow_move_constructible< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression, cppcoreguidelines-noexcept-swap, performance-noexcept-swap) is_nothrow_move_assignable< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects
Definition: json.hpp:24537
BT::FileLogger2::writerLoop
void writerLoop()
Definition: bt_file_logger_v2.cpp:98
BT::NodeStatus
NodeStatus
Definition: basic_types.h:33
BT::FileLogger2::callback
void callback(Duration timestamp, const TreeNode &node, NodeStatus prev_status, NodeStatus status) override
Definition: bt_file_logger_v2.cpp:79
BT::FileLogger2::PImpl
Definition: bt_file_logger_v2.cpp:13


behaviortree_cpp_v4
Author(s): Davide Faconti
autogenerated on Fri Jun 28 2024 02:20:07