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 #include "rawlog_record_node.h"
00035 #include <boost/interprocess/sync/scoped_lock.hpp>
00036
00037 #include <mrpt_bridge/pose.h>
00038 #include <mrpt_bridge/laser_scan.h>
00039 #include <mrpt_bridge/marker_msgs.h>
00040 #include <mrpt_bridge/time.h>
00041
00042 #include <mrpt/version.h>
00043 using namespace mrpt::maps;
00044 using namespace mrpt::obs;
00045
00046 int main(int argc, char** argv)
00047 {
00048 ros::init(argc, argv, "rawlog_record");
00049 ros::NodeHandle n;
00050 RawlogRecordNode my_node(n);
00051 my_node.init();
00052 my_node.loop();
00053 return 0;
00054 }
00055
00056 RawlogRecordNode::~RawlogRecordNode() {}
00057 RawlogRecordNode::RawlogRecordNode(ros::NodeHandle& n)
00058 : RawlogRecord(new RawlogRecordNode::ParametersNode()),
00059 n_(n)
00060 {
00061 }
00062
00063 RawlogRecordNode::ParametersNode* RawlogRecordNode::param()
00064 {
00065 return (RawlogRecordNode::ParametersNode*)param_;
00066 }
00067
00068 void RawlogRecordNode::init()
00069 {
00070 updateRawLogName(mrpt::system::getCurrentLocalTime());
00071 ROS_INFO("rawlog file: %s", param_->raw_log_name.c_str());
00072 if (param_->record_range_scan) {
00073 subLaser_ = n_.subscribe("scan", 1, &RawlogRecordNode::callbackLaser, this);
00074 }
00075 if (param_->record_bearing_range) {
00076 subMarker_ = n_.subscribe ( "marker", 1, &RawlogRecordNode::callbackMarker, this );
00077 }
00078 subOdometry_ = n_.subscribe ( "odom", 1, &RawlogRecordNode::callbackOdometry, this );
00079 }
00080
00081 void RawlogRecordNode::loop()
00082 {
00083 ros::spin();
00084 }
00085
00086 bool RawlogRecordNode::waitForTransform(
00087 mrpt::poses::CPose3D& des, const std::string& target_frame,
00088 const std::string& source_frame, const ros::Time& time,
00089 const ros::Duration& timeout, const ros::Duration& polling_sleep_duration)
00090 {
00091 tf::StampedTransform transform;
00092 try
00093 {
00094 if (param_->debug)
00095 ROS_INFO(
00096 "debug: waitForTransform(): target_frame='%s' "
00097 "source_frame='%s'",
00098 target_frame.c_str(), source_frame.c_str());
00099
00100 listenerTF_.waitForTransform(
00101 target_frame, source_frame, time, polling_sleep_duration);
00102 listenerTF_.lookupTransform(
00103 target_frame, source_frame, time, transform);
00104 }
00105 catch (tf::TransformException)
00106 {
00107 ROS_INFO(
00108 "Failed to get transform target_frame (%s) to source_frame (%s)",
00109 target_frame.c_str(), source_frame.c_str());
00110 return false;
00111 }
00112 mrpt_bridge::convert(transform, des);
00113 return true;
00114 }
00115
00116 void RawlogRecordNode::convert(const nav_msgs::Odometry& src, mrpt::obs::CObservationOdometry &des) {
00117 mrpt_bridge::convert(src.header.stamp, des.timestamp);
00118 mrpt_bridge::convert(src.pose.pose, des.odometry);
00119 std::string odom_frame_id = tf::resolve(param()->tf_prefix, param()->odom_frame_id);
00120 des.sensorLabel = odom_frame_id;
00121 des.hasEncodersInfo = false;
00122 des.hasVelocities = false;
00123
00124 }
00125
00126 void RawlogRecordNode::callbackOdometry(const nav_msgs::Odometry& _msg)
00127 {
00128
00129 if(!last_odometry_) {
00130 last_odometry_ = mrpt::make_aligned_shared<CObservationOdometry>();
00131 }
00132 convert(_msg, *last_odometry_);
00133 addObservation(_msg.header.stamp);
00134
00135 }
00136
00137 void RawlogRecordNode::callbackLaser(const sensor_msgs::LaserScan& _msg)
00138 {
00139
00140 if(!last_range_scan_) {
00141 last_range_scan_ = mrpt::make_aligned_shared<CObservation2DRangeScan>();
00142 }
00143 mrpt::poses::CPose3D sensor_pose_on_robot;
00144
00145 if (getStaticTF(_msg.header.frame_id, sensor_pose_on_robot)) {
00146 mrpt_bridge::convert(_msg, sensor_pose_on_robot, *last_range_scan_);
00147
00148 addObservation(_msg.header.stamp);
00149
00150 }
00151 }
00152
00153 void RawlogRecordNode::callbackMarker(const marker_msgs::MarkerDetection& _msg)
00154 {
00155
00156 if(!last_bearing_range_) {
00157 last_bearing_range_ = mrpt::make_aligned_shared<CObservationBearingRange>();
00158 }
00159 if(!last_beacon_range_) {
00160 last_beacon_range_ = mrpt::make_aligned_shared<CObservationBeaconRanges>();
00161 }
00162 mrpt::poses::CPose3D sensor_pose_on_robot;
00163
00164 if (getStaticTF(_msg.header.frame_id, sensor_pose_on_robot)) {
00165 mrpt_bridge::convert(_msg, sensor_pose_on_robot, *last_bearing_range_);
00166 last_bearing_range_->sensor_std_range = param_->bearing_range_std_range;
00167 last_bearing_range_->sensor_std_yaw = param_->bearing_range_std_yaw;
00168 last_bearing_range_->sensor_std_pitch = param_->bearing_range_std_pitch;
00169
00170 mrpt_bridge::convert(_msg, sensor_pose_on_robot, *last_beacon_range_);
00171 last_beacon_range_->stdError = param_->bearing_range_std_range;
00172 addObservation(_msg.header.stamp);
00173 }
00174
00175 }
00176
00177 void RawlogRecordNode::addObservation(const ros::Time& time) {
00178
00179
00180 sync_attempts_sensor_frame_++;
00181 if(sync_attempts_sensor_frame_ > 10) ROS_INFO("Problem to syn data for sensor frame!");
00182
00183 if(!last_odometry_) return;
00184 CObservationOdometry::Ptr odometry = mrpt::make_aligned_shared<CObservationOdometry>();
00185 *odometry = *last_odometry_;
00186 pRawLog->addObservationMemoryReference(odometry);
00187
00188 CObservation2DRangeScan::Ptr range_scan;
00189 CObservationBearingRange::Ptr bearing_range;
00190 CObservationBeaconRanges::Ptr beacon_range;
00191
00192 if (param_->record_range_scan) {
00193 if(!last_range_scan_) return;
00194 if( fabs(mrpt::system::timeDifference(last_odometry_->timestamp, last_range_scan_->timestamp)) > param()->sensor_frame_sync_threshold) {
00195 return;
00196 }
00197 range_scan = mrpt::make_aligned_shared<CObservation2DRangeScan>();
00198 *range_scan = *last_range_scan_;
00199 pRawLog->addObservationMemoryReference(range_scan);
00200 }
00201
00202 if (param_->record_bearing_range) {
00203 if(!last_bearing_range_) return;
00204 if( fabs(mrpt::system::timeDifference(last_odometry_->timestamp, last_bearing_range_->timestamp)) > param()->sensor_frame_sync_threshold) {
00205 return;
00206 }
00207 bearing_range = mrpt::make_aligned_shared<CObservationBearingRange>();
00208 *bearing_range = *last_bearing_range_;
00209 pRawLog->addObservationMemoryReference(bearing_range);
00210 }
00211 if (param_->record_beacon_range) {
00212 if(!last_beacon_range_) return;
00213 if( fabs(mrpt::system::timeDifference(last_odometry_->timestamp, last_beacon_range_->timestamp)) > param()->sensor_frame_sync_threshold) {
00214 return;
00215 }
00216 beacon_range = mrpt::make_aligned_shared<CObservationBeaconRanges>();
00217 *beacon_range = *last_beacon_range_;
00218 pRawLog->addObservationMemoryReference(beacon_range);
00219 }
00220
00221
00222 static std::shared_ptr<mrpt::poses::CPose2D> lastOdomPose;
00223 if(!lastOdomPose) {
00224 lastOdomPose = std::make_shared<mrpt::poses::CPose2D>();
00225 *lastOdomPose = odometry->odometry;
00226 }
00227
00228 mrpt::poses::CPose2D incOdoPose = odometry->odometry - *lastOdomPose;
00229
00230 CActionRobotMovement2D odom_move;
00231 odom_move.timestamp = odometry->timestamp;
00232 odom_move.computeFromOdometry(incOdoPose, param_->motionModelOptions);
00233 CActionCollection::Ptr action = mrpt::make_aligned_shared<CActionCollection>();
00234 action->insert(odom_move);
00235 pRawLogASF->addActionsMemoryReference(action);
00236
00237 CSensoryFrame::Ptr sf = mrpt::make_aligned_shared<CSensoryFrame>();
00238 if (param_->record_range_scan) {
00239 CObservation::Ptr obs_range_scan = CObservation::Ptr(range_scan);
00240 sf->insert(obs_range_scan);
00241 }
00242
00243 if (param_->record_bearing_range) {
00244 CObservation::Ptr obs_bearing_range = CObservation::Ptr(bearing_range);
00245 sf->insert(obs_bearing_range);
00246 }
00247 if (param_->record_beacon_range) {
00248 CObservation::Ptr obs_bearing_range = CObservation::Ptr(beacon_range);
00249 sf->insert(obs_bearing_range);
00250 }
00251 pRawLogASF->addObservationsMemoryReference(sf);
00252
00253 *lastOdomPose = odometry->odometry;
00254
00255 sync_attempts_sensor_frame_ = 0;
00256
00257 }
00258
00259 bool RawlogRecordNode::getStaticTF(std::string source_frame, mrpt::poses::CPose3D &des)
00260 {
00261 std::string target_frame_id = tf::resolve(param()->tf_prefix, param()->base_frame_id);
00262 std::string source_frame_id = source_frame;
00263 std::string key = target_frame_id + "->" + source_frame_id;
00264 mrpt::poses::CPose3D pose;
00265 tf::StampedTransform transform;
00266
00267 if (static_tf_.find(key) == static_tf_.end()) {
00268
00269 try
00270 {
00271 if (param_->debug)
00272 ROS_INFO(
00273 "debug: updateLaserPose(): target_frame_id='%s' source_frame_id='%s'",
00274 target_frame_id.c_str(), source_frame_id.c_str());
00275
00276 listenerTF_.lookupTransform(
00277 target_frame_id, source_frame_id, ros::Time(0), transform);
00278 tf::Vector3 translation = transform.getOrigin();
00279 tf::Quaternion quat = transform.getRotation();
00280 pose.x() = translation.x();
00281 pose.y() = translation.y();
00282 pose.z() = translation.z();
00283 tf::Matrix3x3 Rsrc(quat);
00284 mrpt::math::CMatrixDouble33 Rdes;
00285 for (int c = 0; c < 3; c++)
00286 for (int r = 0; r < 3; r++) Rdes(r, c) = Rsrc.getRow(r)[c];
00287 pose.setRotationMatrix(Rdes);
00288 static_tf_[key] = pose;
00289 ROS_INFO("Static tf '%s' with '%s'",
00290 key.c_str(), pose.asString().c_str());
00291 }
00292 catch (tf::TransformException ex)
00293 {
00294 ROS_INFO("getStaticTF");
00295 ROS_ERROR("%s", ex.what());
00296 ros::Duration(1.0).sleep();
00297 return false;
00298 }
00299 }
00300 des = static_tf_[key];
00301 return true;
00302
00303 }