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 #include "ncd_parser/ncd_parser.h"
00031
00032 int main(int argc, char** argv)
00033 {
00034 if(argc != 4)
00035 {
00036 printf("usage is `rosrun ncd_parser ncd_parser filename.alog`\n");
00037 return 1;
00038 }
00039
00040 ros::init (argc, argv, "ncd_parser");
00041 NCDParser parser(argv[1]);
00042 sleep(2);
00043 parser.launch();
00044 return 0;
00045 }
00046
00047 NCDParser::NCDParser(char* filename):filename_(filename)
00048 {
00049 ROS_INFO ("Starting NCDParser");
00050
00051 ros::NodeHandle nh;
00052 ros::NodeHandle nh_private ("~");
00053
00054 createOdomToLeftLaserTf();
00055 createOdomToRightLaserTf();
00056 lastTime_ = -1;
00057
00058
00059
00060 if (!nh_private.getParam ("start", start_))
00061 start_ = 0.0;
00062 if (!nh_private.getParam ("end", end_))
00063 end_ = -1;
00064 if (!nh_private.getParam ("rate", rate_))
00065 rate_ = 1.0;
00066
00067 if (rate_ == 0) ROS_FATAL("rate parameter cannot be 0");
00068
00069
00070
00071 leftLaserPublisher_ = nh.advertise<sensor_msgs::LaserScan>("scan", 100);
00072 rightLaserPublisher_ = nh.advertise<sensor_msgs::LaserScan>("scan", 100);
00073 }
00074
00075 NCDParser::~NCDParser()
00076 {
00077 ROS_INFO ("Shutting down NCDParser");
00078 }
00079
00080 void NCDParser::launch()
00081 {
00082 std::ifstream aLogFile;
00083 aLogFile.open(filename_);
00084
00085 if(!aLogFile.is_open())
00086 ROS_FATAL("Could not open %s\n", filename_);
00087
00088 int lineCounter = 0;
00089 std::string line;
00090
00091
00092
00093 for (int i = 0; i < 210; i++)
00094 {
00095 getline(aLogFile, line);
00096 lineCounter++;
00097 }
00098
00099
00100
00101 while (getline(aLogFile, line))
00102 {
00103 lineCounter++;
00104 std::vector<std::string> tokens;
00105 tokenize(line, tokens, " ");
00106
00107
00108 if (tokens.size() < 4) continue;
00109
00110
00111 if (strtod(tokens[0].c_str(), NULL) <= start_) continue;
00112
00113
00114 if (strtod(tokens[0].c_str(), NULL) > end_ && end_ != -1)
00115 {
00116 std::cout << strtod(tokens[0].c_str(), NULL) << ", " << end_ << std::endl;
00117 ROS_INFO("Reached specified end time.");
00118 break;
00119 }
00120
00121
00122 if (tokens[1].compare("LMS_LASER_2D_LEFT") == 0)
00123 publishLaserMessage(tokens, leftLaserFrame_, leftLaserPublisher_);
00124 else if (tokens[1].compare("LMS_LASER_2D_RIGHT") == 0)
00125 publishLaserMessage(tokens, rightLaserFrame_, rightLaserPublisher_);
00126 else if (tokens[1].compare("ODOMETRY_POSE") == 0)
00127 publishTfMessages(tokens);
00128 else
00129 continue;
00130
00131
00132
00133 double time = extractValue(tokens[3], "time=");
00134
00135 if(lastTime_ == -1) lastTime_ = time;
00136 else
00137 {
00138 ros::Duration d = (ros::Time(time) - ros::Time(lastTime_)) * ( 1.0 / rate_);
00139 lastTime_ = time;
00140 if (d.toNSec() > 0) d.sleep();
00141 }
00142 }
00143 }
00144
00145 void NCDParser::publishLaserMessage(const std::vector<std::string>& tokens,
00146 const std::string& laserFrame,
00147 const ros::Publisher& publisher)
00148 {
00149 ROS_DEBUG("Laser message");
00150
00151 sensor_msgs::LaserScan scan;
00152
00153 double time = extractValue(tokens[3], "time=");
00154
00155 scan.header.stamp = ros::Time(time);
00156 scan.header.frame_id = laserFrame;
00157
00158 scan.angle_min = extractValue(tokens[3], "minAngle=") * DEG_TO_RAD;
00159 scan.angle_max = extractValue(tokens[3], "maxAngle=") * DEG_TO_RAD;
00160 scan.angle_increment = extractValue(tokens[3], "angRes=") * DEG_TO_RAD;
00161 scan.range_min = RANGE_MIN;
00162 scan.range_max = RANGE_MAX;
00163 scan.ranges = extractArray(tokens[3], "Range=[181]");
00164 scan.intensities = extractArray(tokens[3], "Reflectance=[181]");
00165
00166 publisher.publish(scan);
00167 }
00168
00169 void NCDParser::publishTfMessages(const std::vector<std::string>& tokens)
00170 {
00171 ROS_DEBUG("Tf message");
00172
00173
00174 double time = extractValue(tokens[3], "time=");
00175
00176
00177 std::vector<float> xytheta = extractArray(tokens[3], "Pose=[3x1]");
00178 double x = xytheta[0];
00179 double y = xytheta[1];
00180 double z = 0.0;
00181 double theta = xytheta[2];
00182
00183
00184 double pitch = extractValue(tokens[3], "Pitch=");
00185
00186
00187 double roll = extractValue(tokens[3], "Roll=");
00188
00189 tf::Quaternion rotation;
00190 rotation.setRPY (roll, pitch, theta);
00191 worldToOdom_.setRotation (rotation);
00192
00193 tf::Vector3 origin;
00194 origin.setValue (x, y, z);
00195 worldToOdom_.setOrigin (origin);
00196
00197 tf::StampedTransform worldToOdomStamped(worldToOdom_, ros::Time(time), worldFrame_, odomFrame_);
00198 tfBroadcaster_.sendTransform(worldToOdomStamped);
00199
00200 tf::StampedTransform odomToLeftLaserStamped(odomToLeftLaser_, ros::Time(time), odomFrame_, leftLaserFrame_);
00201 tfBroadcaster_.sendTransform(odomToLeftLaserStamped);
00202
00203 tf::StampedTransform odomToRightLaserStamped(odomToRightLaser_, ros::Time(time), odomFrame_, rightLaserFrame_);
00204 tfBroadcaster_.sendTransform(odomToRightLaserStamped);
00205 }
00206
00207 void NCDParser::tokenize (const std::string& str,
00208 std::vector <std::string> &tokens,
00209 std::string sentinel)
00210 {
00211 std::string::size_type lastPos = str.find_first_not_of (sentinel, 0);
00212 std::string::size_type pos = str.find_first_of (sentinel, lastPos);
00213
00214 while (std::string::npos != pos || std::string::npos != lastPos)
00215 {
00216 std::string stringToken = str.substr (lastPos, pos - lastPos);
00217 tokens.push_back (stringToken);
00218 lastPos = str.find_first_not_of (sentinel, pos);
00219 pos = str.find_first_of (sentinel, lastPos);
00220 }
00221 }
00222
00223 std::vector<float> NCDParser::extractArray(std::string s, std::string pattern)
00224 {
00225 int n0 = s.find(pattern);
00226 int n1 = s.find("{", n0);
00227 int n2 = s.find("}", n1);
00228 std::string valueList = s.substr(n1+1, n2-n1-1);
00229
00230 std::vector<float> values;
00231 std::vector<std::string> s_values;
00232 tokenize(valueList, s_values, ",");
00233
00234 for (unsigned int i = 0; i < s_values.size(); i++)
00235 values.push_back(strtod(s_values[i].c_str(), NULL));
00236
00237 return values;
00238 }
00239
00240 double NCDParser::extractValue(std::string s, std::string pattern)
00241 {
00242 int n1 = s.find(pattern);
00243 int n2 = s.find(",", n1);
00244 std::string s_value = s.substr(n1+pattern.length(), n2-n1-pattern.length());
00245 return strtod(s_value.c_str(), NULL);
00246 }
00247
00248
00249 void NCDParser::createOdomToLeftLaserTf()
00250 {
00251 double x = -0.270;
00252 double y = -0.030;
00253 double z = 0.495;
00254 double roll = 180.0 * DEG_TO_RAD;
00255 double pitch = 90.0 * DEG_TO_RAD;
00256 double yaw = -90.0 * DEG_TO_RAD;
00257
00258 tf::Quaternion rotation;
00259 rotation.setRPY (roll, pitch, yaw);
00260 odomToLeftLaser_.setRotation (rotation);
00261
00262 tf::Vector3 origin;
00263 origin.setValue (x, y, z);
00264 odomToLeftLaser_.setOrigin (origin);
00265 }
00266
00267 void NCDParser::createOdomToRightLaserTf()
00268 {
00269 double x = 0.270;
00270 double y = -0.030;
00271 double z = 0.495;
00272 double roll = 90.0 * DEG_TO_RAD;
00273 double pitch = -90.0 * DEG_TO_RAD;
00274 double yaw = 180.0 * DEG_TO_RAD;
00275
00276 tf::Quaternion rotation;
00277 rotation.setRPY (roll, pitch, yaw);
00278 odomToRightLaser_.setRotation (rotation);
00279
00280 tf::Vector3 origin;
00281 origin.setValue (x, y, z);
00282 odomToRightLaser_.setOrigin (origin);
00283 }