Go to the documentation of this file.00001
00008 #include <rail_ceiling/calibration_from_carl.h>
00009
00010 using namespace std;
00011
00012 CalibrationFromCarl::CalibrationFromCarl()
00013 {
00014
00015 ros::NodeHandle private_nh("~");
00016
00017
00018 int numCameras;
00019 private_nh.param("num_cameras", numCameras, 5);
00020 private_nh.param("calibration_marker_id", markerID, 200);
00021
00022 calibrationEnabled.resize(numCameras);
00023 transformSamples.resize(numCameras);
00024 finalTransforms.resize(numCameras);
00025 calibrated.resize(numCameras);
00026 markerSubscribers.resize(numCameras);
00027 for (unsigned int i = 0; i < numCameras; i ++)
00028 {
00029 transformSamples[i].clear();
00030 calibrationEnabled[i] = false;
00031 calibrated[i] = false;
00032 stringstream topicStream;
00033 topicStream << "ceiling_cam_tracker_" << i << "/ar_pose_marker";
00034 markerSubscribers[i] = n.subscribe(topicStream.str(), 1, &CalibrationFromCarl::markerCallback, this);
00035 }
00036
00037 startCalibrationSubscriber = n.subscribe("start_calibration", 1, &CalibrationFromCarl::startCalibrationCallback, this);
00038 calibrationComplete = false;
00039 }
00040
00041 void CalibrationFromCarl::startCalibrationCallback(const std_msgs::Int16::ConstPtr& msg)
00042 {
00043
00044 calibrationEnabled[msg->data] = true;
00045 calibrated[msg->data] = false;
00046 transformSamples[msg->data].clear();
00047 calibrationComplete = false;
00048 }
00049
00050 void CalibrationFromCarl::markerCallback(const ar_track_alvar_msgs::AlvarMarkers::ConstPtr& msg)
00051 {
00052 for (unsigned int i = 0; i < msg->markers.size(); i ++)
00053 {
00054
00055 if (msg->markers[i].id == markerID)
00056 {
00057
00058
00059 size_t pos = msg->markers[i].header.frame_id.find("cam_");
00060 int cameraid = atoi((msg->markers[i].header.frame_id.substr(pos + 4)).c_str());
00061 if (calibrationEnabled[cameraid])
00062 {
00063 geometry_msgs::PoseStamped sample = msg->markers[i].pose;
00064 sample.header.frame_id=msg->markers[i].header.frame_id;
00065
00066
00067 tf::Transform tfSample;
00068 tf::StampedTransform finalTransform;
00069 tfSample.setOrigin(tf::Vector3(sample.pose.position.x, sample.pose.position.y, sample.pose.position.z));
00070 tfSample.setRotation(tf::Quaternion(sample.pose.orientation.x, sample.pose.orientation.y, sample.pose.orientation.z, sample.pose.orientation.w).normalize());
00071
00072 tf::Transform tfSampleInverse = tfSample.inverse();
00073 ros::Time time = ros::Time::now();
00074 br.sendTransform(tf::StampedTransform(tfSampleInverse, time, "calibration_link", sample.header.frame_id.c_str()));
00075 tfListener.waitForTransform("map", "calibration_link", time, ros::Duration(1.0));
00076 tfListener.lookupTransform("map", sample.header.frame_id, time, finalTransform);
00077
00078 transformSamples[cameraid].push_back(finalTransform);
00079 if (transformSamples[cameraid].size() >= REQUIRED_SAMPLES)
00080 {
00081 ROS_INFO("Finished calibration for camera %d", cameraid);
00082 calibrationEnabled[cameraid] = false;
00083 }
00084 }
00085 }
00086 }
00087 }
00088
00089 void CalibrationFromCarl::publishTransforms()
00090 {
00091
00092 bool finished = true;
00093 for (unsigned int i = 0; i < transformSamples.size(); i ++)
00094 {
00095
00096 if (transformSamples[i].size() >= REQUIRED_SAMPLES)
00097 {
00098 if (!calibrated[i])
00099 {
00100
00101
00102 tf::StampedTransform avgTransform;
00103 avgTransform.frame_id_ = transformSamples[i][0].frame_id_;
00104 avgTransform.child_frame_id_ = transformSamples[i][0].child_frame_id_;
00105 avgTransform.stamp_ = ros::Time::now();
00106 float x = 0.0, y = 0.0, z = 0.0;
00107
00108 tf::Quaternion avgQuat;
00109 for (unsigned int j = 0; j < transformSamples[i].size(); j++)
00110 {
00111 x += transformSamples[i][j].getOrigin().x();
00112 y += transformSamples[i][j].getOrigin().y();
00113 z += transformSamples[i][j].getOrigin().z();
00114 if (j == 0)
00115 {
00116 avgQuat = transformSamples[i][j].getRotation();
00117 }
00118 else
00119 {
00120 avgQuat.slerp(transformSamples[i][j].getRotation(), 1.0/((float)(j + 1)));
00121 }
00122
00123
00124
00125
00126
00127
00128 }
00129
00130 int numSamples = transformSamples[i].size();
00131 avgTransform.setOrigin(tf::Vector3(x/numSamples, y/numSamples, z/numSamples));
00132
00133 avgTransform.setRotation(avgQuat);
00134
00135 finalTransforms[i] = avgTransform;
00136 calibrated[i] = true;
00137 }
00138
00139 br.sendTransform(finalTransforms[i]);
00140 }
00141 else
00142 {
00143 finished = false;
00144 }
00145 }
00146
00147 if (finished && !calibrationComplete)
00148 {
00149
00150 ROS_INFO("Writing calibration...");
00151
00152 stringstream ss;
00153
00154 ss << getenv("HOME") << "/testCalibrationFile.urdf";
00155 string file_name = ss.str();
00156
00157
00158 ofstream urdf;
00159 urdf.open(file_name.c_str());
00160 if (!urdf.is_open())
00161 ROS_ERROR("Failed to open '~/%s' for writing.", file_name.c_str());
00162 else
00163 {
00164 urdf << "<?xml version=\"1.0\"?>\n";
00165 urdf << "<robot xmlns:xacro=\"http://www.ros.org/wiki/xacro\" name=\"ceiling\">\n\n";
00166
00167 urdf << " <!-- Auto-Generated from rail_ceiling/calibration Node -->\n\n";
00168
00169 urdf << " <xacro:include filename=\"$(find rail_ceiling)/urdf/camera.urdf.xacro\" />\n\n";
00170
00171 urdf << " <xacro:property name=\"PARENT\" value=\"" << "map" << "\" />\n\n";
00172
00173 urdf << " <!-- fixed frame -->\n";
00174 urdf << " <link name=\"${PARENT}\" />\n\n";
00175
00176 urdf << " <!-- " << finalTransforms.size() << " Camera(s) -->\n";
00177 for (int i = 0; i < finalTransforms.size(); i++)
00178 {
00179
00180 tf::StampedTransform &tf = finalTransforms.at(i);
00181 tf::Vector3 &pos = tf.getOrigin();
00182 double roll, pitch, yaw;
00183 tf.getBasis().getRPY(roll, pitch, yaw);
00184 urdf << " <xacro:ceiling_cam parent=\"${PARENT}\" link=\"" << tf.child_frame_id_ << i << "\">\n";
00185 urdf << " <origin xyz=\"" << pos.getX() << " " << pos.getY() << " " << pos.getZ() << "\" rpy=\"" << roll << " "
00186 << pitch << " " << yaw << "\" />\n";
00187 urdf << " </xacro:ceiling_cam>\n";
00188 }
00189 urdf << "</robot>\n\n";
00190
00191 urdf.close();
00192 ROS_INFO("Calibration written to '%s'.", file_name.c_str());
00193 }
00194
00195 calibrationComplete = true;
00196 }
00197 }
00198
00199 int main(int argc, char **argv)
00200 {
00201 ros::init(argc, argv, "calibration_from_carl");
00202
00203 CalibrationFromCarl c;
00204
00205 ros::Rate loop_rate(30);
00206 while (ros::ok())
00207 {
00208 c.publishTransforms();
00209 ros::spinOnce();
00210 loop_rate.sleep();
00211 }
00212 }