00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #ifndef RC_DYNAMICS_API_CSV_PRINTING_H_H
00038 #define RC_DYNAMICS_API_CSV_PRINTING_H_H
00039
00040 #include <string>
00041 #include <sstream>
00042 #include <iostream>
00043 #include <vector>
00044 #include <memory>
00045
00046 #include "rc_dynamics_api/msg_utils.h"
00047
00048 #include "roboception/msgs/frame.pb.h"
00049 #include "roboception/msgs/dynamics.pb.h"
00050 #include "roboception/msgs/imu.pb.h"
00051
00052 namespace csv {
00053
00054
00058 struct Header {
00059
00060 std::vector<std::string> _fields;
00061 std::string _prefix;
00062
00063 static Header
00064 prefixed(const std::string &p, const ::google::protobuf::Message &m)
00065 {
00066 Header header;
00067 header._prefix = p;
00068 return header << m;
00069 }
00070
00071 Header& operator <<(const std::string &field)
00072 {
00073 _fields.insert(std::end(_fields), _prefix + field);
00074 return *this;
00075 }
00076
00077 Header& operator <<(const Header &other)
00078 {
00079 for (auto&& f : other._fields)
00080 _fields.insert(std::end(_fields), _prefix + f);
00081 return *this;
00082 }
00083
00084 Header& operator <<(const ::google::protobuf::Message &m)
00085 {
00086 using namespace ::google::protobuf;
00087
00088 auto descr = m.GetDescriptor();
00089 auto refl = m.GetReflection();
00090 for (int i=0; i<descr->field_count(); ++i)
00091 {
00092 auto field = descr->field(i);
00093
00094 if (field->is_repeated())
00095 {
00096 int size = refl->FieldSize(m, field);
00097 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE)
00098 {
00099 for (int i=0; i<size; i++)
00100 {
00101 *this << prefixed(field->name() + '_' + std::to_string(i),
00102 refl->GetMessage(m, field));
00103 }
00104 } else {
00105 for (int i=0; i<size; i++)
00106 {
00107 *this << field->name() + "_" + std::to_string(i);
00108 }
00109 }
00110 }
00111 else if (!field->is_optional() || refl->HasField(m, field))
00112 {
00113 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE)
00114 {
00115 *this << prefixed(field->name() + '_', refl->GetMessage(m, field));
00116 } else {
00117 *this << field->name();
00118 }
00119 }
00120
00121 }
00122
00123 return *this;
00124 }
00125
00126 };
00127
00128
00132 struct Line
00133 {
00134 std::vector<std::string> _entries;
00135
00136
00137 Line& operator <<(const std::string &t)
00138 {
00139 this->_entries.insert(std::end(this->_entries), t);
00140 return *this;
00141 }
00142
00143 Line &operator<<(const ::google::protobuf::Message &m)
00144 {
00145 using namespace ::google::protobuf;
00146
00147 auto descr = m.GetDescriptor();
00148 auto refl = m.GetReflection();
00149 for (int i=0; i<descr->field_count(); ++i)
00150 {
00151 auto field = descr->field(i);
00152
00153 if (field->is_repeated())
00154 {
00155 int size = refl->FieldSize(m, field);
00156 switch (field->cpp_type()) {
00157 case FieldDescriptor::CPPTYPE_MESSAGE:
00158 for (int i=0; i<size;++i)
00159 {
00160 *this << refl->GetRepeatedMessage(m, field, i);
00161 }
00162 break;
00163 case FieldDescriptor::CPPTYPE_BOOL:
00164 for (int i=0; i<size;++i)
00165 {
00166 *this << std::to_string(refl->GetRepeatedBool(m, field, i));
00167 }
00168 break;
00169 case FieldDescriptor::CPPTYPE_ENUM:
00170 for (int i=0; i<size;++i)
00171 {
00172 *this << refl->GetRepeatedEnum(m, field, i)->name();
00173 }
00174 break;
00175 case FieldDescriptor::CPPTYPE_FLOAT:
00176 for (int i=0; i<size;++i)
00177 {
00178 *this << std::to_string(refl->GetRepeatedFloat(m, field, i));
00179 }
00180 break;
00181 case FieldDescriptor::CPPTYPE_DOUBLE:
00182 for (int i=0; i<size;++i)
00183 {
00184 *this << std::to_string(refl->GetRepeatedDouble(m, field, i));
00185 }
00186 break;
00187 case FieldDescriptor::CPPTYPE_UINT32:
00188 for (int i=0; i<size;++i)
00189 {
00190 *this << std::to_string(refl->GetRepeatedUInt32(m, field, i));
00191 }
00192 break;
00193 case FieldDescriptor::CPPTYPE_UINT64:
00194 for (int i=0; i<size;++i)
00195 {
00196 *this << std::to_string(refl->GetRepeatedUInt64(m, field, i));
00197 }
00198 break;
00199 case FieldDescriptor::CPPTYPE_INT32:
00200 for (int i=0; i<size;++i)
00201 {
00202 *this << std::to_string(refl->GetRepeatedInt32(m, field, i));
00203 }
00204 break;
00205 case FieldDescriptor::CPPTYPE_INT64:
00206 for (int i=0; i<size;++i)
00207 {
00208 *this << std::to_string(refl->GetRepeatedInt64(m, field, i));
00209 }
00210 break;
00211 case FieldDescriptor::CPPTYPE_STRING:
00212 for (int i=0; i<size;++i)
00213 {
00214 *this << refl->GetRepeatedString(m, field, i);
00215 }
00216 break;
00217 }
00218
00219 } else if (!field->is_optional() || refl->HasField(m, field))
00220 {
00221 switch (field->cpp_type()) {
00222 case FieldDescriptor::CPPTYPE_MESSAGE:
00223 *this << refl->GetMessage(m, field);
00224 break;
00225 case FieldDescriptor::CPPTYPE_BOOL:
00226 *this << std::to_string(refl->GetBool(m, field));
00227 break;
00228 case FieldDescriptor::CPPTYPE_ENUM:
00229 *this << refl->GetEnum(m, field)->name();
00230 break;
00231 case FieldDescriptor::CPPTYPE_FLOAT:
00232 *this << std::to_string(refl->GetFloat(m, field));
00233 break;
00234 case FieldDescriptor::CPPTYPE_DOUBLE:
00235 *this << std::to_string(refl->GetDouble(m, field));
00236 break;
00237 case FieldDescriptor::CPPTYPE_UINT32:
00238 *this << std::to_string(refl->GetUInt32(m, field));
00239 break;
00240 case FieldDescriptor::CPPTYPE_UINT64:
00241 *this << std::to_string(refl->GetUInt64(m, field));
00242 break;
00243 case FieldDescriptor::CPPTYPE_INT32:
00244 *this << std::to_string(refl->GetInt32(m, field));
00245 break;
00246 case FieldDescriptor::CPPTYPE_INT64:
00247 *this << std::to_string(refl->GetInt64(m, field));
00248 break;
00249 case FieldDescriptor::CPPTYPE_STRING:
00250 *this << refl->GetString(m, field);
00251 break;
00252 }
00253 }
00254 }
00255
00256 return *this;
00257 }
00258 };
00259
00260 }
00261
00262
00263
00264 std::ostream& operator <<(std::ostream& s, const csv::Header &header)
00265 {
00266 bool first = true;
00267 for (auto&& hf : header._fields)
00268 {
00269 if (first)
00270 s << hf;
00271 else
00272 s << "," << hf;
00273 first = false;
00274 }
00275 return s;
00276 }
00277
00278
00279
00280 std::ostream& operator<<(std::ostream& s, const csv::Line &csv)
00281 {
00282 bool first = true;
00283 for (auto&& e : csv._entries)
00284 {
00285 if (first)
00286 {
00287 s << e;
00288 } else {
00289 s << "," << e;
00290 }
00291 first = false;
00292 }
00293
00294 return s;
00295 }
00296
00297 #endif //RC_DYNAMICS_API_CSV_PRINTING_H_H