tCanMatrixParser.cpp
Go to the documentation of this file.
1 // -- BEGIN LICENSE BLOCK ----------------------------------------------
2 // This file is part of FZIs ic_workspace.
3 //
4 // This program is free software licensed under the LGPL
5 // (GNU LESSER GENERAL PUBLIC LICENSE Version 3).
6 // You can find a copy of this license in LICENSE folder in the top
7 // directory of the source code.
8 //
9 // © Copyright 2016 FZI Forschungszentrum Informatik, Karlsruhe, Germany
10 //
11 // -- END LICENSE BLOCK ------------------------------------------------
12 
13 // ----------------------------------------------------------
14 /*
15  * tCanMatrixParser.cpp
16  * <section>
17  *
18  * Created by Hugo Ritzkowski on 2011-04-14.
19  * Copyright 2011
20  * Company Forschungszentrum Informatik (FZI), Abteilung IDS.
21  * All rights reserved.
22  *
23  */
24 // ----------------------------------------------------------
33 // ----------------------------------------------------------
34 
35 #include "tCanMatrixParser.h"
36 
38 #include "icl_core_config/Config.h"
39 
40 #include <boost/filesystem.hpp>
41 #include <map>
42 #include <tinyxml.h>
43 
44 #ifdef _IC_BUILDER_CANTOOLS_
45 extern "C" {
46 #include <dbcModel.h>
47 #include <dbcReader.h>
48 }
49 #endif
50 
51 namespace icl_hardware {
52 namespace can {
53 
54 tCanMatrixParser::tCanMatrixParser(const std::string identifier)
55  : m_data_file_name(NULL),
56  is_initialized(false)
57 {
58 
59  //get the filename of the xml-file
60  if (identifier != "")
61  {
62  setDataFileName(boost::filesystem::path(identifier));
63  }
64  else
65  {
66  throw std::runtime_error("No CAN matrix provided!");
67  return;
68  }
69 
70  LOGGING_DEBUG(icl_hardware::can::CAN, "Opening CanMatrixParser with interpreter data from file: " << getDataFileName().string() << icl_core::logging::endl);
71 
72  int ret = 0;
73 #if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2
74  std::string extension = getDataFileName().extension();
75 #else
76  std::string extension = getDataFileName().extension().string();
77 #endif
78 
79  if (extension == ".xml" || extension == ".canxml")
80  {
81  // open and check xml-file
82  TiXmlHandle doc_handle(NULL);
83  TiXmlDocument default_header_file(getDataFileName().string());
84 
85  if (default_header_file.LoadFile())
86  {
87  doc_handle = TiXmlHandle(&default_header_file);
88  if (!doc_handle.FirstChildElement().ToElement())
89  {
90  // No valid root tag
91  throw std::runtime_error("Found no root tag in " + getDataFileName().string());
92  return;
93  }
94  }
95  else
96  {
97  throw std::runtime_error("File " + getDataFileName().string() + " is not well-formed XML");
98  return;
99  }
100  //get content of xml-file in std::map
101  ret = mapContentOfFile(doc_handle);
102  }
103  else if (extension == ".dbc")
104  {
105 #ifdef _IC_BUILDER_CANTOOLS_
106  dbc_t* dbc;
107 
108  if (boost::filesystem::exists(getDataFileName()))
109  {
110  dbc = dbc_read_file(getDataFileName().string().c_str());
111  if (!dbc->filename)
112  {
113  throw std::runtime_error("File " + getDataFileName().string() + " is not a valid DBC file");
114  return;
115  }
116  ret = mapContentOfFile(dbc);
117  dbc_free(dbc);
118  }
119  else
120  {
121  throw std::runtime_error("File " + getDataFileName().string() + " is not a valid file");
122  return;
123  }
124 #else
125  throw std::runtime_error("Missing dbc support, please compile with cantools library.");
126  return;
127 #endif
128  }
129 
130  if(ret != 0)
131  {
132  throw std::runtime_error("CanMatrix could not be read.");
133  return;
134  }
135 
136  is_initialized = true;
137 }
138 
140 {
141  if (m_data_file_name != NULL)
142  {
143  delete m_data_file_name;
144  m_data_file_name = NULL;
145  }
146 }
147 
149 {
150  return m_canmatrix;
151 }
152 
153 int tCanMatrixParser::mapContentOfFile(TiXmlHandle &doc_handle)
154 {
155  // <icl_hardware_can>
156  // <can_matrix>
157  // <message>
158  // <canid>32</canid>
159  // <conversion>0.001</conversion>
160  // <description>The velocity of the left wheel</description>
161  // <unit>1/s</unit>
162  // <data_start_bit> 2 </data_start_bit> (index 0..63)
163  // <signal_length> 2 </signal_length>
164  // <offset> 10. </offset>
165  // <lower_bound> 0. </lower_bound>
166  // <upper_bound> 1. </upper_bound>
167  // <little_endian> 1 </little_endian>
168  // <signedness> 0 </signedness>
169  // </message>
170  // ...
171  // </can_matrix>
172  // </icl_hardware_can>
173 
174  TiXmlElement * element = doc_handle.FirstChildElement().ToElement();
175  if (std::string(element->Value()) != "icl_hardware_can")
176  {
177  LOGGING_ERROR(icl_hardware::can::CAN, "Found no <icl_hardware_can> root tag in " << getDataFileName().string() << icl_core::logging::endl);
178  return -1;
179  }
180 
181  TiXmlElement* message_data = doc_handle.FirstChildElement().FirstChildElement().FirstChildElement().ToElement();
182  if (std::string(message_data->Value()) == "message")
183  {
184  unsigned int id = 0;
185 
186  struct CanMatrixElement can_matrix_data = {"", 0., "", 0 , 0 , 0., 0., 0., false, false};
187 
188  if (checkXmlFile(message_data) == 0)
189  {
190  do
191  {
192  id = atoi(message_data->FirstChild("canid")->ToElement()->GetText());
193  can_matrix_data.conversion = atof(message_data->FirstChild("conversion")->ToElement()->GetText());
194  can_matrix_data.description = message_data->FirstChild("description")->ToElement()->GetText();
195  can_matrix_data.unit = message_data->FirstChild("unit")->ToElement()->GetText();
196  can_matrix_data.start_bit = atoi(message_data->FirstChild("data_start_bit")->ToElement()->GetText());
197  can_matrix_data.signal_length = atoi(message_data->FirstChild("signal_length")->ToElement()->GetText());
198  can_matrix_data.offset = atof(message_data->FirstChild("offset")->ToElement()->GetText());
199  can_matrix_data.lower_border = atof(message_data->FirstChild("lower_border")->ToElement()->GetText());
200  can_matrix_data.upper_border = atof(message_data->FirstChild("upper_border")->ToElement()->GetText());
201  can_matrix_data.little_endian = bool(atoi(message_data->FirstChild("little_endian")->ToElement()->GetText()));
202  can_matrix_data.signedness = bool(atoi(message_data->FirstChild("signedness")->ToElement()->GetText()));
203 
204  CanMatrix::iterator iter = m_canmatrix.find(id);
205 
206  if (iter != m_canmatrix.end())
207  {
209  iter->second.insert(iter->second.end(), can_matrix_data);
210  }
211  else
212  {
214  m_canmatrix.insert(std::pair<unsigned int, std::vector<CanMatrixElement> >(id, std::vector<CanMatrixElement>(1, can_matrix_data)));
215  }
216 
217  }
218  while ((message_data = message_data->NextSiblingElement()));
219  message_data = NULL;
220  }
221  else
222  {
223  LOGGING_ERROR(icl_hardware::can::CAN, "Structure of xml-file is not compatible." << icl_core::logging::endl);
224  LOGGING_ERROR(icl_hardware::can::CAN, "Missing child element!" << icl_core::logging::endl);
225  return -1;
226  }
227  }
228  else
229  {
230  LOGGING_ERROR(icl_hardware::can::CAN, "Structure of xml-file is not compatible " << getDataFileName().string() << icl_core::logging::endl);
231  return -1;
232  }
233  element = NULL;
234 
235  return 0;
236 }
237 
238 const int tCanMatrixParser::checkXmlFile(TiXmlElement *element) const
239 {
240 
241  if (element->FirstChild("canid") && element->FirstChild("conversion") && element->FirstChild("description")
242  && element->FirstChild("unit") && element->FirstChild("data_start_bit") && element->FirstChild("signal_length")
243  && element->FirstChild("offset") && element->FirstChild("lower_border") && element->FirstChild("upper_border")
244  && element->FirstChild("little_endian") && element->FirstChild("signedness") )
245  {
246  return 0;
247  }
248  else
249  {
250  return -1;
251  }
252 }
253 
255 {
256 #ifndef _IC_BUILDER_CANTOOLS_
257  return -1;
258 #else
259  dbc_t *dbc = reinterpret_cast<dbc_t*>(dbc_);
260 
261  if (!dbc)
262  {
263  return -1;
264  }
265 
266  message_list_t *ml;
267  signal_list_t *sl;
268 
269  for(ml = dbc->message_list; ml != NULL; ml = ml->next) {
270  unsigned int id = ml->message->id;
271 
272  for(sl = ml->message->signal_list; sl != NULL; sl = sl->next) {
273  struct CanMatrixElement can_matrix_data = {"", 0., "", 0 , 0 , 0., 0., 0., false, false};
274 
275  can_matrix_data.conversion = sl->signal->scale;
276  can_matrix_data.description = sl->signal->name;
277  can_matrix_data.unit = sl->signal->unit?sl->signal->unit:"";
278  can_matrix_data.start_bit = sl->signal->bit_start + 1;
279  can_matrix_data.signal_length = sl->signal->bit_len;
280  can_matrix_data.offset = sl->signal->offset;
281  can_matrix_data.lower_border = sl->signal->min;
282  can_matrix_data.upper_border = sl->signal->max;
283  can_matrix_data.little_endian = sl->signal->endianess;
284  can_matrix_data.signedness = sl->signal->signedness;
285 
286  CanMatrix::iterator iter = m_canmatrix.find(id);
287 
288  if (iter != m_canmatrix.end())
289  {
291  iter->second.insert(iter->second.end(), can_matrix_data);
292  }
293  else
294  {
296  m_canmatrix.insert(std::pair<unsigned int, std::vector<CanMatrixElement> >(id, std::vector<CanMatrixElement>(1, can_matrix_data)));
297  }
298  }
299  }
300 
301 #endif
302  return 0;
303 }
304 
305 void tCanMatrixParser::setDataFileName(const boost::filesystem::path &file_name)
306 {
307  if (m_data_file_name)
308  {
309  delete m_data_file_name;
310  }
311  m_data_file_name = new boost::filesystem::path(file_name);
312 }
313 
314 const boost::filesystem::path & tCanMatrixParser::getDataFileName() const
315 {
316  return *m_data_file_name;
317 }
318 
319 const bool tCanMatrixParser::isActive() const
320 {
321  return is_initialized;
322 }
323 
324 std::ostream &operator<<(std::ostream &stream, const CanMatrix& can_matrix)
325 {
326 // icl_graphics::tCameraParameterIO::WriteDeviceTag(&camera_parameter_provider, stream);
327  stream << can_matrix.size();
328  return stream;
329 }
330 
331 }
332 }
#define LOGGING_DEBUG(streamname, arg)
std::ostream & operator<<(std::ostream &os, InterpretedCanMessages const &interpreted_can_messages)
#define LOGGING_ERROR(streamname, arg)
This modul constructs a map of a can-mask-file the map can be request by getcanmatrix() ...
boost::filesystem::path * m_data_file_name
ThreadStream & endl(ThreadStream &stream)
const boost::filesystem::path & getDataFileName() const
const int checkXmlFile(TiXmlElement *element) const
tCanMatrixParser(const std::string identifier="")
int mapContentOfFile(TiXmlHandle &doc_handle)
const CanMatrix & getCanMatrix() const
std::map< unsigned int, std::vector< CanMatrixElement > > CanMatrix
void setDataFileName(const boost::filesystem::path &file_name)


fzi_icl_can
Author(s):
autogenerated on Mon Jun 10 2019 13:17:02