00001
00064 #include <math.h>
00065 #include <stdio.h>
00066 #include <stdlib.h>
00067
00068 #include <ros/ros.h>
00069 #include <pcl/point_types.h>
00070 #include <geometry_msgs/Twist.h>
00071 #include <sensor_msgs/Image.h>
00072 #include <tf/transform_listener.h>
00073 #include <Eigen/Core>
00074 #include <Eigen/Geometry>
00075 #include <nav_msgs/Odometry.h>
00076 #include <trajectory_msgs/JointTrajectory.h>
00077 #include <pcl_ros/point_cloud.h>
00078 #include <pcl/io/pcd_io.h>
00079 #include <gazebo/GetModelState.h>
00080 #include <iostream>
00081
00082 class Capture
00083 {
00084 private:
00085 double walk_vel, yaw_rate, nick_rate;
00086 geometry_msgs::Twist cmd;
00087 trajectory_msgs::JointTrajectory cmd_nick_;
00088
00089 ros::NodeHandle n_;
00090 ros::Publisher vel_pub_, nick_pub_;
00091 ros::Subscriber odo_sub_, point_cloud_sub_, image_sub_, image_depth_sub_;
00092 tf::TransformListener listener;
00093
00094 bool moving_, freeze_, first_;
00095 int not_moving_;
00096 int phase1_len_, phase2_len_, phase3_len_;
00097
00098 Eigen::Vector3f absolute_pos_, start_pos_;
00099 Eigen::Quaternionf absolute_rot_, start_rot_;
00100
00101 sensor_msgs::PointCloud2ConstPtr last_pc_;
00102 sensor_msgs::ImageConstPtr last_img_, last_depth_img_;
00103
00104 std::string prefix_;
00105 int frame_number_;
00106 FILE *fp_xml_;
00107 int mode_;
00108
00109 bool states_[4];
00110
00111 public:
00112 void init()
00113 {
00114 moving_ = true;
00115 freeze_ = false;
00116 first_ = true;
00117
00118 frame_number_=0;
00119
00120 cmd.linear.x = cmd.linear.y = cmd.angular.z = 0;
00121 cmd_nick_.joint_names.push_back("torso_lower_neck_tilt_joint");
00122 cmd_nick_.joint_names.push_back("torso_pan_joint");
00123 cmd_nick_.joint_names.push_back("torso_upper_neck_tilt_joint");
00124
00125 trajectory_msgs::JointTrajectoryPoint point;
00126 point.positions.push_back(0.);
00127 point.positions.push_back(0.);
00128 point.positions.push_back(0.);
00129 point.time_from_start = ros::Duration(0.01);
00130
00131 cmd_nick_.points.push_back(point);
00132
00133 vel_pub_ = n_.advertise<geometry_msgs::Twist>("/base_controller/command", 1);
00134 nick_pub_= n_.advertise<trajectory_msgs::JointTrajectory>("/torso_controller/command", 1);
00135 odo_sub_ = n_.subscribe("/base_controller/odometry",10,&Capture::odometrySubCallback, this);
00136 point_cloud_sub_ = n_.subscribe("/cam3d/rgb/points", 1, &Capture::pointCloudSubCallback, this);
00137 image_sub_ = n_.subscribe("/cam3d/rgb/image_raw", 1, &Capture::imageSubCallback, this);
00138 image_depth_sub_ = n_.subscribe("/cam3d/depth/image_raw", 1, &Capture::imageSubCallback_depth, this);
00139
00140 ros::NodeHandle n_private("~");
00141
00142 n_private.param("mode", mode_, 1);
00143
00144 n_private.param("walk_vel", walk_vel, 0.01);
00145 n_private.param("yaw_rate", yaw_rate, 0.01);
00146 n_private.param("nick_rate", nick_rate, 0.01);
00147 n_private.param("prefix", prefix_, std::string(""));
00148 n_private.param("phase1_len", phase1_len_, 3);
00149 n_private.param("phase2_len", phase2_len_, 10);
00150 n_private.param("phase3_len", phase3_len_, 3);
00151
00152 n_private.param("state_trans_x", states_[0], false);
00153 n_private.param("state_trans_y", states_[1], false);
00154 n_private.param("state_rot_z", states_[2], false);
00155 n_private.param("state_rot_x", states_[3], false);
00156
00157 }
00158
00159 ~Capture() { }
00160
00161 void reset_world() {system("rosservice call /gazebo/reset_world");}
00162
00163 void run();
00164
00165 void record_start() {
00166 char fn[256];
00167 sprintf(fn, "%sreplay.xml",prefix_.c_str());
00168
00169 ROS_INFO("creating %s...",fn);
00170 fp_xml_ = fopen(fn,"w");
00171
00172 ROS_ASSERT(fp_xml_);
00173
00174 fputs("<?xml version=\"1.0\" ?>\n", fp_xml_);
00175 fputs("<replay>\n", fp_xml_);
00176 }
00177
00178 void record_end() {
00179 fputs("</replay>\n", fp_xml_);
00180 fclose(fp_xml_);
00181 }
00182
00183 void record_entry() {
00184 if(!last_pc_ || !last_img_)
00185 return;
00186
00187 freeze_=true;
00188
00189 if(first_) {
00190 first_=false;
00191 start_pos_= absolute_pos_;
00192 start_rot_= absolute_rot_;
00193 }
00194
00195 char fn_pcd[256], fn_img[256], fn_img_depth[256];
00196 sprintf(fn_pcd, "%spcd_%d.pcd",prefix_.c_str(),frame_number_);
00197 sprintf(fn_img, "%simg_%d.img",prefix_.c_str(),frame_number_);
00198 sprintf(fn_img_depth, "%simg_depth_%d.img",prefix_.c_str(),frame_number_);
00199
00200 frame_number_++;
00201
00202 pcl::PointCloud<pcl::PointXYZRGB> pc;
00203 pcl::fromROSMsg(*last_pc_,pc);
00204 pcl::io::savePCDFileASCII (fn_pcd, pc);
00205
00206 #ifdef PCL_VERSION_COMPARE
00207 std::ofstream stream(fn_img);
00208 stream << *last_img_;
00209 stream.close();
00210 #else
00211
00212 FILE *fp = fopen(fn_img,"wb");
00213 if(fp)
00214 {
00215 uint32_t len = last_img_->serializationLength();
00216
00217 uint8_t *wptr = new uint8_t[len];
00218 last_img_->serialize(wptr,0);
00219 fwrite(wptr, 1, len, fp);
00220 delete [] wptr;
00221
00222 fclose(fp);
00223 }
00224 #endif
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239 Eigen::Vector3f pos= absolute_pos_ - start_pos_;
00240 Eigen::Quaternionf rot = absolute_rot_*start_rot_.inverse();
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250 fputs("\t<frame>\n", fp_xml_);
00251
00252 fputs("\t\t<pose>\n", fp_xml_);
00253
00254 fputs("\t\t\t<position>", fp_xml_);
00255 fprintf(fp_xml_,"%f,%f,%f",pos(0),pos(1),pos(2));
00256 fputs("</position>\n", fp_xml_);
00257
00258 fputs("\t\t\t<orientation>", fp_xml_);
00259 fprintf(fp_xml_,"%f,%f,%f,%f",rot.x(), rot.y(), rot.z(), rot.w());
00260 fputs("</orientation>\n", fp_xml_);
00261
00262 fputs("\t\t</pose>\n", fp_xml_);
00263
00264 fputs("\t\t<pcd>", fp_xml_);
00265 fputs(fn_pcd, fp_xml_);
00266 fputs("</pcd>\n", fp_xml_);
00267
00268 fputs("\t\t<img>", fp_xml_);
00269 fputs(fn_img, fp_xml_);
00270 fputs("</img>\n", fp_xml_);
00271
00272
00273
00274
00275
00276 fputs("\t</frame>\n", fp_xml_);
00277
00278 last_pc_.reset();
00279 last_img_.reset();
00280
00281 freeze_=false;
00282 }
00283
00284 void
00285 pointCloudSubCallback(const sensor_msgs::PointCloud2ConstPtr& pc_in)
00286 {
00287 if(freeze_)
00288 return;
00289
00290 last_pc_ = pc_in;
00291 }
00292
00293 void
00294 imageSubCallback(const sensor_msgs::ImageConstPtr& img_in)
00295 {
00296 if(freeze_)
00297 return;
00298
00299 last_img_ = img_in;
00300 }
00301
00302 void
00303 imageSubCallback_depth(const sensor_msgs::ImageConstPtr& img_in)
00304 {
00305 if(freeze_)
00306 return;
00307
00308 last_depth_img_ = img_in;
00309 }
00310
00311 void
00312 odometrySubCallback(const nav_msgs::Odometry &odometry)
00313 {
00314 if(freeze_ || mode_==2)
00315 return;
00316
00317 tf::StampedTransform transform;
00318 try{
00319 listener.lookupTransform("/base_footprint", "/head_cam3d_link",
00320 ros::Time(0), transform);
00321 }
00322 catch (tf::TransformException ex){
00323 ROS_ERROR("%s",ex.what());
00324 moving_ = true;
00325 return;
00326 }
00327
00328 ros::ServiceClient client = n_.serviceClient<gazebo::GetModelState>("/gazebo/get_model_state");
00329 gazebo::GetModelState srv;
00330
00331 srv.request.model_name = "robot";
00332
00333 if(!client.call(srv)) {
00334 ROS_ERROR("service call for gazebo model state failed");
00335 moving_ = true;
00336 return;
00337 }
00338
00339 Eigen::Vector3f pos_base, pos_rel;
00340 Eigen::Quaternionf rot_base, rot_rel;
00341
00342
00343
00344
00345 pos_base(0) = srv.response.pose.position.x;
00346 pos_base(1) = srv.response.pose.position.y;
00347 pos_base(2) = srv.response.pose.position.z;
00348
00349 pos_rel(0) = transform.getOrigin().m_floats[0];
00350 pos_rel(1) = transform.getOrigin().m_floats[1];
00351 pos_rel(2) = transform.getOrigin().m_floats[2];
00352
00353
00354
00355
00356
00357 rot_base.x() = srv.response.pose.orientation.x;
00358 rot_base.y() = srv.response.pose.orientation.y;
00359 rot_base.z() = srv.response.pose.orientation.z;
00360 rot_base.w() = srv.response.pose.orientation.w;
00361
00362 rot_rel.x() = transform.getRotation().getX();
00363 rot_rel.y() = transform.getRotation().getY();
00364 rot_rel.z() = transform.getRotation().getZ();
00365 rot_rel.w() = transform.getRotation().getW();
00366
00367
00368 {
00369 Eigen::Vector3f Y;
00370 Y(0)=Y(2)=0;Y(1)=1;
00371 Eigen::Vector3f X;
00372 X(1)=X(2)=0;X(0)=1;
00373 Eigen::AngleAxisf r1(-M_PI/2,Y), r2(-M_PI/2,X);
00374
00375 Eigen::Matrix3f R=r1.toRotationMatrix()*r2.toRotationMatrix();
00376
00377
00378
00379
00380
00381
00382
00383
00384 rot_base = R*rot_base;
00385 pos_base = R*pos_base;
00386 }
00387
00388
00389
00390
00391 Eigen::Vector3f pos= pos_base+pos_rel;
00392 Eigen::Quaternionf rot = rot_base*rot_rel;
00393
00394
00395
00396 moving_ =
00397 (pos-absolute_pos_).norm()>0.00001 ||
00398 rot.angularDistance(absolute_rot_)>0.00001;
00399
00400 absolute_pos_= pos;
00401 absolute_rot_= rot;
00402
00403 if(!moving_) {
00404 not_moving_++;
00405 }
00406 else
00407 not_moving_=0;
00408
00409 }
00410
00411 void buildState() {
00412 if(mode_==2) {
00413 ROS_INFO("please move camera to desired position");
00414 ROS_INFO("now enter:");
00415
00416 float x=0,y=0,a=0;
00417
00418 std::cout<<"translation x (in cm): ";
00419 std::cin>>x;
00420 std::cout<<"translation y (in cm): ";
00421 std::cin>>y;
00422 std::cout<<"rotation (degree): ";
00423 std::cin>>a;
00424
00425 x/=100.f;
00426 y/=100.f;
00427 a*=M_PI/180.f;
00428
00429 absolute_pos_(0)=x;
00430 absolute_pos_(1)=0;
00431 absolute_pos_(2)=y;
00432
00433 Eigen::Vector3f Y;
00434 Y(0)=Y(2)=0.f;Y(1)=1.f;
00435 Eigen::AngleAxisf aa(a,Y);
00436 absolute_rot_=Eigen::Quaternionf(aa);
00437 }
00438 else
00439 {
00440 cmd.linear.x = cmd.linear.y = cmd.angular.z = 0;
00441
00442 if(frame_number_ >= phase1_len_&& frame_number_<phase1_len_+phase2_len_) {
00443 if(states_[0]) state2_x();
00444 if(states_[1]) state2_y();
00445 if(states_[2]) state3();
00446 if(states_[3]) state4();
00447 }
00448 }
00449
00450 }
00451
00452 void state2_x() {
00453 static bool forw=true;
00454 if(absolute_pos_(0)<-2.5)
00455 forw=false;
00456 if(absolute_pos_(0)>-0.5)
00457 forw=true;
00458
00459 if(forw)
00460 cmd.linear.x = - walk_vel;
00461 else
00462 cmd.linear.x = walk_vel;
00463 }
00464
00465 void state2_y() {
00466 static bool forw=true;
00467 if(absolute_pos_(1)<-1)
00468 forw=false;
00469 if(absolute_pos_(1)>1)
00470 forw=true;
00471
00472 if(forw)
00473 cmd.linear.y = - walk_vel;
00474 else
00475 cmd.linear.y = walk_vel;
00476 }
00477
00478 void state3() {
00479 static bool forw=true;
00480
00481 static float yaw = 0.;
00482
00483 if(yaw<-0.4)
00484 forw=false;
00485 if(yaw>0.4)
00486 forw=true;
00487
00488 if(forw)
00489 yaw += -nick_rate;
00490 else
00491 yaw += nick_rate;
00492
00493 cmd_nick_.points[0].positions[1] = yaw;
00494 }
00495
00496 void state4() {
00497 static bool forw=true;
00498
00499 static float yaw = 0.;
00500
00501 if(yaw<-0.4)
00502 forw=false;
00503 if(yaw>0.4)
00504 forw=true;
00505
00506 if(forw)
00507 yaw += -nick_rate;
00508 else
00509 yaw += nick_rate;
00510
00511 cmd_nick_.points[0].positions[0] = yaw;
00512 cmd_nick_.points[0].positions[2] = 1.5*yaw;
00513 }
00514 };
00515
00516
00517 int main(int argc, char** argv)
00518 {
00519 ros::init(argc, argv, "capture");
00520
00521 Capture tpk;
00522 tpk.init();
00523
00524 tpk.reset_world();
00525 boost::thread workerThread(&Capture::run, &tpk);
00526
00527 ros::spin();
00528
00529 return(0);
00530 }
00531
00532 void Capture::run()
00533 {
00534 record_start();
00535
00536 for(;ros::ok();)
00537 {
00538
00539 ROS_INFO("move");
00540
00541 buildState();
00542
00543 vel_pub_.publish(cmd);
00544 nick_pub_.publish(cmd_nick_);
00545
00546 usleep(1000*200);
00547 while(moving_&¬_moving_<20) usleep(10000);
00548
00549
00550
00551 Eigen::Matrix3f t =absolute_rot_.toRotationMatrix();
00552
00553
00554
00555
00556
00557
00558
00559
00560 record_entry();
00561
00562 if(frame_number_ >= phase1_len_+phase2_len_+phase3_len_)
00563 break;
00564 }
00565 ROS_INFO("finished");
00566 record_end();
00567 ros::shutdown();
00568 }