bool SlamKarto::updateMap() { boost::mutex::scoped_lock(map_mutex_); karto::OccupancyGrid* occ_grid = karto::OccupancyGrid::CreateFromScans(mapper_->GetAllProcessedScans(), resolution_); if(!occ_grid) return false; if(!got_map_) { map_.map.info.resolution = resolution_; map_.map.info.origin.position.x = 0.0; map_.map.info.origin.position.y = 0.0; map_.map.info.origin.position.z = 0.0; map_.map.info.origin.orientation.x = 0.0; map_.map.info.origin.orientation.y = 0.0; map_.map.info.origin.orientation.z = 0.0; map_.map.info.origin.orientation.w = 1.0; } // Translate to ROS format kt_int32s width = occ_grid->GetWidth(); kt_int32s height = occ_grid->GetHeight(); karto::Vector2<kt_double> offset = occ_grid->GetCoordinateConverter()->GetOffset(); if(map_.map.info.width != (unsigned int) width || map_.map.info.height != (unsigned int) height || map_.map.info.origin.position.x != offset.GetX() || map_.map.info.origin.position.y != offset.GetY()) { map_.map.info.origin.position.x = offset.GetX(); map_.map.info.origin.position.y = offset.GetY(); map_.map.info.width = width; map_.map.info.height = height; map_.map.data.resize(map_.map.info.width * map_.map.info.height); } for (kt_int32s y=0; y<height; y++) { for (kt_int32s x=0; x<width; x++) { // Getting the value at position x,y kt_int8u value = occ_grid->GetValue(karto::Vector2<kt_int32s>(x, y)); switch (value) { case karto::GridStates_Unknown: map_.map.data[MAP_IDX(map_.map.info.width, x, y)] = -1; break; case karto::GridStates_Occupied: map_.map.data[MAP_IDX(map_.map.info.width, x, y)] = 100; break; case karto::GridStates_Free: map_.map.data[MAP_IDX(map_.map.info.width, x, y)] = 0; break; default: ROS_WARN("Encountered unknown cell value at %d, %d", x, y); break; } } } // Set the header information on the map map_.map.header.stamp = ros::Time::now(); map_.map.header.frame_id = map_frame_; sst_.publish(map_.map); sstm_.publish(map_.map.info); delete occ_grid; return true; }
bool SlamKarto::addScan(karto::LaserRangeFinder* laser, const sensor_msgs::LaserScan::ConstPtr& scan, karto::Pose2& karto_pose) { if(!getOdomPose(karto_pose, scan->header.stamp)) return false; // Create a vector of doubles for karto std::vector<kt_double> readings; if (lasers_inverted_[scan->header.frame_id]) { for(std::vector<float>::const_reverse_iterator it = scan->ranges.rbegin(); it != scan->ranges.rend(); ++it) { readings.push_back(*it); } } else { for(std::vector<float>::const_iterator it = scan->ranges.begin(); it != scan->ranges.end(); ++it) { readings.push_back(*it); } } // create localized range scan karto::LocalizedRangeScan* range_scan = new karto::LocalizedRangeScan(laser->GetName(), readings); range_scan->SetOdometricPose(karto_pose); range_scan->SetCorrectedPose(karto_pose); // Add the localized range scan to the mapper bool processed; if((processed = mapper_->Process(range_scan))) { //std::cout << "Pose: " << range_scan->GetOdometricPose() << " Corrected Pose: " << range_scan->GetCorrectedPose() << std::endl; karto::Pose2 corrected_pose = range_scan->GetCorrectedPose(); // Compute the map->odom transform tf::Stamped<tf::Pose> odom_to_map; try { tf_.transformPose(odom_frame_,tf::Stamped<tf::Pose> (tf::Transform(tf::createQuaternionFromRPY(0, 0, corrected_pose.GetHeading()), tf::Vector3(corrected_pose.GetX(), corrected_pose.GetY(), 0.0)).inverse(), scan->header.stamp, base_frame_),odom_to_map); } catch(tf::TransformException e) { ROS_ERROR("Transform from base_link to odom failed\n"); odom_to_map.setIdentity(); } map_to_odom_mutex_.lock(); map_to_odom_ = tf::Transform(tf::Quaternion( odom_to_map.getRotation() ), tf::Point( odom_to_map.getOrigin() ) ).inverse(); map_to_odom_mutex_.unlock(); // Add the localized range scan to the dataset (for memory management) dataset_->Add(range_scan); } else delete range_scan; return processed; }
/** * @brief SlamKarto::addScan * @param laser LaserRangeFinder ref base * @param scan 传感器数据 ref laser * @param karto_pose odom_pose 回调 * @return */ bool SlamKarto::addScan(karto::LaserRangeFinder* laser, const sensor_msgs::LaserScan::ConstPtr& scan, karto::Pose2& karto_pose) { if(!getOdomPose(karto_pose, scan->header.stamp)) // 将odom与base保持坐标系对齐. 返回 odom --> karto_pose return false; // Create a vector of doubles for karto std::vector<kt_double> readings; //readings 原始scan laser -> reading if (lasers_inverted_[scan->header.frame_id]) { for(std::vector<float>::const_reverse_iterator it = scan->ranges.rbegin(); it != scan->ranges.rend(); ++it) { readings.push_back(*it); //laser range messages } } else { for(std::vector<float>::const_iterator it = scan->ranges.begin(); it != scan->ranges.end(); ++it) { readings.push_back(*it); debugPrint_<<" "<< *it; } } debugPrint_<<" " <<endl; if(debug_flag_) debugPrint_<<"reading.size() "<<readings.size()<<endl; // create localized range scan 创建rangeScan karto::LocalizedRangeScan* range_scan = new karto::LocalizedRangeScan(laser->GetName(), readings);// range_scan->SetOdometricPose(karto_pose);// Sets the odometric pose of this scan range_scan->SetCorrectedPose(karto_pose);// Moves the scan by moving the robot pose to the given location. if(debug_print_flag_) debugPrint_<<"1.1 addScan-karto_pose-: "<<karto_pose.GetX()<<" "<<karto_pose.GetY()<<" "<< karto_pose.GetHeading() <<" "<<endl; // Add the localized range scan to the mapper bool processed; //range_scan contain reading and predict pose of robot if((processed = mapper_->Process(range_scan))) // pose 为base相对odom的pose { //std::cout << "Pose: " << range_scan->GetOdometricPose() << " Corrected Pose: " << range_scan->GetCorrectedPose() << std::endl; karto::Pose2 corrected_pose = range_scan->GetCorrectedPose(); if(debug_print_flag_) debugPrint_<<"1.2 addScan-corrected_pose-: "<<corrected_pose.GetX()<<" "<<corrected_pose.GetY()<<" "<< corrected_pose.GetHeading() <<" "<<endl; // Compute the map->odom transform tf::Stamped<tf::Pose> odom_to_map; try { tf_.transformPose(odom_frame_,tf::Stamped<tf::Pose> (tf::Transform( tf::createQuaternionFromRPY(0, 0, corrected_pose.GetHeading()), tf::Vector3(corrected_pose.GetX(), corrected_pose.GetY(), 0.0)).inverse(), scan->header.stamp, base_frame_),odom_to_map); } catch(tf::TransformException e) { ROS_ERROR("Transform from base_link to odom failed\n"); odom_to_map.setIdentity(); } map_to_odom_mutex_.lock(); map_to_odom_ = tf::Transform(tf::Quaternion( odom_to_map.getRotation() ), tf::Point( odom_to_map.getOrigin() ) ).inverse(); map_to_odom_mutex_.unlock(); //debugPrint_<< " x y z "<< odom_to_map.getOrigin().getX() <<" "<< odom_to_map.getOrigin().getY()<<" "<<odom_to_map.getOrigin().getZ()<<endl; if(debug_print_flag_) debugPrint_<<"1.3 addScan-odom_to_map: "<<odom_to_map.getOrigin().getX() <<" "<< odom_to_map.getOrigin().getY()<<" "<<endl; // Add the localized range scan to the dataset (for memory management) dataset_->Add(range_scan); } else delete range_scan; return processed; }