コード例 #1
0
int main(int argc, char **argv)
{
	ros::init(argc, argv, "object_recognition");
	ros::NodeHandle nh;
	ros::NodeHandle nh_param("~");
	
	// Create a ROS subscriber for the object and world keypoints and descriptors
	sub_keypoint_object = nh.subscribe ("/object_recognition/object/keypoints", 1, object_keypoint_cb);
	sub_keypoint_world  = nh.subscribe ("/object_recognition/world/keypoints",  1, world_keypoint_cb );
	sub_descriptors_object_shot352 = nh.subscribe ("/object_recognition/object/descriptors/Shot352" , 1, object_descriptor_shot352_cb);
	sub_descriptors_world_shot352  = nh.subscribe ("/object_recognition/world/descriptors/Shot352"  , 1, world_descriptor_shot352_cb );
	sub_descriptors_object_shot1344= nh.subscribe ("/object_recognition/object/descriptors/Shot1344", 1, object_descriptor_shot1344_cb);
	sub_descriptors_world_shot1344 = nh.subscribe ("/object_recognition/world/descriptors/Shot1344" , 1, world_descriptor_shot1344_cb );

	pub_object = nh.advertise<PointCloudROS> ("correspondences/object/clustered", 1);	
	pub_world = nh.advertise<PointCloudROS> ("correspondences/world/clustered", 1);
	pub_object2 = nh.advertise<PointCloudROS> ("correspondences/object", 1);	
	pub_world2 = nh.advertise<PointCloudROS> ("correspondences/world", 1);

	ros::spin();
	return 0;
}
コード例 #2
0
ファイル: joy_node.cpp プロジェクト: kissdestinator/FroboMind
  ///\brief Opens joystick port, reads from port and publishes while node is active
  int main(int argc, char **argv)
  {
    diagnostic_.add("Joystick Driver Status", this, &Joystick::diagnostics);
    diagnostic_.setHardwareID("none");

    // Parameters
    ros::NodeHandle nh_param("~");
    pub_ = nh_.advertise<fmMsgs::Joy>("joy", 1);
    nh_param.param<std::string>("dev", joy_dev_, "/dev/input/js0");
    nh_param.param<double>("deadzone", deadzone_, 0.05);
    nh_param.param<double>("autorepeat_rate", autorepeat_rate_, 0);
    nh_param.param<double>("coalesce_interval", coalesce_interval_, 0.001);
    
    // Checks on parameters
    if (autorepeat_rate_ > 1 / coalesce_interval_)
      ROS_WARN("joy_node: autorepeat_rate (%f Hz) > 1/coalesce_interval (%f Hz) does not make sense. Timing behavior is not well defined.", autorepeat_rate_, 1/coalesce_interval_);
    
    if (deadzone_ >= 1)
    {
      ROS_WARN("joy_node: deadzone greater than 1 was requested. The semantics of deadzone have changed. It is now related to the range [-1:1] instead of [-32767:32767]. For now I am dividing your deadzone by 32767, but this behavior is deprecated so you need to update your launch file.");
      deadzone_ /= 32767;
    }
    
    if (deadzone_ > 0.9)
    {
      ROS_WARN("joy_node: deadzone (%f) greater than 0.9, setting it to 0.9", deadzone_);
      deadzone_ = 0.9;
    }
    
    if (deadzone_ < 0)
    {
      ROS_WARN("joy_node: deadzone_ (%f) less than 0, setting to 0.", deadzone_);
      deadzone_ = 0;
    }

    if (autorepeat_rate_ < 0)
    {
      ROS_WARN("joy_node: autorepeat_rate (%f) less than 0, setting to 0.", autorepeat_rate_);
      autorepeat_rate_ = 0;
    }
    
    if (coalesce_interval_ < 0)
    {
      ROS_WARN("joy_node: coalesce_interval (%f) less than 0, setting to 0.", coalesce_interval_);
      coalesce_interval_ = 0;
    }
    
    // Parameter conversions
    double autorepeat_interval = 1 / autorepeat_rate_;
    double scale = -1. / (1. - deadzone_) / 32767.;
    double unscaled_deadzone = 32767. * deadzone_;

    js_event event;
    struct timeval tv;
    fd_set set;
    int joy_fd;
    event_count_ = 0;
    pub_count_ = 0;
    lastDiagTime_ = ros::Time::now().toSec();
    
    // Big while loop opens, publishes
    while (nh_.ok())
    {                                      
      open_ = false;
      diagnostic_.force_update();
      bool first_fault = true;
      while (true)
      {
        ros::spinOnce();
        if (!nh_.ok())
          goto cleanup;
        joy_fd = open(joy_dev_.c_str(), O_RDONLY);
        if (joy_fd != -1)
        {
          // There seems to be a bug in the driver or something where the
          // initial events that are to define the initial state of the
          // joystick are not the values of the joystick when it was opened
          // but rather the values of the joystick when it was last closed.
          // Opening then closing and opening again is a hack to get more
          // accurate initial state data.
          close(joy_fd);
          joy_fd = open(joy_dev_.c_str(), O_RDONLY);
        }
        if (joy_fd != -1)
          break;
        if (first_fault)
        {
          ROS_ERROR("Couldn't open joystick %s. Will retry every second.", joy_dev_.c_str());
          first_fault = false;
        }
        sleep(1.0);
        diagnostic_.update();
      }
      
      ROS_INFO("Opened joystick: %s. deadzone_: %f.", joy_dev_.c_str(), deadzone_);
      open_ = true;
      diagnostic_.force_update();
      
      bool tv_set = false;
      bool publication_pending = false;
      tv.tv_sec = 1;
      tv.tv_usec = 0;
      fmMsgs::Joy joy_msg; // Here because we want to reset it on device close.
      while (nh_.ok()) 
      {
        ros::spinOnce();
        
        bool publish_now = false;
        bool publish_soon = false;
        FD_ZERO(&set);
        FD_SET(joy_fd, &set);
        
        //ROS_INFO("Select...");
        int select_out = select(joy_fd+1, &set, NULL, NULL, &tv);
        //ROS_INFO("Tick...");
        if (select_out == -1)
        {
          tv.tv_sec = 0;
          tv.tv_usec = 0;
          //ROS_INFO("Select returned negative. %i", ros::isShuttingDown());
          continue;
          //				break; // Joystick is probably closed. Not sure if this case is useful.
        }
        
        if (FD_ISSET(joy_fd, &set))
        {
          if (read(joy_fd, &event, sizeof(js_event)) == -1 && errno != EAGAIN)
            break; // Joystick is probably closed. Definitely occurs.
          
          //ROS_INFO("Read data...");
          joy_msg.header.stamp = ros::Time().now();
          event_count_++;
          switch(event.type)
          {
          case JS_EVENT_BUTTON:
          case JS_EVENT_BUTTON | JS_EVENT_INIT:
            if(event.number >= joy_msg.buttons.size())
            {
              int old_size = joy_msg.buttons.size();
              joy_msg.buttons.resize(event.number+1);
              for(unsigned int i=old_size;i<joy_msg.buttons.size();i++)
                joy_msg.buttons[i] = 0.0;
            }
            joy_msg.buttons[event.number] = (event.value ? 1 : 0);
            // For initial events, wait a bit before sending to try to catch
            // all the initial events.
            if (!(event.type & JS_EVENT_INIT))
              publish_now = true;
            else
              publish_soon = true;
            break;
          case JS_EVENT_AXIS:
          case JS_EVENT_AXIS | JS_EVENT_INIT:
            if(event.number >= joy_msg.axes.size())
            {
              int old_size = joy_msg.axes.size();
              joy_msg.axes.resize(event.number+1);
              for(unsigned int i=old_size;i<joy_msg.axes.size();i++)
                joy_msg.axes[i] = 0.0;
            }
            if (!(event.type & JS_EVENT_INIT)) // Init event.value is wrong.
            {
              double val = event.value;
              // Allows deadzone to be "smooth"
              if (val > unscaled_deadzone)
                val -= unscaled_deadzone;
              else if (val < -unscaled_deadzone)
                val += unscaled_deadzone;
              else
                val = 0;
              joy_msg.axes[event.number] = val * scale;
            }
            // Will wait a bit before sending to try to combine events. 				
            publish_soon = true;
            break;
          default:
            ROS_WARN("joy_node: Unknown event type. Please file a ticket. time=%u, value=%d, type=%Xh, number=%d", event.time, event.value, event.type, event.number);
            break;
          }
        }
        else if (tv_set) // Assume that the timer has expired.
          publish_now = true;
        
        if (publish_now)
        {
          // Assume that all the JS_EVENT_INIT messages have arrived already.
          // This should be the case as the kernel sends them along as soon as
          // the device opens.
          //ROS_INFO("Publish...");
          pub_.publish(joy_msg);
          publish_now = false;
          tv_set = false;
          publication_pending = false;
          publish_soon = false;
          pub_count_++;
        }
        
        // If an axis event occurred, start a timer to combine with other
        // events.
        if (!publication_pending && publish_soon)
        {
          tv.tv_sec = trunc(coalesce_interval_);
          tv.tv_usec = (coalesce_interval_ - tv.tv_sec) * 1e6;
          publication_pending = true;
          tv_set = true;
          //ROS_INFO("Pub pending...");
        }
        
        // If nothing is going on, start a timer to do autorepeat.
        if (!tv_set && autorepeat_rate_ > 0)
        {
          tv.tv_sec = trunc(autorepeat_interval);
          tv.tv_usec = (autorepeat_interval - tv.tv_sec) * 1e6; 
          tv_set = true;
          //ROS_INFO("Autorepeat pending... %i %i", tv.tv_sec, tv.tv_usec);
        }
        
        if (!tv_set)
        {
          tv.tv_sec = 1;
          tv.tv_usec = 0;
        }
	
        diagnostic_.update();
      } // End of joystick open loop.
      
      close(joy_fd);
      ros::spinOnce();
      if (nh_.ok())
        ROS_ERROR("Connection to joystick device lost unexpectedly. Will reopen.");
    }
    
  cleanup:
    ROS_INFO("joy_node shut down.");
    
    return 0;
  }
コード例 #3
0
// callback function when the object descriptors are received
// this will also trigger the recognition if all the other keypoints and descriptors have been received
void object_descriptor_shot352_cb (const object_recognition::Shot352_bundle::Ptr input)
{
	ros::NodeHandle nh_param("~");
	nh_param.param<double>("maximum_descriptor_distance" , max_descr_dist_ , 0.25 );

	// check if world was already processed
	if (world_descriptors_shot352 == NULL)
	{
		ROS_WARN("Received object descriptors before having a world pointcloud to compare");
		return;
	}
	// check if the stored world descriptors can be assinged to the stored keypoints
	if ((int)world_keypoints->size() != (int)world_descriptors_shot352->size())
	{
		ROS_WARN("Received %i descriptors and %i keypoints for the world. Number must be equal", (int)world_descriptors_shot352->size(), (int)world_keypoints->size());
		return;
	}
	// check if the received object descriptors can be assigned to the stored keypoints
	if ((int)object_keypoints->size() != (int)input->descriptors.size())
	{
		ROS_WARN("Received %i descriptors and %i keypoints for the object. Number must be equal", (int)input->descriptors.size(), (int)object_keypoints->size());
		return;
	}
	
	// Debug output 
	ROS_INFO("Received %i descriptors for the world and %i for the object", (int)world_descriptors_shot352->size(), (int)input->descriptors.size());

	object_descriptors_shot352 = DescriptorCloudShot352::Ptr (new DescriptorCloudShot352 ());
	fromROSMsg(*input, *object_descriptors_shot352);
	//
	//  Find Object-World Correspondences with KdTree
	//
	cout << "... finding correspondences ..." << endl;
	pcl::CorrespondencesPtr object_world_corrs (new pcl::Correspondences ());
	
	pcl::KdTreeFLANN<SHOT352> match_search;
	match_search.setInputCloud (object_descriptors_shot352);

	// For each world keypoint descriptor
	// find nearest neighbor into the object keypoints descriptor cloud 
	// and add it to the correspondences vector
	for (size_t i = 0; i < world_descriptors_shot352->size (); ++i)
	{
		std::vector<int> neigh_indices (1);
		std::vector<float> neigh_sqr_dists (1);
		if (!pcl_isfinite (world_descriptors_shot352->at (i).descriptor[0])) //skipping NaNs
		{
			continue;
		}
		int found_neighs = match_search.nearestKSearch (world_descriptors_shot352->at (i), 1, neigh_indices, neigh_sqr_dists);
		// add match only if the squared descriptor distance is less than 0.25 
		// SHOT descriptor distances are between 0 and 1 by design
		if(found_neighs == 1 && neigh_sqr_dists[0] < (float)max_descr_dist_) 
		{
			pcl::Correspondence corr (neigh_indices[0], static_cast<int> (i), neigh_sqr_dists[0]);
			object_world_corrs->push_back (corr);
		}
	}
	std::cout << "Correspondences found: " << object_world_corrs->size () << std::endl;
	
	//
	// all keypoints and descriptors were found, no match the correspondences to the real object!
	//
	cluster(object_world_corrs);
}
コード例 #4
0
void cluster(const pcl::CorrespondencesPtr &object_world_corrs)
{
	ros::NodeHandle nh_param("~");
	nh_param.param<double>("cg_size" , cg_size_ , 0.01 );
	nh_param.param<double>("cg_thresh", cg_thresh_, 5.0);

	//
	// Debug output
	//
	PointCloud correspondence_object;
	PointCloud correspondence_world;
	for (int j = 0; j < object_world_corrs->size (); ++j)
  {
    PointType& object_point = object_keypoints->at(object_world_corrs->at(j).index_query);
    PointType& world_point = world_keypoints->at(object_world_corrs->at(j).index_match);

		correspondence_object.push_back(object_point);
		correspondence_world.push_back(world_point);

		
		// cout << object_point.x << " " << object_point.y << " " <<  object_point.z << endl;
		// cout << world_point.x << " " << world_point.y << " " <<  world_point.z << endl;
  }

	PointCloudROS pub_me_object2;
	PointCloudROS pub_me_world2;
	toROSMsg(correspondence_object, pub_me_object2);
	toROSMsg(correspondence_world, pub_me_world2);
	pub_me_object2.header.frame_id = "/object";
	pub_me_world2.header.frame_id = "/world";
	pub_object2.publish(pub_me_object2);
	pub_world2.publish(pub_me_world2);

  //
  //  Actual Clustering
  //
	cout << "... clustering ..." << endl;    
  std::vector<Eigen::Matrix4f, Eigen::aligned_allocator<Eigen::Matrix4f> > rototranslations;
  std::vector<pcl::Correspondences> clustered_corrs;
    
	pcl::GeometricConsistencyGrouping<PointType, PointType> gc_clusterer;
	gc_clusterer.setGCSize (cg_size_);
	gc_clusterer.setGCThreshold (cg_thresh_);

	gc_clusterer.setInputCloud (object_keypoints);
	gc_clusterer.setSceneCloud (world_keypoints);
	gc_clusterer.setModelSceneCorrespondences (object_world_corrs);

	gc_clusterer.recognize (rototranslations, clustered_corrs);

    
  //
  //  Output results
  //
  std::cout << "Object instances found: " << rototranslations.size () << std::endl;
	int maximum = 0;
	int best;
	for (int i = 0; i < rototranslations.size (); ++i)
	{
		cout << "Instance "<< i << " has " << clustered_corrs[i].size () << " correspondences" << endl;
		if (maximum < clustered_corrs[i].size ())
		{
			maximum = clustered_corrs[i].size ();
			best = i;
		}
	}

  if (rototranslations.size () > 0)
  {
		cout << "selecting instance " << best << " and calculating TF" << endl;

    // Print the rotation matrix and translation vector
    Eigen::Matrix3f rotation = rototranslations[best].block<3,3>(0, 0);
    Eigen::Vector3f translation = rototranslations[best].block<3,1>(0, 3);
    
    printf ("\n");
    printf ("            | %6.3f %6.3f %6.3f | \n", rotation (0,0), rotation (0,1), rotation (0,2));
    printf ("        R = | %6.3f %6.3f %6.3f | \n", rotation (1,0), rotation (1,1), rotation (1,2));
    printf ("            | %6.3f %6.3f %6.3f | \n", rotation (2,0), rotation (2,1), rotation (2,2));
    printf ("\n");
    printf ("        t = < %0.3f, %0.3f, %0.3f >\n", translation (0), translation (1), translation (2));

		// convert Eigen matricies into ROS TF message
		tf::Vector3 object_offset;
		tf::Quaternion object_rotation;
		object_offset[0] = translation (0);
		object_offset[1] = translation (1);
		object_offset[2] = translation (2);
		// convert rotation matrix to quaternion
		Eigen::Quaternionf quaternion (rotation);
		object_rotation[0] = quaternion.x();
		object_rotation[1] = quaternion.y();
		object_rotation[2] = quaternion.z();
		object_rotation[3] = quaternion.w();

		static tf::TransformBroadcaster br;
		tf::Transform transform;
		transform.setOrigin (object_offset);
		transform.setRotation (object_rotation);
		br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "world", "object"));

		//
		// Debug output
		//
		PointCloud correspondence_object_cluster;
		PointCloud correspondence_world_cluster;
		
		for (int j = 0; j < clustered_corrs[best].size (); ++j)
    {
      PointType& model_point = object_keypoints->at(clustered_corrs[best][j].index_query);
      PointType& scene_point = world_keypoints->at(clustered_corrs[best][j].index_match);
			correspondence_object_cluster.push_back(model_point);
			correspondence_world_cluster.push_back(scene_point);
			//cout << model_point.x << " " << model_point.y << " " <<  model_point.z << endl;
			//cout << scene_point.x << " " <<  scene_point.y << " " <<  scene_point.z << endl;
    }

		PointCloudROS pub_me_object;
		PointCloudROS pub_me_world;
		toROSMsg(correspondence_object_cluster, pub_me_object);
		toROSMsg(correspondence_world_cluster, pub_me_world);
		pub_me_object.header.frame_id = "/object";
		pub_me_world.header.frame_id = "/world";
		pub_object.publish(pub_me_object);
		pub_world.publish(pub_me_world);
  }
}
コード例 #5
0
// callback function when the object descriptors are received
// this will also trigger the recognition if all the other keypoints and descriptors have been received
void object_descriptor_shot1344_cb (const object_recognition::Shot1344_bundle::Ptr input)
{
	ros::NodeHandle nh_param("~");
	nh_param.param<double>("maximum_descriptor_distance" , max_descr_dist_ , 0.25 );
	// check if world was already processed
	if (world_descriptors_shot1344 == NULL)
	{
		ROS_WARN("Received object descriptors before having a world pointcloud to compare");
		return;
	}
	// check if the stored world descriptors can be assinged to the stored keypoints
	if ((int)world_keypoints->size() != (int)world_descriptors_shot1344->size())
	{
		ROS_WARN("Received %i descriptors and %i keypoints for the world. Number must be equal", (int)world_descriptors_shot1344->size(), (int)world_keypoints->size());
		return;
	}
	// check if the received object descriptors can be assigned to the stored keypoints
	if ((int)object_keypoints->size() != (int)input->descriptors.size())
	{
		ROS_WARN("Received %i descriptors and %i keypoints for the object. Number must be equal", (int)input->descriptors.size(), (int)object_keypoints->size());
		return;
	}
	
	object_descriptors_shot1344 = DescriptorCloudShot1344::Ptr (new DescriptorCloudShot1344 ());
	fromROSMsg(*input, *object_descriptors_shot1344);

	// Debug output 
	ROS_INFO("Received %i descriptors for the world and %i for the object", (int)world_descriptors_shot1344->size(), (int)input->descriptors.size());

	//
	//  Find Object-World Correspondences with KdTree
	//
	cout << "... finding correspondences ..." << endl;
	pcl::CorrespondencesPtr object_world_corrs (new pcl::Correspondences ());
	
	pcl::KdTreeFLANN<SHOT1344> match_search;
	match_search.setInputCloud (object_descriptors_shot1344);
		
	// For each world keypoint descriptor
	// find nearest neighbor into the object keypoints descriptor cloud 
	// and add it to the correspondences vector
	for (size_t i = 0; i < world_descriptors_shot1344->size (); ++i)
	{
		std::vector<int> neigh_indices (1);
		std::vector<float> neigh_sqr_dists (1);
		if (!pcl_isfinite (world_descriptors_shot1344->at (i).descriptor[0])) //skipping NaNs
		{
			continue;
		}
		int found_neighs = match_search.nearestKSearch (world_descriptors_shot1344->at (i), 1, neigh_indices, neigh_sqr_dists);
		// add match only if the squared descriptor distance is less than max_descr_dist_ 
		// SHOT descriptor distances are between 0 and 1 by design
		if(found_neighs == 1 && neigh_sqr_dists[0] < (float)max_descr_dist_) 
		{
			pcl::Correspondence corr (neigh_indices[0], static_cast<int> (i), neigh_sqr_dists[0]);

			// check if new correspondence is better than any previous at this point
			bool found_better_result = false;
			for (int j = 0; j < object_world_corrs->size(); ++j)
			{
				// is the found neigbor the same one like in the correspondence j
				if (object_world_corrs->at(j).index_query == neigh_indices[0])
				{
					// do not add a new correspondence later
					found_better_result = true;
					// is the new distance smaller? (that means better)
					if (neigh_sqr_dists[0] < object_world_corrs->at(j).distance)
					{
						// replace correspondence with better one
						object_world_corrs->at(j) = corr;
					}
					else
						// break out of inner loop to save time and try next keypoint
						break;
				}
			}
			// if this is a new correspondence, add a new correspondence at the end
			if (!found_better_result)
				object_world_corrs->push_back (corr);	
		}
	}
	std::cout << "Correspondences found: " << object_world_corrs->size () << std::endl;


	//
	// all correspondences were found, now match the correspondences to the real object!
	//
	cluster(object_world_corrs);
}