void fi::MSHRFileIO::getProjectionPointOnImage(const pcl::PointXYZ &reconstructed_3D_point,
	const Eigen::Matrix3f &cam_calib,
	const Eigen::Matrix3f &rotations_matrix, 
	const Eigen::Vector3f &translation_vector,
	float radial_dist1, 
	float radial_dist2,
	unsigned int img_width,
	unsigned int img_height,
	Eigen::Vector2f &image_point)
{

	Eigen::Vector3f tmp_point;
	tmp_point(0) = reconstructed_3D_point.x;
	tmp_point(1) = reconstructed_3D_point.y;
	tmp_point(2) = reconstructed_3D_point.z;

	//place point to camera axis
	Eigen::Vector3f point_cam = rotations_matrix*tmp_point + translation_vector;

	//project on x-y plane
	Eigen::Vector3f point_xy1;
	point_xy1(0) = point_cam(0)/point_cam(2);
	point_xy1(1) = point_cam(1)/point_cam(2);
	point_xy1(2) = 1.0f;

	Eigen::Vector3f point_homgenoues_img = cam_calib*point_xy1;

	//undistortion
	float r = sqrtf(point_xy1(0)*point_xy1(0) + point_xy1(1)*point_xy1(1)); 

	float xa = point_xy1(0)*(1 + radial_dist1*(r*r) + radial_dist2*(r*r*r*r));
	float ya = point_xy1(1)*(1 + radial_dist1*(r*r) + radial_dist2*(r*r*r*r));

	//rescale
	float img_scale = (img_width + img_height)/2;
	float step_x = img_width/2;
	float step_y = img_height/2;

	float pixel_x = xa * img_scale + step_x;
	float pixel_y = ya * img_scale + step_y;

	image_point(0) = pixel_x;
	image_point(1) = pixel_y;
}
    // This function is responsible for converting the data from the
    // kinect into an odometry message, and tranforming it to the same
    // frame that the ekf uses    
    void send_kinect_estimate(geometry_msgs::PointStamped pt,
			      geometry_msgs::PointStamped ptlast,
			      int index, int op)
	{
	    ROS_DEBUG("send_kinect_estimate triggered");

	    Eigen::Affine3d gwo;
	    Eigen::Vector3d tmp_point; 
	    tf::Transform transform;
	    geometry_msgs::PointStamped transpt, transptlast;
	    ros::Time tstamp = pt.header.stamp;
	    

	    // set transform parameters
	    transform.setOrigin(tf::Vector3(cal_pos(0),
					    cal_pos(1), cal_pos(2)));
	    transform.setRotation(tf::Quaternion(0,0,0,1));

	    // convert to Eigen:
	    tf::TransformTFToEigen(transform, gwo);
	    gwo = gwo.inverse();

	    tmp_point << pt.point.x, pt.point.y, pt.point.z;
	    tmp_point = gwo*tmp_point;
	    transpt.header.frame_id = "optimization_frame";
	    transpt.header.stamp = tstamp;
	    transpt.point.x = tmp_point(0);
	    transpt.point.y = tmp_point(1);
	    transpt.point.z = tmp_point(2);

	    tmp_point << ptlast.point.x, ptlast.point.y, ptlast.point.z;
	    tmp_point = gwo*tmp_point;
	    transptlast.header.frame_id = "optimization_frame";
	    transptlast.header.stamp = tstamp;
	    transptlast.point.x = tmp_point(0);
	    transptlast.point.y = tmp_point(1);
	    transptlast.point.z = tmp_point(2);
	    
	    ROS_DEBUG("Done transforming PointStamped messages");
	    // Let's first get the transform from /optimization_frame
	    // to /map
	    tf::StampedTransform trans_stamped;
	    geometry_msgs::PointStamped tmp;
	    try{
	    	tf.lookupTransform(
	    	    "map", "optimization_frame",
	    	    tstamp, trans_stamped);
	    	tf.transformPoint("map", transpt, tmp);

	    }
	    catch(tf::TransformException& ex){
	    	ROS_ERROR(
	    	    "Error trying to lookupTransform from /map "
	    	    "to /optimization_frame: %s", ex.what());
	    	return;
	    }
	    
	    // Now we can publish the Kinect's estimate of the robot's
	    // pose
	    std::stringstream ss;
	    ss << "base_footprint_kinect_robot_" << index;
	    kin_pose[index].header.stamp = ros::Time::now();
	    kin_pose[index].header.frame_id = "map";
	    kin_pose[index].child_frame_id = ss.str();
	    tmp.point.z = 0.0;
	    kin_pose[index].pose.pose.position = tmp.point;
	    double theta = 0.0;
	    if (op == 2)
	    {
	    	theta = atan2(transpt.point.x-
	    			     transptlast.point.x,
	    			     transpt.point.z-
	    			     transptlast.point.z);
	    	theta = clamp_angle(theta-M_PI/2.0);
		ROS_DEBUG("Calculated angle = %f",theta);					  
	    }
	    else
	    {
	    	theta = robot_start_ori[index];
	    	theta = clamp_angle(-theta);
		ROS_DEBUG("predetermined angle = %f",theta);
	    }
	    geometry_msgs::Quaternion quat = tf::createQuaternionMsgFromYaw(theta);
	    kin_pose[index].pose.pose.orientation = quat;

	    // Let's check if this is a "bad" point
	    if (bad_array[index])
	    {
		boost::array<double,36ul> tmpcov;
		for (int i=0; i<36; i++)
		    tmpcov[i] = kincov[i]*1000.0;
		kin_pose[index].pose.covariance = tmpcov;
	    }
	    else
		kin_pose[index].pose.covariance = kincov;
	    
	    ROS_DEBUG("Done filling in Odometry message");

	    // Now let's publish the estimated pose as a
	    // nav_msgs/Odometry message on a topic called /vo
	    ROS_DEBUG("publishing /vo for robot %d", index+1);
	    robots_pub[index].publish(kin_pose[index]);

	    // now, let's publish the transforms that goes along with it
	    geometry_msgs::TransformStamped kin_trans;
	    tf::Quaternion q1, q2;
	    q1 = tf::createQuaternionFromYaw(theta);
	    q2 = tf::Quaternion(1.0,0,0,0);
	    q1 = q1*q2;
	    tf::quaternionTFToMsg(q1, quat);

	    kin_trans.header.stamp = tstamp;
	    kin_trans.header.frame_id = kin_pose[index].header.frame_id;
	    kin_trans.child_frame_id = kin_pose[index].child_frame_id;
	    kin_trans.transform.translation.x = kin_pose[index].pose.pose.position.x;
	    kin_trans.transform.translation.y = kin_pose[index].pose.pose.position.y;
	    kin_trans.transform.translation.z = kin_pose[index].pose.pose.position.z;
	    kin_trans.transform.rotation = quat;

	    ROS_DEBUG("Sending transform for output of estimator node");
	    br.sendTransform(kin_trans);
	    
	    return;
	}