00001
00010 #include "hrpsys/util/Hrpsys.h"
00011 #include "hrpsys/idl/pointcloud.hh"
00012 #include "hrpsys/idl/RobotHardwareService.hh"
00013 #include "DataLogger.h"
00014
00015
00016 typedef coil::Guard<coil::Mutex> Guard;
00017
00018
00019
00020 static const char* nullcomponent_spec[] =
00021 {
00022 "implementation_id", "DataLogger",
00023 "type_name", "DataLogger",
00024 "description", "data logger component",
00025 "version", HRPSYS_PACKAGE_VERSION,
00026 "vendor", "AIST",
00027 "category", "example",
00028 "activity_type", "DataFlowComponent",
00029 "max_instance", "10",
00030 "language", "C++",
00031 "lang_type", "compile",
00032
00033 "conf.default.log_precision", "0",
00034 ""
00035 };
00036
00037
00038 #define LOG_SET_PRECISION(strm) \
00039 int prc; \
00040 if (precision != 0) { \
00041 prc = os.precision(); \
00042 os << std::scientific << std::setprecision(precision); \
00043 } \
00044
00045 #define LOG_UNSET_PRECISION(strm) \
00046 if (precision != 0) \
00047 os << std::fixed << std::setprecision(prc); \
00048
00049 void printData(std::ostream& os, const RTC::Acceleration3D& data, unsigned int precision = 0)
00050 {
00051 LOG_SET_PRECISION(os);
00052 os << data.ax << " " << data.ay << " " << data.az << " ";
00053 LOG_UNSET_PRECISION(os);
00054 }
00055
00056 void printData(std::ostream& os, const RTC::Velocity2D& data, unsigned int precision = 0)
00057 {
00058 LOG_SET_PRECISION(os);
00059 os << data.vx << " " << data.vy << " " << data.va << " ";
00060 LOG_UNSET_PRECISION(os);
00061 }
00062
00063 void printData(std::ostream& os, const RTC::Pose3D& data, unsigned int precision = 0)
00064 {
00065 LOG_SET_PRECISION(os);
00066 os << data.position.x << " " << data.position.y << " "
00067 << data.position.z << " " << data.orientation.r << " "
00068 << data.orientation.p << " " << data.orientation.y << " ";
00069 LOG_UNSET_PRECISION(os);
00070 }
00071
00072 void printData(std::ostream& os, const RTC::AngularVelocity3D& data, unsigned int precision = 0)
00073 {
00074 LOG_SET_PRECISION(os);
00075 os << data.avx << " " << data.avy << " " << data.avz << " ";
00076 LOG_UNSET_PRECISION(os);
00077 }
00078
00079 void printData(std::ostream& os, const RTC::Point3D& data, unsigned int precision = 0)
00080 {
00081 LOG_SET_PRECISION(os);
00082 os << data.x << " " << data.y << " " << data.z << " ";
00083 LOG_UNSET_PRECISION(os);
00084 }
00085
00086 void printData(std::ostream& os, const RTC::Orientation3D& data, unsigned int precision = 0)
00087 {
00088 LOG_SET_PRECISION(os);
00089 os << data.r << " " << data.p << " " << data.y << " ";
00090 LOG_UNSET_PRECISION(os);
00091 }
00092
00093 void printData(std::ostream& os, const PointCloudTypes::PointCloud& data, unsigned int precision = 0)
00094 {
00095 uint npoint = data.data.length()/data.point_step;
00096 os << data.width << " " << data.height << " " << data.type << " " << npoint;
00097 float *ptr = (float *)data.data.get_buffer();
00098 std::string type(data.type);
00099 if (type != "xyz" && type != "xyzrgb"){
00100 std::cerr << "point cloud type(" << type << ") is not supported"
00101 << std::endl;
00102 return;
00103 }
00104 for (uint i=0; i<npoint ;i++){
00105 os << " " << *ptr++ << " " << *ptr++ << " " << *ptr++;
00106 if (type == "xyzrgb"){
00107 unsigned char *rgb = (unsigned char *)ptr;
00108 os << " " << (int)rgb[0] << " " << (int)rgb[1] << " " << (int)rgb[2];
00109 ptr++;
00110 }
00111 }
00112 }
00113
00114 template<class T>
00115 std::ostream& operator<<(std::ostream& os, const _CORBA_Unbounded_Sequence<T > & data)
00116 {
00117 for (unsigned int j=0; j<data.length(); j++){
00118 os << data[j] << " ";
00119 }
00120 return os;
00121 }
00122
00123 std::ostream& operator<<(std::ostream& os, const OpenHRP::RobotHardwareService::DblSequence6 & data)
00124 {
00125 for (unsigned int j=0; j<data.length(); j++){
00126 os << data[j] << " ";
00127 }
00128 return os;
00129 }
00130
00131 std::ostream& operator<<(std::ostream& os, const OpenHRP::RobotHardwareService::DblSequence3 & data)
00132 {
00133 for (unsigned int j=0; j<data.length(); j++){
00134 os << data[j] << " ";
00135 }
00136 return os;
00137 }
00138
00139 std::ostream& operator<<(std::ostream& os, const OpenHRP::RobotHardwareService::BatteryState & data)
00140 {
00141 os << data.voltage << " " << data.current << " " << data.soc << " ";
00142 return os;
00143 }
00144
00145 template <class T>
00146 void printData(std::ostream& os, const T& data, unsigned int precision = 0)
00147 {
00148 LOG_SET_PRECISION(os);
00149 for (unsigned int j=0; j<data.length(); j++){
00150 os << data[j] << " ";
00151 }
00152 LOG_UNSET_PRECISION(os);
00153 }
00154
00155 void printData(std::ostream& os, double data, unsigned int precision = 0)
00156 {
00157 LOG_SET_PRECISION(os);
00158 os << data << " ";
00159 LOG_UNSET_PRECISION(os);
00160 }
00161
00162 void printData(std::ostream& os, const OpenHRP::RobotHardwareService::RobotState2& data, unsigned int precision = 0)
00163 {
00164 printData(os, data.angle, precision);
00165 printData(os, data.command, precision);
00166 printData(os, data.torque, precision);
00167 printData(os, data.servoState, precision);
00168 printData(os, data.force, precision);
00169 printData(os, data.rateGyro, precision);
00170 printData(os, data.accel, precision);
00171 printData(os, data.batteries, precision);
00172 printData(os, data.voltage, precision);
00173 printData(os, data.current, precision);
00174 printData(os, data.temperature, precision);
00175 }
00176
00177 template <class T>
00178 class LoggerPort : public LoggerPortBase
00179 {
00180 public:
00181 LoggerPort(const char *name) : m_port(name, m_data) {}
00182 const char *name(){
00183 return m_port.name();
00184 }
00185 virtual void dumpLog(std::ostream& os, unsigned int precision = 0){
00186 os.setf(std::ios::fixed, std::ios::floatfield);
00187 for (unsigned int i=0; i<m_log.size(); i++){
00188 printLog(os, m_log[i], precision);
00189 }
00190 }
00191 void printLog(std::ostream& os, T &data, unsigned int precision = 0){
00192 os << std::setprecision(6) << (data.tm.sec + data.tm.nsec/1e9) << " ";
00193
00194 printData(os, data.data, precision);
00195 os << std::endl;
00196 }
00197 InPort<T>& port(){
00198 return m_port;
00199 }
00200 void log(){
00201 if (m_port.isNew()){
00202 m_port.read();
00203 m_log.push_back(m_data);
00204 while (m_log.size() > m_maxLength){
00205 m_log.pop_front();
00206 }
00207 }
00208 }
00209 void clear(){
00210 m_log.clear();
00211 }
00212 protected:
00213 InPort<T> m_port;
00214 T m_data;
00215 std::deque<T> m_log;
00216 };
00217
00218 class LoggerPortForPointCloud : public LoggerPort<PointCloudTypes::PointCloud>
00219 {
00220 public:
00221 LoggerPortForPointCloud(const char *name) : LoggerPort<PointCloudTypes::PointCloud>(name) {}
00222 void dumpLog(std::ostream& os, unsigned int precision = 0){
00223 os.setf(std::ios::fixed, std::ios::floatfield);
00224 for (unsigned int i=0; i<m_log.size(); i++){
00225
00226 os << std::setprecision(6) << (m_log[i].tm.sec + m_log[i].tm.nsec/1e9) << " ";
00227
00228 printData(os, m_log[i], precision);
00229 os << std::endl;
00230 }
00231 }
00232 };
00233
00234 DataLogger::DataLogger(RTC::Manager* manager)
00235 : RTC::DataFlowComponentBase(manager),
00236
00237 m_emergencySignalIn("emergencySignal", m_emergencySignal),
00238 m_DataLoggerServicePort("DataLoggerService"),
00239
00240 m_suspendFlag(false),
00241 m_log_precision(0),
00242 dummy(0)
00243 {
00244 m_service0.setLogger(this);
00245 }
00246
00247 DataLogger::~DataLogger()
00248 {
00249 }
00250
00251
00252
00253 RTC::ReturnCode_t DataLogger::onInitialize()
00254 {
00255 std::cerr << "[" << m_profile.instance_name << "] onInitialize()" << std::endl;
00256 bindParameter("log_precision", m_log_precision, "0");
00257
00258
00259
00260
00261 addInPort("emergencySignal", m_emergencySignalIn);
00262
00263
00264
00265
00266 m_DataLoggerServicePort.registerProvider("service0", "DataLoggerService", m_service0);
00267
00268
00269
00270
00271 addPort(m_DataLoggerServicePort);
00272
00273
00274
00275
00276
00277
00278
00279 return RTC::RTC_OK;
00280 }
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305 RTC::ReturnCode_t DataLogger::onActivated(RTC::UniqueId ec_id)
00306 {
00307 return RTC::RTC_OK;
00308 }
00309
00310 RTC::ReturnCode_t DataLogger::onDeactivated(RTC::UniqueId ec_id)
00311 {
00312 return RTC::RTC_OK;
00313 }
00314
00315 RTC::ReturnCode_t DataLogger::onExecute(RTC::UniqueId ec_id)
00316 {
00317 if (ec_id == 0){
00318 if (m_emergencySignalIn.isNew()){
00319 m_emergencySignalIn.read();
00320 time_t sec = time(NULL);
00321 struct tm *tm_ = localtime(&sec);
00322 char date[20];
00323 strftime(date,20, "%Y-%m-%d", tm_);
00324 char basename[30];
00325 sprintf(basename, "emglog-%s-%02d%02d",
00326 date, tm_->tm_hour, tm_->tm_min);
00327 std::cout << "received emergency signal. saving log files("
00328 << basename << ")" << std::endl;
00329 save(basename);
00330 while (m_emergencySignalIn.isNew()){
00331 m_emergencySignalIn.read();
00332 }
00333 }
00334 }else{
00335 Guard guard(m_suspendFlagMutex);
00336
00337 if (m_suspendFlag) return RTC::RTC_OK;
00338
00339 for (unsigned int i=0; i<m_ports.size(); i++){
00340 m_ports[i]->log();
00341 }
00342 }
00343 return RTC::RTC_OK;
00344 }
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381 bool DataLogger::add(const char *i_type, const char *i_name)
00382 {
00383 suspendLogging();
00384 for (unsigned int i=0; i<m_ports.size(); i++){
00385 if (strcmp(m_ports[i]->name(),i_name) == 0){
00386 std::cerr << "Logger port named \"" << i_name << "\" already exists"
00387 << std::endl;
00388 resumeLogging();
00389 return false;
00390 }
00391 }
00392
00393 LoggerPortBase *new_port=NULL;
00394 if (strcmp(i_type, "TimedDoubleSeq")==0){
00395 LoggerPort<TimedDoubleSeq> *lp = new LoggerPort<TimedDoubleSeq>(i_name);
00396 new_port = lp;
00397 if (!addInPort(i_name, lp->port())) {
00398 resumeLogging();
00399 return false;
00400 }
00401 }else if (strcmp(i_type, "TimedLongSeq")==0){
00402 LoggerPort<TimedLongSeq> *lp = new LoggerPort<TimedLongSeq>(i_name);
00403 new_port = lp;
00404 if (!addInPort(i_name, lp->port())) {
00405 resumeLogging();
00406 return false;
00407 }
00408 }else if (strcmp(i_type, "TimedBooleanSeq")==0){
00409 LoggerPort<TimedBooleanSeq> *lp = new LoggerPort<TimedBooleanSeq>(i_name);
00410 new_port = lp;
00411 if (!addInPort(i_name, lp->port())) {
00412 resumeLogging();
00413 return false;
00414 }
00415 }else if (strcmp(i_type, "TimedLongSeqSeq")==0){
00416 LoggerPort<OpenHRP::TimedLongSeqSeq> *lp = new LoggerPort<OpenHRP::TimedLongSeqSeq>(i_name);
00417 new_port = lp;
00418 if (!addInPort(i_name, lp->port())) {
00419 resumeLogging();
00420 return false;
00421 }
00422 }else if (strcmp(i_type, "TimedPoint3D")==0){
00423 LoggerPort<TimedPoint3D> *lp = new LoggerPort<TimedPoint3D>(i_name);
00424 new_port = lp;
00425 if (!addInPort(i_name, lp->port())) {
00426 resumeLogging();
00427 return false;
00428 }
00429 }else if (strcmp(i_type, "TimedOrientation3D")==0){
00430 LoggerPort<TimedOrientation3D> *lp = new LoggerPort<TimedOrientation3D>(i_name);
00431 new_port = lp;
00432 if (!addInPort(i_name, lp->port())) {
00433 resumeLogging();
00434 return false;
00435 }
00436 }else if (strcmp(i_type, "TimedAcceleration3D")==0){
00437 LoggerPort<TimedAcceleration3D> *lp = new LoggerPort<TimedAcceleration3D>(i_name);
00438 new_port = lp;
00439 if (!addInPort(i_name, lp->port())) {
00440 resumeLogging();
00441 return false;
00442 }
00443 }else if (strcmp(i_type, "TimedAngularVelocity3D")==0){
00444 LoggerPort<TimedAngularVelocity3D> *lp = new LoggerPort<TimedAngularVelocity3D>(i_name);
00445 new_port = lp;
00446 if (!addInPort(i_name, lp->port())) {
00447 resumeLogging();
00448 return false;
00449 }
00450 }else if (strcmp(i_type, "TimedVelocity2D")==0){
00451 LoggerPort<TimedVelocity2D> *lp = new LoggerPort<TimedVelocity2D>(i_name);
00452 new_port = lp;
00453 if (!addInPort(i_name, lp->port())) {
00454 resumeLogging();
00455 return false;
00456 }
00457 }else if (strcmp(i_type, "TimedPose3D")==0){
00458 LoggerPort<TimedPose3D> *lp = new LoggerPort<TimedPose3D>(i_name);
00459 new_port = lp;
00460 if (!addInPort(i_name, lp->port())) {
00461 resumeLogging();
00462 return false;
00463 }
00464 }else if (strcmp(i_type, "PointCloud")==0){
00465 LoggerPort<PointCloudTypes::PointCloud> *lp = new LoggerPortForPointCloud(i_name);
00466 new_port = lp;
00467 if (!addInPort(i_name, lp->port())) {
00468 resumeLogging();
00469 return false;
00470 }
00471 }else if (strcmp(i_type, "TimedRobotState2")==0){
00472 LoggerPort<OpenHRP::RobotHardwareService::TimedRobotState2> *lp = new LoggerPort<OpenHRP::RobotHardwareService::TimedRobotState2>(i_name);
00473 new_port = lp;
00474 if (!addInPort(i_name, lp->port())) {
00475 resumeLogging();
00476 return false;
00477 }
00478 }else{
00479 std::cout << "DataLogger: unsupported data type(" << i_type << ")"
00480 << std::endl;
00481 resumeLogging();
00482 return false;
00483 }
00484 m_ports.push_back(new_port);
00485 resumeLogging();
00486 return true;
00487 }
00488
00489 bool DataLogger::save(const char *i_basename)
00490 {
00491 suspendLogging();
00492 bool ret = true;
00493 for (unsigned int i=0; i<m_ports.size(); i++){
00494 std::string fname = i_basename;
00495 fname.append(".");
00496 fname.append(m_ports[i]->name());
00497 std::ofstream ofs(fname.c_str());
00498 if (ofs.is_open()){
00499 m_ports[i]->dumpLog(ofs, m_log_precision);
00500 }else{
00501 std::cerr << "[" << m_profile.instance_name << "] failed to open(" << fname << ")" << std::endl;
00502 ret = false;
00503 }
00504 }
00505 if (ret) std::cerr << "[" << m_profile.instance_name << "] Save log to " << i_basename << ".*" << std::endl;
00506 resumeLogging();
00507 return ret;
00508 }
00509
00510 bool DataLogger::clear()
00511 {
00512 suspendLogging();
00513 for (unsigned int i=0; i<m_ports.size(); i++){
00514 m_ports[i]->clear();
00515 }
00516 std::cerr << "[" << m_profile.instance_name << "] Log cleared" << std::endl;
00517 resumeLogging();
00518 return true;
00519 }
00520
00521 void DataLogger::suspendLogging()
00522 {
00523 Guard guard(m_suspendFlagMutex);
00524 m_suspendFlag = true;
00525 }
00526
00527 void DataLogger::resumeLogging()
00528 {
00529 Guard guard(m_suspendFlagMutex);
00530 m_suspendFlag = false;
00531 }
00532
00533 void DataLogger::maxLength(unsigned int len)
00534 {
00535 suspendLogging();
00536 for (unsigned int i=0; i<m_ports.size(); i++){
00537 m_ports[i]->maxLength(len);
00538 }
00539 std::cerr << "[" << m_profile.instance_name << "] Log max length is set to " << len << std::endl;
00540 resumeLogging();
00541 }
00542
00543 extern "C"
00544 {
00545
00546 void DataLoggerInit(RTC::Manager* manager)
00547 {
00548 RTC::Properties profile(nullcomponent_spec);
00549 manager->registerFactory(profile,
00550 RTC::Create<DataLogger>,
00551 RTC::Delete<DataLogger>);
00552 }
00553
00554 };
00555
00556