lvx_file.cpp
Go to the documentation of this file.
1 //
2 // The MIT License (MIT)
3 //
4 // Copyright (c) 2019 Livox. All rights reserved.
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining a copy
7 // of this software and associated documentation files (the "Software"), to deal
8 // in the Software without restriction, including without limitation the rights
9 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 // copies of the Software, and to permit persons to whom the Software is
11 // furnished to do so, subject to the following conditions:
12 //
13 // The above copyright notice and this permission notice shall be included in
14 // all copies or substantial portions of the Software.
15 //
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 // SOFTWARE.
23 //
24 
25 #include "lvx_file.h"
26 #include <string.h>
27 #include <time.h>
28 #include <cmath>
29 
30 #include "lds.h"
31 #include "rapidxml/rapidxml.hpp"
33 
34 namespace livox_ros {
35 
36 #define M_PI 3.14159265358979323846
37 
39 const char *kLvxHeaderSigStr = "livox_tech";
40 const uint32_t kLvxHeaderMagicCode = 0xac0ea767;
41 
43  : file_ver_(kLvxFileV1),
44  device_count_(0),
45  cur_frame_index_(0),
46  cur_offset_(0),
47  data_start_offset_(0),
48  size_(0),
49  mode_(0),
50  state_(0) {
51  memset((void *)&public_header_, 0, sizeof(public_header_));
52  memset((void *)&private_header_, 0, sizeof(private_header_));
53  memset((void *)&private_header_v0_, 0, sizeof(private_header_v0_));
54 }
55 
57  lvx_file_.seekg(0, std::ios::beg);
58  lvx_file_.read((char *)(&public_header_), sizeof(public_header_));
59 
60  if (strcmp((const char *)public_header_.signature, kLvxHeaderSigStr)) {
61  return false;
62  }
63 
70  printf("Unkown lvx file version[%d.%d.%d.%d]\n", public_header_.version[0],
73  return false;
74  }
75 
77  printf("Livox file version[%d]\n", file_ver_);
78 
79  return true;
80 }
81 
83  if (file_ver_ == kLvxFileV1) {
84  return (sizeof(LvxFilePublicHeader) + sizeof(LvxFilePrivateHeader) +
85  sizeof(LvxFileDeviceInfo) + sizeof(FrameHeader) +
86  sizeof(LvxFilePacket));
87  } else {
88  return (sizeof(LvxFilePublicHeader) + sizeof(LvxFilePrivateHeaderV0) +
89  sizeof(LvxFileDeviceInfoV0) + sizeof(FrameHeaderV0) +
90  sizeof(LvxFilePacketV0));
91  }
92 }
93 
95  return sizeof(LvxFilePublicHeader);
96 }
97 
99  if (file_ver_ == kLvxFileV1) {
100  return (sizeof(LvxFilePublicHeader) + sizeof(LvxFilePrivateHeader) +
102  } else {
103  return (sizeof(LvxFilePublicHeader) + sizeof(LvxFilePrivateHeaderV0) +
105  }
106 }
107 
109  lvx_file_.seekg(PrivateHeaderOffset(), std::ios::beg);
110 
111  if (file_ver_ == kLvxFileV1) {
112  lvx_file_.read((char *)(&private_header_), sizeof(private_header_));
114  } else {
115  lvx_file_.read((char *)(&private_header_v0_), sizeof(private_header_v0_));
117  }
118 
119  if (!device_count_) {
120  return false;
121  }
122 
123  for (int i = 0; i < device_count_; i++) {
124  LvxFileDeviceInfo device_info;
125  if (file_ver_ == kLvxFileV1) {
126  lvx_file_.read((char *)(&device_info), sizeof(LvxFileDeviceInfo));
127  } else { /* device info v0 to v1 */
128  LvxFileDeviceInfoV0 device_info_v0;
129  lvx_file_.read((char *)(&device_info_v0), sizeof(LvxFileDeviceInfoV0));
130  memcpy((void *)&device_info, (void *)&device_info_v0,
131  &device_info.extrinsic_enable - device_info.lidar_broadcast_code);
132  memcpy((void *)&device_info.roll, (void *)&device_info_v0.roll,
133  sizeof(float) * 6);
134  device_info.extrinsic_enable = 0;
135  }
136  AddDeviceInfo(device_info);
137  }
138 
139  return true;
140 }
141 
143  lvx_file_.seekg(DataStartOffset(), std::ios::beg);
144 
145  FrameHeader frame_header; /* v0&v1 compatible */
146  lvx_file_.read((char *)(&frame_header), sizeof(frame_header));
147 
148  if ((frame_header.current_offset != DataStartOffset()) ||
149  (frame_header.frame_index != 0)) {
150  return false;
151  }
152 
154  lvx_file_.seekg(DataStartOffset(), std::ios::beg);
155 
156  return true;
157 }
158 
159 int LvxFileHandle::Open(const char *filename, std::ios_base::openmode mode) {
160  if ((mode & std::ios::in) == std::ios::in) {
161  state_ = kLvxFileOk;
162  lvx_file_.open(filename, mode | std::ios_base::binary | std::ios_base::ate);
163 
164  if (!lvx_file_.is_open()) {
166  return state_;
167  }
168 
169  size_ = lvx_file_.tellg();
170  lvx_file_.seekg(0, std::ios::beg);
171  printf("Filesize %lu\n", size_);
172 
173  if (size_ < MiniFileSize()) {
175 
176  return state_;
177  }
178 
179  if (!ReadAndCheckHeader()) {
181  return state_;
182  }
183 
184  if (!AddAndCheckDeviceInfo()) {
186  return state_;
187  }
188 
189  if (!PrepareDataRead()) {
191  return state_;
192  }
193  } else {
194  lvx_file_.open(filename, mode | std::ios_base::binary);
195 
196  if (!lvx_file_.is_open()) {
198  return state_;
199  }
200  }
201 
202  return state_;
203 }
204 
205 bool LvxFileHandle::Eof() { return lvx_file_.eof(); }
206 
208  time_t curtime = time(nullptr);
209  char filename[30] = {0};
210 
211  tm *local_time = localtime(&curtime);
212  strftime(filename, sizeof(filename), "%Y%m%d%H%M%S", local_time);
213 
214  return Open(filename, std::ios::out | std::ios::binary);
215 }
216 
218  char write_buffer[kMaxLvxFileHeaderLength];
219  cur_offset_ = 0;
220 
221  std::string signature = kLvxHeaderSigStr;
222  memcpy(public_header_.signature, signature.c_str(), signature.size());
223  public_header_.version[0] = 1;
224  public_header_.version[1] = file_ver_; /* default version 1 */
225  public_header_.version[2] = 0;
226  public_header_.version[3] = 0;
228  memcpy(&write_buffer[cur_offset_], (void *)&public_header_,
229  sizeof(public_header_));
230  cur_offset_ += sizeof(public_header_);
231 
232  if (file_ver_ == kLvxFileV1) {
234  static_cast<uint8_t>(device_info_list_.size());
237  memcpy(&write_buffer[cur_offset_], (void *)&private_header_,
238  sizeof(private_header_));
239  cur_offset_ += sizeof(private_header_);
240  } else {
242  static_cast<uint8_t>(device_info_list_.size());
244  memcpy(&write_buffer[cur_offset_], (void *)&private_header_v0_,
245  sizeof(private_header_v0_));
246  cur_offset_ += sizeof(private_header_v0_);
247  }
248 
249  for (int i = 0; i < device_count_; i++) {
250  if (file_ver_ == kLvxFileV1) {
251  memcpy(&write_buffer[cur_offset_], (void *)&device_info_list_[i],
252  sizeof(LvxFileDeviceInfo));
253  cur_offset_ += sizeof(LvxFileDeviceInfo);
254  } else {
255  LvxFileDeviceInfoV0 device_info_v0;
256  memcpy((void *)&device_info_v0, (void *)&device_info_list_[i],
257  &device_info_list_[i].extrinsic_enable -
258  device_info_list_[i].lidar_broadcast_code);
259  memcpy((void *)&device_info_v0.roll, (void *)&device_info_list_[i].roll,
260  sizeof(float) * 6);
261  memcpy(&write_buffer[cur_offset_], (void *)&device_info_v0,
262  sizeof(device_info_v0));
263  cur_offset_ += sizeof(device_info_v0);
264  }
265  }
266 
267  lvx_file_.write(&write_buffer[cur_offset_], cur_offset_);
268 }
269 
271  std::list<LvxFilePacket> &point_packet_list_temp) {
272  uint64_t cur_pos = 0;
273  FrameHeader frame_header = {0};
274  std::unique_ptr<char[]> write_buffer(new char[kMaxFrameSize]);
275 
276  frame_header.current_offset = cur_offset_;
277  frame_header.next_offset = cur_offset_ + sizeof(FrameHeader);
278  for (auto iter : point_packet_list_temp) {
279  frame_header.next_offset += iter.pack_size;
280  }
281 
282  frame_header.frame_index = cur_frame_index_;
283 
284  memcpy(write_buffer.get() + cur_pos, (void *)&frame_header,
285  sizeof(FrameHeader));
286  cur_pos += sizeof(FrameHeader);
287 
288  for (auto iter : point_packet_list_temp) {
289  if (cur_pos + iter.pack_size >= kMaxFrameSize) {
290  lvx_file_.write((char *)write_buffer.get(), cur_pos);
291  cur_pos = 0;
292  memcpy(write_buffer.get() + cur_pos, (void *)&(iter), iter.pack_size);
293  cur_pos += iter.pack_size;
294  } else {
295  memcpy(write_buffer.get() + cur_pos, (void *)&(iter), iter.pack_size);
296  cur_pos += iter.pack_size;
297  }
298  }
299  lvx_file_.write((char *)write_buffer.get(), cur_pos);
300 
301  cur_offset_ = frame_header.next_offset;
303 }
304 
306  if (lvx_file_ && lvx_file_.is_open()) lvx_file_.close();
307 }
308 
309 void LvxFileHandle::BasePointsHandle(LivoxEthPacket *data,
310  LvxFilePacket &packet) {
311  memcpy((void *)&packet, (void *)data, GetEthPacketLen(data->data_type));
312 }
313 
315  if (idx < device_info_list_.size()) {
316  *info = device_info_list_[idx];
317  return 0;
318  }
319 
320  return -1;
321 }
322 
324  if (!lvx_file_ || lvx_file_.eof()) {
326  return kLvxFileAtEnd;
327  }
328 
329  uint64_t tmp_size = lvx_file_.tellg();
330  if (tmp_size >= size_) {
331  printf("At the file end %lu\n", tmp_size);
333  return kLvxFileAtEnd;
334  }
335 
336  FrameHeader frame_header;
337  FrameHeaderV0 frame_header_v0;
338  uint64_t read_length;
339  if (file_ver_ == kLvxFileV1) {
340  lvx_file_.read((char *)&frame_header, sizeof(frame_header));
341  if (!lvx_file_) {
342  return kLvxFileReadFail;
343  }
344  if ((size_ < frame_header.current_offset) ||
345  (frame_header.next_offset < frame_header.current_offset)) {
347  }
348  packets_of_frame->data_size = DataSizeOfFrame(frame_header);
349  read_length = packets_of_frame->data_size;
350  } else {
351  lvx_file_.read((char *)&frame_header_v0, sizeof(frame_header_v0));
352  if (!lvx_file_) {
353  return kLvxFileReadFail;
354  }
355  if ((size_ < frame_header_v0.current_offset) ||
356  (frame_header_v0.next_offset < frame_header_v0.current_offset)) {
358  }
359  packets_of_frame->data_size = DataSizeOfFrame(frame_header_v0);
360  read_length = packets_of_frame->data_size;
361  }
362  lvx_file_.read((char *)(packets_of_frame->packet), read_length);
363  if (lvx_file_) {
364  return kLvxFileOk;
365  } else {
366  return kLvxFileReadFail;
367  }
368 }
369 
371  if (!size_) {
372  return 0;
373  }
374 
375  if (!lvx_file_.eof()) {
376  return (lvx_file_.tellg() * 100ULL) / size_;
377  } else {
378  return 100;
379  }
380 }
381 
383  rapidxml::file<> extrinsic_param("extrinsic.xml");
385  doc.parse<0>(extrinsic_param.data());
386  rapidxml::xml_node<> *root = doc.first_node();
387  if ("Livox" == (std::string)root->name()) {
388  for (rapidxml::xml_node<> *device = root->first_node(); device;
389  device = device->next_sibling()) {
390  if ("Device" == (std::string)device->name() &&
391  (strncmp(item.info.broadcast_code, device->value(),
392  kBroadcastCodeSize) == 0)) {
393  memcpy(info.lidar_broadcast_code, device->value(), kBroadcastCodeSize);
394  memset(info.hub_broadcast_code, 0, kBroadcastCodeSize);
395  info.device_type = item.info.type;
396  info.device_index = item.handle;
397  for (rapidxml::xml_attribute<> *param = device->first_attribute();
398  param; param = param->next_attribute()) {
399  if ("roll" == (std::string)param->name()) {
400  info.roll = static_cast<float>(atof(param->value()));
401  }
402  if ("pitch" == (std::string)param->name()) {
403  info.pitch = static_cast<float>(atof(param->value()));
404  }
405  if ("yaw" == (std::string)param->name()) {
406  info.yaw = static_cast<float>(atof(param->value()));
407  }
408  if ("x" == (std::string)param->name()) {
409  info.x = static_cast<float>(atof(param->value()));
410  }
411  if ("y" == (std::string)param->name()) {
412  info.y = static_cast<float>(atof(param->value()));
413  }
414  if ("z" == (std::string)param->name()) {
415  info.z = static_cast<float>(atof(param->value()));
416  }
417  }
418  }
419  }
420  }
421 }
422 
423 } // namespace livox_ros
This file contains rapidxml parser and DOM implementation.
LvxFilePublicHeader public_header_
Definition: lvx_file.h:202
filename
bool param(const std::string &param_name, T &param_val, const T &default_val)
uint64_t PrivateHeaderOffset()
Definition: lvx_file.cpp:94
const uint32_t kMaxLvxFileHeaderLength
Definition: lvx_file.cpp:38
Represents data loaded from a file.
LvxFilePrivateHeader private_header_
Definition: lvx_file.h:203
const uint32_t kLvxHeaderMagicCode
Definition: lvx_file.cpp:40
const uint32_t kMaxFrameSize
Definition: lvx_file.h:39
uint64_t DataStartOffset()
Definition: lvx_file.cpp:98
const char * kLvxHeaderSigStr
Definition: lvx_file.cpp:39
uint8_t hub_broadcast_code[16]
Definition: lvx_file.h:87
void parse(Ch *text)
Definition: rapidxml.hpp:1319
unsigned char uint8_t
Definition: stdint.h:125
int GetDeviceInfo(uint8_t idx, LvxFileDeviceInfo *info)
Definition: lvx_file.cpp:314
xml_node< Ch > * first_node(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
Definition: rapidxml.hpp:895
int GetPacketsOfFrame(OutPacketBuffer *PacketsOfFrame)
Definition: lvx_file.cpp:323
int Open(const char *filename, std::ios_base::openmode mode)
Definition: lvx_file.cpp:159
void SaveFrameToLvxFile(std::list< LvxFilePacket > &point_packet_list_temp)
Definition: lvx_file.cpp:270
uint64_t current_offset
Definition: lvx_file.h:114
std::vector< LvxFileDeviceInfo > device_info_list_
Definition: lvx_file.h:199
unsigned int uint32_t
Definition: stdint.h:127
Ch * name() const
Definition: rapidxml.hpp:657
unsigned __int64 uint64_t
Definition: stdint.h:137
uint64_t DataSizeOfFrame(FrameHeader &frame_header)
Definition: lvx_file.h:222
uint8_t lidar_broadcast_code[16]
Definition: lvx_file.h:86
void BasePointsHandle(LivoxEthPacket *data, LvxFilePacket &packet)
Definition: lvx_file.cpp:309
LvxFilePrivateHeaderV0 private_header_v0_
Definition: lvx_file.h:204
DeviceInfo info
Definition: lvx_file.h:69
void AddDeviceInfo(LvxFileDeviceInfo &info)
Definition: lvx_file.h:186
std::fstream lvx_file_
Definition: lvx_file.h:198
uint32_t GetEthPacketLen(uint32_t data_type)
Definition: lds.h:308
void ParseExtrinsicXml(DeviceItem &item, LvxFileDeviceInfo &info)
Definition: lvx_file.cpp:382


livox_ros_driver
Author(s): Livox Dev Team
autogenerated on Mon Mar 15 2021 02:40:46