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