Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00033
00034
00035 #include "tCanMatrixParser.h"
00036
00037 #include "icl_hardware_can/Logging.h"
00038 #include "icl_core_config/Config.h"
00039
00040 #include <boost/filesystem.hpp>
00041 #include <map>
00042 #include <tinyxml.h>
00043
00044 #ifdef _IC_BUILDER_CANTOOLS_
00045 extern "C" {
00046 #include <dbcModel.h>
00047 #include <dbcReader.h>
00048 }
00049 #endif
00050
00051 namespace icl_hardware {
00052 namespace can {
00053
00054 tCanMatrixParser::tCanMatrixParser(const std::string identifier)
00055 : m_data_file_name(NULL),
00056 is_initialized(false)
00057 {
00058
00059
00060 if (identifier != "")
00061 {
00062 setDataFileName(boost::filesystem::path(identifier));
00063 }
00064 else
00065 {
00066 throw std::runtime_error("No CAN matrix provided!");
00067 return;
00068 }
00069
00070 LOGGING_DEBUG(icl_hardware::can::CAN, "Opening CanMatrixParser with interpreter data from file: " << getDataFileName().string() << icl_core::logging::endl);
00071
00072 int ret = 0;
00073 #if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2
00074 std::string extension = getDataFileName().extension();
00075 #else
00076 std::string extension = getDataFileName().extension().string();
00077 #endif
00078
00079 if (extension == ".xml" || extension == ".canxml")
00080 {
00081
00082 TiXmlHandle doc_handle(NULL);
00083 TiXmlDocument default_header_file(getDataFileName().string());
00084
00085 if (default_header_file.LoadFile())
00086 {
00087 doc_handle = TiXmlHandle(&default_header_file);
00088 if (!doc_handle.FirstChildElement().ToElement())
00089 {
00090
00091 throw std::runtime_error("Found no root tag in " + getDataFileName().string());
00092 return;
00093 }
00094 }
00095 else
00096 {
00097 throw std::runtime_error("File " + getDataFileName().string() + " is not well-formed XML");
00098 return;
00099 }
00100
00101 ret = mapContentOfFile(doc_handle);
00102 }
00103 else if (extension == ".dbc")
00104 {
00105 #ifdef _IC_BUILDER_CANTOOLS_
00106 dbc_t* dbc;
00107
00108 if (boost::filesystem::exists(getDataFileName()))
00109 {
00110 dbc = dbc_read_file(getDataFileName().string().c_str());
00111 if (!dbc->filename)
00112 {
00113 throw std::runtime_error("File " + getDataFileName().string() + " is not a valid DBC file");
00114 return;
00115 }
00116 ret = mapContentOfFile(dbc);
00117 dbc_free(dbc);
00118 }
00119 else
00120 {
00121 throw std::runtime_error("File " + getDataFileName().string() + " is not a valid file");
00122 return;
00123 }
00124 #else
00125 throw std::runtime_error("Missing dbc support, please compile with cantools library.");
00126 return;
00127 #endif
00128 }
00129
00130 if(ret != 0)
00131 {
00132 throw std::runtime_error("CanMatrix could not be read.");
00133 return;
00134 }
00135
00136 is_initialized = true;
00137 }
00138
00139 tCanMatrixParser::~tCanMatrixParser()
00140 {
00141 if (m_data_file_name != NULL)
00142 {
00143 delete m_data_file_name;
00144 m_data_file_name = NULL;
00145 }
00146 }
00147
00148 const CanMatrix& tCanMatrixParser::getCanMatrix() const
00149 {
00150 return m_canmatrix;
00151 }
00152
00153 int tCanMatrixParser::mapContentOfFile(TiXmlHandle &doc_handle)
00154 {
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174 TiXmlElement * element = doc_handle.FirstChildElement().ToElement();
00175 if (std::string(element->Value()) != "icl_hardware_can")
00176 {
00177 LOGGING_ERROR(icl_hardware::can::CAN, "Found no <icl_hardware_can> root tag in " << getDataFileName().string() << icl_core::logging::endl);
00178 return -1;
00179 }
00180
00181 TiXmlElement* message_data = doc_handle.FirstChildElement().FirstChildElement().FirstChildElement().ToElement();
00182 if (std::string(message_data->Value()) == "message")
00183 {
00184 unsigned int id = 0;
00185
00186 struct CanMatrixElement can_matrix_data = {"", 0., "", 0 , 0 , 0., 0., 0., false, false};
00187
00188 if (checkXmlFile(message_data) == 0)
00189 {
00190 do
00191 {
00192 id = atoi(message_data->FirstChild("canid")->ToElement()->GetText());
00193 can_matrix_data.conversion = atof(message_data->FirstChild("conversion")->ToElement()->GetText());
00194 can_matrix_data.description = message_data->FirstChild("description")->ToElement()->GetText();
00195 can_matrix_data.unit = message_data->FirstChild("unit")->ToElement()->GetText();
00196 can_matrix_data.start_bit = atoi(message_data->FirstChild("data_start_bit")->ToElement()->GetText());
00197 can_matrix_data.signal_length = atoi(message_data->FirstChild("signal_length")->ToElement()->GetText());
00198 can_matrix_data.offset = atof(message_data->FirstChild("offset")->ToElement()->GetText());
00199 can_matrix_data.lower_border = atof(message_data->FirstChild("lower_border")->ToElement()->GetText());
00200 can_matrix_data.upper_border = atof(message_data->FirstChild("upper_border")->ToElement()->GetText());
00201 can_matrix_data.little_endian = bool(atoi(message_data->FirstChild("little_endian")->ToElement()->GetText()));
00202 can_matrix_data.signedness = bool(atoi(message_data->FirstChild("signedness")->ToElement()->GetText()));
00203
00204 CanMatrix::iterator iter = m_canmatrix.find(id);
00205
00206 if (iter != m_canmatrix.end())
00207 {
00209 iter->second.insert(iter->second.end(), can_matrix_data);
00210 }
00211 else
00212 {
00214 m_canmatrix.insert(std::pair<unsigned int, std::vector<CanMatrixElement> >(id, std::vector<CanMatrixElement>(1, can_matrix_data)));
00215 }
00216
00217 }
00218 while ((message_data = message_data->NextSiblingElement()));
00219 message_data = NULL;
00220 }
00221 else
00222 {
00223 LOGGING_ERROR(icl_hardware::can::CAN, "Structure of xml-file is not compatible." << icl_core::logging::endl);
00224 LOGGING_ERROR(icl_hardware::can::CAN, "Missing child element!" << icl_core::logging::endl);
00225 return -1;
00226 }
00227 }
00228 else
00229 {
00230 LOGGING_ERROR(icl_hardware::can::CAN, "Structure of xml-file is not compatible " << getDataFileName().string() << icl_core::logging::endl);
00231 return -1;
00232 }
00233 element = NULL;
00234
00235 return 0;
00236 }
00237
00238 const int tCanMatrixParser::checkXmlFile(TiXmlElement *element) const
00239 {
00240
00241 if (element->FirstChild("canid") && element->FirstChild("conversion") && element->FirstChild("description")
00242 && element->FirstChild("unit") && element->FirstChild("data_start_bit") && element->FirstChild("signal_length")
00243 && element->FirstChild("offset") && element->FirstChild("lower_border") && element->FirstChild("upper_border")
00244 && element->FirstChild("little_endian") && element->FirstChild("signedness") )
00245 {
00246 return 0;
00247 }
00248 else
00249 {
00250 return -1;
00251 }
00252 }
00253
00254 int tCanMatrixParser::mapContentOfFile(void *dbc_)
00255 {
00256 #ifndef _IC_BUILDER_CANTOOLS_
00257 return -1;
00258 #else
00259 dbc_t *dbc = reinterpret_cast<dbc_t*>(dbc_);
00260
00261 if (!dbc)
00262 {
00263 return -1;
00264 }
00265
00266 message_list_t *ml;
00267 signal_list_t *sl;
00268
00269 for(ml = dbc->message_list; ml != NULL; ml = ml->next) {
00270 unsigned int id = ml->message->id;
00271
00272 for(sl = ml->message->signal_list; sl != NULL; sl = sl->next) {
00273 struct CanMatrixElement can_matrix_data = {"", 0., "", 0 , 0 , 0., 0., 0., false, false};
00274
00275 can_matrix_data.conversion = sl->signal->scale;
00276 can_matrix_data.description = sl->signal->name;
00277 can_matrix_data.unit = sl->signal->unit?sl->signal->unit:"";
00278 can_matrix_data.start_bit = sl->signal->bit_start + 1;
00279 can_matrix_data.signal_length = sl->signal->bit_len;
00280 can_matrix_data.offset = sl->signal->offset;
00281 can_matrix_data.lower_border = sl->signal->min;
00282 can_matrix_data.upper_border = sl->signal->max;
00283 can_matrix_data.little_endian = sl->signal->endianess;
00284 can_matrix_data.signedness = sl->signal->signedness;
00285
00286 CanMatrix::iterator iter = m_canmatrix.find(id);
00287
00288 if (iter != m_canmatrix.end())
00289 {
00291 iter->second.insert(iter->second.end(), can_matrix_data);
00292 }
00293 else
00294 {
00296 m_canmatrix.insert(std::pair<unsigned int, std::vector<CanMatrixElement> >(id, std::vector<CanMatrixElement>(1, can_matrix_data)));
00297 }
00298 }
00299 }
00300
00301 #endif
00302 return 0;
00303 }
00304
00305 void tCanMatrixParser::setDataFileName(const boost::filesystem::path &file_name)
00306 {
00307 if (m_data_file_name)
00308 {
00309 delete m_data_file_name;
00310 }
00311 m_data_file_name = new boost::filesystem::path(file_name);
00312 }
00313
00314 const boost::filesystem::path & tCanMatrixParser::getDataFileName() const
00315 {
00316 return *m_data_file_name;
00317 }
00318
00319 const bool tCanMatrixParser::isActive() const
00320 {
00321 return is_initialized;
00322 }
00323
00324 std::ostream &operator<<(std::ostream &stream, const CanMatrix& can_matrix)
00325 {
00326
00327 stream << can_matrix.size();
00328 return stream;
00329 }
00330
00331 }
00332 }