MBDyn-1.7.3
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups
module-flightgear.cc
Go to the documentation of this file.
1 /* $Header: /var/cvs/mbdyn/mbdyn/mbdyn-1.0/modules/module-flightgear/module-flightgear.cc,v 1.2 2017/09/28 10:04:32 masarati Exp $ */
2 /*
3  * MBDyn (C) is a multibody analysis code.
4  * http://www.mbdyn.org
5  *
6  * Copyright (C) 1996-2017
7  *
8  * Pierangelo Masarati <masarati@aero.polimi.it>
9  * Paolo Mantegazza <mantegazza@aero.polimi.it>
10  *
11  * Dipartimento di Ingegneria Aerospaziale - Politecnico di Milano
12  * via La Masa, 34 - 20156 Milano, Italy
13  * http://www.aero.polimi.it
14  *
15  * Changing this copyright notice is forbidden.
16  *
17  * This program is free software; you can redistribute it and/or modify
18  * it under the terms of the GNU General Public License as published by
19  * the Free Software Foundation (version 2 of the License).
20  *
21  *
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25  * GNU General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License
28  * along with this program; if not, write to the Free Software
29  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30  */
31 
32 #include "mbconfig.h" /* This goes first in every *.c,*.cc file */
33 
34 //#include <cstdint>
35 #include <unistd.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <fcntl.h>
39 
40 #include <fstream>
41 
42 #include "userelem.h"
43 #include "socketstream_out_elem.h"
44 #include "socketstreamdrive.h"
45 #include "bufmod.h"
46 #include "drive_.h"
47 
48 #include "module-flightgear.h"
49 
52 
57 
58 extern "C"
59 int module_init(const char *module_name, void *pdm, void *php){
60 
61 #if 0
62  DataManager *pDM = (DataManager *)pdm;
63  MBDynParser *pHP = (MBDynParser *)php;
64 #endif
65  /*Stream output element content type for Flight Gear*/
67  if (!SetStreamOutputContentType("FlightGear", rf1)) {
68  delete rf1;
69  return -1;
70  }
71 
72  /*file drive content type for Flight Gear*/
74  if (!SetFileDriveContentType("FlightGear", rf2)) {
75  delete rf2;
76  return -1;
77  }
78 
79  /*file drive caller content type for Flight Gear*/
81  if (!setFileDriveCallerType("FlightGear", rf3)) {
82  delete rf3;
83  return -1;
84  }
85 
87 
88  return 0;
89 }
90 
92  //FGStructuresLoaded = true;
93  readFGStructuresFromFile("FG_structures/FGNetFDM_structure.txt", "FG_NET_FDM_VERSION", fieldsDescriptionFGNetFDM, FGNetFDMCurVersion);
94  readFGStructuresFromFile("FG_structures/FGNetCtrls_structure.txt", "FG_NET_CTRLS_VERSION", fieldsDescriptionFGNetCtrls, FGNetCtrlsCurVersion);
95 }
96 
97 void readFGStructuresFromFile(const char *filePath, std::string currentVersionLabel, FieldsDescriptionFG &fieldsDescriptionFG, int &currentVersion){
98 
99  std::string fieldNameDelimiter = ":";//after name field this character must occur
100  std::string fieldInfoDelimiter = "= ";//before field info (type, size, offset) this character must occur
101  std::string fieldInfoSeparator = ",";//field info (type, size, offset) are comma separated
102  std::string openSquareBracket = "[";//used to identify fields with multiple entities (array)
103 
104  std::ifstream infile(filePath);
105 
106  /*checks if file is correctly opened*/
107  if(!infile.is_open()){
108  silent_cerr("Error while loading of " << filePath << ": file not found" << std::endl);
110  }
111 
112  std::string line; /*the file is read by lines: every line is temporary stored inside of this object*/
113  std::getline(infile, line);/*gets first line of the file, where field 'version' should be stored*/
114 
115  /*checks if file is empty*/
116  if(infile.eof()){
117  silent_cerr("Error while reading " << filePath << ": file is empty"<< std::endl);
119  }
120 
121  /*reads current version*/
122 
123  if(line.find(currentVersionLabel) == std::string::npos){/*checks if version is present and it is the first field*/
124  silent_cerr("Error while reading " << filePath << ": " << currentVersionLabel << " not found at line '" << line.substr(0, line.size()-1) << "'" << std::endl);
126  }
127  std::size_t found = line.find(fieldInfoDelimiter);/*finds delimiter before version value*/
128  if(found == std::string::npos){/*checks if delimiter is present before version value*/
129  silent_cerr("Error while reading " << filePath << ": " << "delimiter '" << fieldInfoDelimiter << "' not found after " << currentVersionLabel << std::endl);
131  }
132  /*acquisition of the version value*/
133 
134  std::string value = std::string();
135  for(int i = 0 ; isdigit(line.at(found + fieldInfoDelimiter.size() + i)) ; i++){
136  char digit = line.at(found + fieldInfoDelimiter.size() + i);
137  std::stringstream ss;
138  ss << digit;
139  std::string tmp;
140  ss >> tmp;
141  value.append(tmp);
142  }
143 
144  if(value.size() == 0){/*checks if version value is present in the file*/
145  silent_cerr("Error while reading " << filePath << ": " << " missing value of " << currentVersionLabel << " at line '" << line.substr(0, line.size()-1) << "'" << std::endl);
147  }
148 
149  std::stringstream tmpss1;
150  tmpss1 << value;
151  tmpss1 >> currentVersion; //stores the acquired value inside of FGNetFDMCurVersion/FGNetCtrlsCurVersion
152 
153  /*reads all of the other fields*/
154 
155  int fieldPosition = 1; /*used to register every field with its proper position*/
156  do{
157  std::getline(infile, line);
158  if(!infile.eof()){
159 
160  /*reads field name*/
161 
162  std::string fieldName; /*stores the name of field read from the file*/
163  found = line.find(fieldNameDelimiter); /*searches for name delimiter in order to acquire field name*/
164  if(found == std::string::npos){/*checks if delimiter is missing*/
165  silent_cerr("Error while reading " << filePath << ": " << "delimiter '" << fieldNameDelimiter << "' not found at line '" << line.substr(0,line.size()-1) << "'" << std::endl);
167  }
168  fieldName = line.substr(0, found); /*collects only the part of the current line containing the field name*/
169  found = line.find(fieldInfoDelimiter);/*ex: eng_state: type, size, offset = unsigned int [4], 16, 124 finds where '= ' is located*/
170  if(found == std::string::npos){
171  silent_cerr("Error while reading " << filePath << ": " << "delimiter '" << fieldInfoDelimiter << "' not found for field '" << fieldName << "'" << std::endl);
173  }
174  std::string fieldInfoRawString = line.substr(line.find(fieldInfoDelimiter) + fieldInfoDelimiter.size(), line.size()); //ex: "unsigned int [4], 16, 124"
175 
176  /*reads field type*/
177 
178  found = fieldInfoRawString.find(openSquareBracket);
179  int fieldNumOfElem; //store how many elements that field has (ex array fields will have fieldNumOfElem > 1)
180  std::string typeFullName;
181  if(found != std::string::npos){/*field is an array: '[' found inside of the current line*/
182  /*reads the number inside of []*/
183  value = std::string();
184  for(int i = 0 ; isdigit(fieldInfoRawString.at(found + openSquareBracket.size() + i)) ; i++){
185  char digit = fieldInfoRawString.at(found + openSquareBracket.size() + i);
186  std::stringstream ss;
187  ss << digit;
188  std::string tmp;
189  ss >> tmp;
190  value.append(tmp);
191  }
192  if(value.size() == 0){/*checks if [] are empty*/
193  silent_cerr("Error while reading " << filePath << ": " << " empty brackets for field '" << fieldName << "' at line '" << line.substr(0, line.size()-1) << "'" << std::endl);
195  }
196  std::stringstream tmpss2;
197  tmpss2 << value;
198  tmpss2 >> fieldNumOfElem;
199 
200  typeFullName = fieldInfoRawString.substr(0, found-1); //ex: gets "unsigned int" from current line*/
201  found = fieldInfoRawString.find(fieldInfoSeparator); //finds the first comma
202  }else{
203  fieldNumOfElem = 1; /*the current field is a single-variable field*/
204  found = fieldInfoRawString.find(fieldInfoSeparator); //finds the first comma
205  if(found != std::string::npos){
206  typeFullName = fieldInfoRawString.substr(0, found);
207  }
208  }
209 
210  /*checks if both info separators ',' are missing*/
211  if(found == std::string::npos){
212  silent_cerr("Error while reading " << filePath << ": " << "both info separators '" <<fieldInfoSeparator << "' missing for field '" << fieldName << "' at line '" << line.substr(0, line.size()-1) << "'" << std::endl);
214  }
215 
216  /*checks if one info separator ',' are missing*/
217  std::string tmp = fieldInfoRawString.substr(found+1, fieldInfoRawString.size());
218  if(tmp.find(fieldInfoSeparator) == std::string::npos){
219  silent_cerr("Error while reading " << filePath << ": " << "missing info separator '" <<fieldInfoSeparator << "' for field '" << fieldName << "' at line '" << line.substr(0, line.size()-1) << "'" << std::endl);
221  }
222 
223  std::string sizeAndOffsetRawString = fieldInfoRawString.substr(found+1, fieldInfoRawString.size()); /*ex: got " 16, 124" */
224  found = sizeAndOffsetRawString.find(fieldInfoSeparator); /*gets second comma in the current line (between size and offset)*/
225 
226  /*reads offset*/
227  int offset;
228  value = std::string();
229  for(int i = 0 ; isdigit(sizeAndOffsetRawString.at(found+2+i)) && found+2+i < sizeAndOffsetRawString.size() ; i++){
230  char digit = sizeAndOffsetRawString.at(found+2+i);
231  std::stringstream ss;
232  ss << digit;
233  std::string tmp;
234  ss >> tmp;
235  value.append(tmp);
236  }
237 
238  if(value.size() == 0){/*checks if offset is missing*/
239  silent_cerr("Error while reading " << filePath << ": " << " missing offset for field '" << fieldName << "' at line '" << line.substr(0, line.size()-1) << "'" << std::endl);
241  }
242 
243  std::stringstream tmpss3;
244  tmpss3 << value;
245  tmpss3 >> offset;
246 
247  /*once all information has been acquired, field is registered inside of fieldsDescriptionFG*/
248 
249  for(int i = 0 ; i < fieldNumOfElem ; i++){//creates 'fieldNumOfElem' entries for the current field
250  std::string label = std::string();
251  std::string finalFieldName = std::string(fieldName);
252 
253  if(fieldNumOfElem > 1){
254  label = std::string("_");
255  std::string num;
256  std::stringstream convert;
257  convert << i+1;
258  num = convert.str();
259 
260  if(fieldNumOfElem < 10){
261  label.append("0");
262  }
263 
264  label.append(num);
265  }
266  finalFieldName.append(label);
267 
268  if(typeFullName.compare("unsigned int") == 0){
269  fieldsDescriptionFG.insert(FieldsDescriptionFG::value_type(finalFieldName,{typeid(uint32_t),sizeof(uint32_t),fieldPosition,offset+sizeof(uint32_t)*i}));
270  }else if(typeFullName.compare("int") == 0){
271  fieldsDescriptionFG.insert(FieldsDescriptionFG::value_type(finalFieldName,{typeid(int32_t),sizeof(int32_t),fieldPosition,offset+sizeof(int32_t)*i}));
272  }else if(typeFullName.compare("float") == 0){
273  fieldsDescriptionFG.insert(FieldsDescriptionFG::value_type(finalFieldName,{typeid(float),sizeof(float),fieldPosition,offset+sizeof(float)*i}));
274  }else if(typeFullName.compare("double") == 0){
275  fieldsDescriptionFG.insert(FieldsDescriptionFG::value_type(finalFieldName,{typeid(double),sizeof(double),fieldPosition,offset+sizeof(double)*i}));
276  }else{
277  silent_cerr("Error while reading " << filePath << ": " << " unknown type for field '" << fieldName << "' at line '" << line.substr(0, line.size()-1) << "'" << std::endl);
279  }
280 
281  fieldPosition++;
282  }
283  }else if(fieldPosition == 1){
284  silent_cerr("Error while reading " << filePath << ": " << " file does not contain any field description" << std::endl);
286  }
287  }while(!infile.eof());
288 
289  infile.close();
290 }
291 
292 void printOptionsOnTextFile(const char * fileName, FieldsDescriptionFG &fieldsDescriptionFG){
293  std::ofstream outFile;
294  outFile.open(fileName);
295 
296  if(!outFile.is_open()){
297  silent_cerr("Error while writing on file: " << fileName << ", impossible to open it" << std::endl);
299  }
300 
301  for(int i = 0 ; i < (int)fieldsDescriptionFG.size() ; i++){
302  for(FieldsDescriptionFG::iterator it = fieldsDescriptionFG.begin() ; it != fieldsDescriptionFG.end() ; it++){
303  if(it->second.position == i+1){
304  outFile << it->first << std::endl;
305  }
306  }
307  }
308 
309  outFile.close();
310  }
311 
312 void buildFGBufCast(std::vector<BufCast *>& data, FieldsDescriptionFG &fieldsDescriptionFGInUse){
313  TypeMap_t swapmap;
314  SwapMapInit(swapmap);
315 
316  //every type must be reversed for FG communication! (FG expects big-endian format data)
317  if(bIsLittleEndian()){
318  for(TypeMap_t::iterator i = swapmap.begin() ; i != swapmap.end() ; i++){
319  i->second = true;
320  }
321  }
322 
323  for (FieldsDescriptionFG::iterator it = fieldsDescriptionFGInUse.begin() ; it != fieldsDescriptionFGInUse.end() ; it++){
324  data[it->second.position-1] = buildOneFGBufCast(it->second.offset, swapmap, it->second.type);
325  }
326  }
327 
328 BufCast *buildOneFGBufCast(size_t& offset, TypeMap_t& swapmap, const std::type_info &fieldType){
329  BufCast *pBC(0);
330 
331  if (fieldType == typeid(int8_t)) {
332  TypeMap_t::const_iterator i = swapmap.find(typeid(int8_t).name());
333  if (i->second) {
334  pBC = new TBufCastHToN<int8_t>(offset);
335  } else {
336  pBC = new TBufCast<int8_t>(offset);
337  }
338 
339  } else if (fieldType == typeid(uint8_t)) {
340  TypeMap_t::const_iterator i = swapmap.find(typeid(uint8_t).name());
341  if (i->second) {
342  pBC = new TBufCastHToN<uint8_t>(offset);
343  } else {
344  pBC = new TBufCast<uint8_t>(offset);
345  }
346 
347  } else if (fieldType == typeid(int16_t)) {
348  TypeMap_t::const_iterator i = swapmap.find(typeid(int16_t).name());
349  if (i->second) {
350  pBC = new TBufCastHToN<int16_t>(offset);
351  } else {
352  pBC = new TBufCast<int16_t>(offset);
353  }
354 
355  } else if (fieldType == typeid(uint16_t)) {
356  TypeMap_t::const_iterator i = swapmap.find(typeid(uint16_t).name());
357  if (i->second) {
358  pBC = new TBufCastHToN<uint16_t>(offset);
359  } else {
360  pBC = new TBufCast<uint16_t>(offset);
361  }
362 
363  } else if (fieldType == typeid(int32_t)) {
364  TypeMap_t::const_iterator i = swapmap.find(typeid(int32_t).name());
365  if (i->second) {
366  pBC = new TBufCastHToN<int32_t>(offset);
367  } else {
368  pBC = new TBufCast<int32_t>(offset);
369  }
370 
371  } else if (fieldType == typeid(uint32_t)) {
372  TypeMap_t::const_iterator i = swapmap.find(typeid(uint32_t).name());
373  if (i->second) {
374  pBC = new TBufCastHToN<uint32_t>(offset);
375  } else {
376  pBC = new TBufCast<uint32_t>(offset);
377  }
378 
379  } else if (fieldType == typeid(float)) {
380  TypeMap_t::const_iterator i = swapmap.find(typeid(float).name());
381  if (i->second) {
382  pBC = new TBufCastHToN<float>(offset);
383  } else {
384  pBC = new TBufCast<float>(offset);
385  }
386 
387  } else if (fieldType == typeid(double)) {
388  TypeMap_t::const_iterator i = swapmap.find(typeid(double).name());
389  if (i->second) {
390  pBC = new TBufCastHToN<double>(offset);
391  } else {
392  pBC = new TBufCast<double>(offset);
393  }
394 
395  }
396 
397  return pBC;
398  }
#define MBDYN_EXCEPT_ARGS
Definition: except.h:63
void SwapMapInit(TypeMap_t &swapmap)
Definition: bufmod.cc:266
bool setFileDriveCallerType(const char *name, FileDriveCallerTypeReader *rf)
Definition: drive_.cc:2920
void printOptionsOnTextFile(const char *fileName, FieldsDescriptionFG &fieldsDescriptionFG)
void buildFGBufCast(std::vector< BufCast * > &data, FieldsDescriptionFG &fieldsDescriptionFGInUse)
bool SetStreamOutputContentType(const char *name, StreamOutputContentTypeReader *rf)
void readFGStructuresFromFile(const char *filePath, std::string currentVersionLabel, FieldsDescriptionFG &fieldsDescriptionFG, int &currentVersion)
FGNetCtrlsWordSet fGNetCtrlsWordSet
bool SetFileDriveContentType(const char *name, FileDriveContentTypeReader *rf)
int FGNetCtrlsCurVersion
bool bIsLittleEndian(void)
Definition: bufmod.cc:259
int module_init(const char *module_name, void *pdm, void *php)
This function registers our user defined element for the math parser.
int FGNetFDMCurVersion
std::map< std::string, bool > TypeMap_t
Definition: bufmod.h:37
FieldsDescriptionFG fieldsDescriptionFGNetCtrls
void buildFieldsDescriptionFG(void)
FGNetFDMWordSet fGNetFDMWordSet
BufCast * buildOneFGBufCast(size_t &offset, TypeMap_t &swapmap, const std::type_info &fieldType)
FieldsDescriptionFG fieldsDescriptionFGNetFDM
static std::stack< const HighParser * > pHP
Definition: parser.cc:598
std::map< std::string, FieldInfo > FieldsDescriptionFG
Definition: bufmod.h:42