Go to the documentation of this file.00001
00008 #include <carl_tools/camera_external_calibration.h>
00009
00010 using namespace std;
00011
00012 CameraExternalCalibration::CameraExternalCalibration()
00013 {
00014
00015 ros::NodeHandle private_nh("~");
00016
00017
00018 private_nh.param("calibration_marker_id", markerID, 200);
00019
00020 calibrated = false;
00021 calibrationEnabled = false;
00022 calibrationWritten = false;
00023 transformSamples.clear();
00024
00025 asusCommandPublisher = n.advertise<std_msgs::Float64>("asus_controller/command", 1);
00026
00027 markerSubscriber = n.subscribe("asus_marker_tracker/ar_pose_marker", 1, &CameraExternalCalibration::markerCallback, this);
00028
00029
00030 this->setCameraPos();
00031 }
00032
00033 void CameraExternalCalibration::setCameraPos()
00034 {
00035 ROS_INFO("Setting camera position and waiting for autofocus/autoexposure...");
00036 std_msgs::Float64 asusCmd;
00037 asusCmd.data = 0.5;
00038 asusCommandPublisher.publish(asusCmd);
00039 ros::Duration(5.0).sleep();
00040 calibrationEnabled = true;
00041 ROS_INFO("Ready to calibrate.");
00042 }
00043
00044 void CameraExternalCalibration::markerCallback(const ar_track_alvar_msgs::AlvarMarkers::ConstPtr& msg)
00045 {
00046 if (calibrationEnabled)
00047 {
00048 for (unsigned int i = 0; i < msg->markers.size(); i++)
00049 {
00050
00051 if (msg->markers[i].id == markerID)
00052 {
00053 geometry_msgs::PoseStamped sample = msg->markers[i].pose;
00054 sample.header.frame_id = msg->markers[i].header.frame_id;
00055
00056
00057 tf::Transform tfSample;
00058 tfSample.setOrigin(tf::Vector3(sample.pose.position.x, sample.pose.position.y, sample.pose.position.z));
00059 tfSample.setRotation(tf::Quaternion(sample.pose.orientation.x, sample.pose.orientation.y, sample.pose.orientation.z, sample.pose.orientation.w).normalize());
00060
00061 tf::Transform tfSampleInverse = tfSample.inverse();
00062 ros::Time time = ros::Time::now();
00063 tf::StampedTransform tfSampleStamped(tfSampleInverse, time, "calibration_link", "calibrated_asus_camera_link");
00064 br.sendTransform(tfSampleStamped);
00065
00066 transformSamples.push_back(tfSampleStamped);
00067 if (transformSamples.size() >= REQUIRED_SAMPLES)
00068 {
00069 ROS_INFO("Finished calibration for asus.");
00070 calibrationEnabled = false;
00071 }
00072 }
00073 }
00074 }
00075 }
00076
00077 void CameraExternalCalibration::publishTransforms()
00078 {
00079
00080 bool finished = true;
00081
00082
00083 if (transformSamples.size() >= REQUIRED_SAMPLES)
00084 {
00085 if (!calibrated)
00086 {
00087
00088 tf::StampedTransform avgTransform;
00089 avgTransform.frame_id_ = transformSamples[0].frame_id_;
00090 avgTransform.child_frame_id_ = transformSamples[0].child_frame_id_;
00091 avgTransform.stamp_ = ros::Time::now();
00092 float x = 0.0, y = 0.0, z = 0.0;
00093 tf::Quaternion avgQuat;
00094 int failedSamples = 0;
00095 for (unsigned int i = 0; i < transformSamples.size(); i++)
00096 {
00097
00098 if (transformSamples[i].getOrigin().x() == 0 && transformSamples[i].getOrigin().y() == 0 && transformSamples[i].getOrigin().z() == 0)
00099 {
00100 failedSamples ++;
00101 }
00102 else
00103 {
00104 x += transformSamples[i].getOrigin().x();
00105 y += transformSamples[i].getOrigin().y();
00106 z += transformSamples[i].getOrigin().z();
00107 if (i == 0)
00108 {
00109 avgQuat = transformSamples[i].getRotation().normalize();
00110 }
00111 else
00112 {
00113 avgQuat.slerp(transformSamples[i].getRotation().normalize(), 1.0 / ((float) (i + 1 - failedSamples))).normalize();
00114 }
00115 }
00116 }
00117
00118 int numSamples = transformSamples.size() - failedSamples;
00119 avgTransform.setOrigin(tf::Vector3(x/numSamples, y/numSamples, z/numSamples));
00120 avgTransform.setRotation(avgQuat);
00121
00122 finalTransform = avgTransform;
00123 calibrated = true;
00124 }
00125
00126 finalTransform.stamp_ = ros::Time::now();
00127 br.sendTransform(finalTransform);
00128 }
00129 else
00130 {
00131 finished = false;
00132 }
00133
00134 if (finished && !calibrationWritten)
00135 {
00136
00137 tf::StampedTransform correctedTransform;
00138 tfListener.waitForTransform("asus_mount_link", "calibrated_asus_camera_link", ros::Time::now(), ros::Duration(5.0));
00139 tfListener.lookupTransform("asus_mount_link", "calibrated_asus_camera_link", ros::Time(0), correctedTransform);
00140 double roll, pitch, yaw;
00141 tf::Matrix3x3(correctedTransform.getRotation()).getRPY(roll, pitch, yaw);
00142
00143
00144 ROS_INFO("The new calibrated transform between asus_mount_link and camera_link is:\n\n"
00145 "<origin xyz=\"%f %f %f\" rpy=\"%f %f %f\" />\n",
00146 correctedTransform.getOrigin().x(), correctedTransform.getOrigin().y(), correctedTransform.getOrigin().z(),
00147 roll, pitch, yaw);
00148 ROS_INFO("If this accurate, copy the above line into the carl_asus_camera.urdf.xacro file in the carl_bot package in place of the origin line\n"
00149 "<xacro:sensor_asus_xtion_pro parent=\"asus_mount_link\">\n"
00150 " <origin ... />\n"
00151 "</xacro:sensor_asus_xtion_pro>");
00152
00153 calibrationWritten = true;
00154 }
00155 }
00156
00157 int main(int argc, char **argv)
00158 {
00159 ros::init(argc, argv, "camera_external_calibration");
00160
00161 CameraExternalCalibration c;
00162
00163 ros::Rate loop_rate(30);
00164 while (ros::ok())
00165 {
00166 c.publishTransforms();
00167 ros::spinOnce();
00168 loop_rate.sleep();
00169 }
00170 }