wifi_mapping_node.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2013, Seigo ITO
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of Seigo ITO nor the names of its
00014  *       contributors may be used to endorse or promote products derived from
00015  *       this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00030 
00031 // ROS
00032 #include "ros/ros.h"
00033 #include "ros/package.h"
00034 #include "tf/transform_broadcaster.h"
00035 #include "tf/transform_listener.h"
00036 #include "tf/message_filter.h"
00037 #include "tf/tf.h"
00038 #include "message_filters/subscriber.h"
00039 #include "sensor_msgs/PointCloud2.h"
00040 #include <pcl_ros/point_cloud.h>
00041 #include <pcl/point_types.h>
00042 #include <pcl/io/pcd_io.h>
00043 #include "std_srvs/Empty.h"
00044 
00045 // WiFi
00046 #include "wifi_tools/WifiData.h"
00047 #include "wifi_tools/Out2File.h"
00048 
00049 
00050 
00051 class WiFiMappingNode
00052 {
00053 public:
00054   WiFiMappingNode();
00055   ~WiFiMappingNode();
00056 
00057   void wifiScanReceived(const wifi_tools::WifiDataConstPtr& wifi_msg);
00058   bool outputFile(std_srvs::Empty::Request& req, std_srvs::Empty::Response& res);
00059 
00060 private:
00061   message_filters::Subscriber<wifi_tools::WifiData>* wifiscan_sub_;
00062   tf::MessageFilter<wifi_tools::WifiData>* wifi_filter_;
00063 
00064   ros::NodeHandle nh_;
00065   tf::TransformListener* tf_;
00066 
00067   // frame_id for odom
00068   std::string odom_frame_id_;
00069   // frame_id for base
00070   std::string base_frame_id_;
00071 
00072   // topic of wifi_scan
00073   std::string wifiscan_topic_;
00074 
00075   // AP map
00076   std::map<std::string,pcl::PointCloud<pcl::PointXYZ> > ap_map_;
00077 
00078   // wifi map publisher
00079   ros::Publisher wifi_map_pub_;
00080 
00081   ros::ServiceServer out2file_srv_;
00082 };
00083 
00084 
00085 
00086 WiFiMappingNode::WiFiMappingNode()
00087 {
00088   nh_.param("wifiscan_topic",wifiscan_topic_,std::string("/wifi_tools/wifi_data"));
00089   nh_.param("odom_frame_id", odom_frame_id_, std::string("/odom"));
00090   nh_.param("base_frame_id", base_frame_id_, std::string("/base_link"));
00091 
00092   tf_ = new tf::TransformListener();
00093 
00094   // wifiscan subscriber
00095   wifiscan_sub_ = new message_filters::Subscriber<wifi_tools::WifiData>(nh_, wifiscan_topic_, 100);
00096 
00097   // Mesage integration
00098   wifi_filter_     =  new tf::MessageFilter<wifi_tools::WifiData>(*wifiscan_sub_, *tf_, odom_frame_id_, 100);
00099   wifi_filter_->registerCallback(boost::bind(&WiFiMappingNode::wifiScanReceived,this, _1));
00100 
00101   // wifi map publisher
00102   wifi_map_pub_    = nh_.advertise<sensor_msgs::PointCloud2>("/wifi_map", 10);
00103 
00104   // output file service
00105   out2file_srv_ = nh_.advertiseService("/wifi_mapping/o2file", &WiFiMappingNode::outputFile,this);
00106 
00107 }
00108 
00109 
00110 
00111 WiFiMappingNode::~WiFiMappingNode()
00112 {
00113 }
00114 
00115 
00116 
00117 bool WiFiMappingNode::outputFile(std_srvs::Empty::Request& req, std_srvs::Empty::Response& res)
00118 {
00119   // outpu2 pcd file
00120   std::string file_base = ros::package::getPath("wifi_tools") + "/map/";
00121   std::map<std::string,pcl::PointCloud<pcl::PointXYZ> >::iterator it = ap_map_.begin();
00122   while(it != ap_map_.end())
00123   {
00124     std::string filename = file_base + (std::string)(*it).first + ".pcd";
00125     pcl::io::savePCDFileASCII (filename, (*it).second);
00126     ++it;
00127   }
00128   ROS_INFO("WiFi maps have written to %s",file_base.c_str());
00129   return true;
00130 }
00131 
00132 
00133 
00134 void WiFiMappingNode::wifiScanReceived(const wifi_tools::WifiDataConstPtr& wifi_msg)
00135 {
00136   // *** tf pose associated with this massage ***
00137   tf::Stamped<tf::Pose> odom_pose;
00138   tf::Stamped<tf::Pose> base_pose (tf::Transform(tf::createIdentityQuaternion(),tf::Vector3(0,0,0)), wifi_msg->header.stamp, base_frame_id_);
00139   try
00140   {
00141     this->tf_->transformPose(odom_frame_id_, base_pose, odom_pose);
00142   }
00143   catch(tf::TransformException e)
00144   {
00145           ROS_WARN("can't get transform. (%s)", e.what());
00146   }
00147 
00148   // wifi_msg
00149   std::map<std::string,pcl::PointCloud<pcl::PointXYZ> >::iterator it;
00150   std::string mac;
00151   double z_x,z_y,z_ss;
00152   for(int i=0; i<wifi_msg->data.size();i++)
00153   {
00154     mac = wifi_msg->data[i].mac_address;
00155     it = ap_map_.find(mac);
00156     z_x = (double)odom_pose.getOrigin().x();
00157     z_y = (double)odom_pose.getOrigin().y();
00158     z_ss = (double)wifi_msg->data[i].ss;
00159     if( it == ap_map_.end())
00160     {
00161       // first ap observation
00162       pcl::PointCloud<pcl::PointXYZ> ap;
00163       ap_map_.insert(std::map<std::string,pcl::PointCloud<pcl::PointXYZ> >::value_type(mac,ap));
00164       ROS_INFO("new ap %s",mac.c_str());
00165     }
00166     else
00167     {
00168       pcl::PointCloud<pcl::PointXYZ> cloud;
00169       cloud.width    = 1;
00170       cloud.height   = 1;
00171       cloud.is_dense = false;
00172       cloud.points.resize (cloud.width * cloud.height);
00173       cloud.points[0].x = z_x;
00174       cloud.points[0].y = z_y;
00175       cloud.points[0].z = z_ss;
00176       (*it).second += cloud;
00177     }
00178   }
00179 
00180 }
00181 
00182 
00183 
00184 int main(int argc, char** argv)
00185 {
00186   ros::init(argc, argv, "WiFi_mapping_node");
00187   ros::NodeHandle nh;
00188   WiFiMappingNode wifi_mapping;
00189 
00190   ROS_INFO("Waiting for WiFi signals...");
00191   ros::spin();
00192   return (0);
00193 }


wifi_tools
Author(s): Seigo ITO
autogenerated on Mon Oct 6 2014 12:23:56