00001 #include <ros/ros.h>
00002 #include <ros/console.h>
00003 #include <std_msgs/Int8.h>
00004 #include <geometry_msgs/Twist.h>
00005 #include <geometry_msgs/PoseStamped.h>
00006
00007 #include <visp_bridge/3dpose.h>
00008
00009 #include <visp/vpAdaptiveGain.h>
00010 #include <visp/vpCameraParameters.h>
00011 #include <visp/vpDot.h>
00012 #include <visp/vpDot2.h>
00013 #include <visp/vpFeatureBuilder.h>
00014 #include <visp/vpFeatureDepth.h>
00015 #include <visp/vpFeaturePoint.h>
00016 #include <visp/vpHomogeneousMatrix.h>
00017 #include <visp/vpPioneerPan.h>
00018 #include <visp/vpRobot.h>
00019 #include <visp/vpServo.h>
00020 #include <visp/vpVelocityTwistMatrix.h>
00021
00022 class VS
00023 {
00024 private:
00025 ros::NodeHandle nh_;
00026 ros::Publisher pubTwistPioneer_;
00027 ros::Publisher pubTwistBiclops_;
00028 ros::Subscriber subPoseTarget_;
00029 ros::Subscriber subStatusTarget_;
00030 ros::Subscriber subBiclopsOdom_;
00031
00032 vpServo task;
00033
00034 vpFeaturePoint s_x, s_xd;
00035 vpFeatureDepth s_Z, s_Zd;
00036
00037 vpCameraParameters cam;
00038 double depth;
00039 double Z, Zd;
00040 double lambda;
00041
00042 bool valid_pose;
00043 bool valid_pose_prev;
00044
00045 double t_start_loop;
00046 double tinit;
00047
00048 vpColVector v;
00049 vpColVector vi;
00050 vpColVector qm;
00051 double qm_pan;
00052 double mu;
00053 vpAdaptiveGain lambda_adapt;
00054 vpPioneerPan robot;
00055
00056 public:
00057 void init_vs();
00058 void poseCallback(const geometry_msgs::PoseStampedConstPtr& msg);
00059 void biclopsOdomCallback(const geometry_msgs::PoseStampedConstPtr& msg);
00060 void statusCallback(const std_msgs::Int8ConstPtr& msg);
00061 VS(int argc, char**argv);
00062 virtual ~VS() {
00063 task.kill();
00064 };
00065 };
00066
00067 VS::VS(int argc, char**argv)
00068 {
00069 init_vs();
00070
00071 subPoseTarget_ = nh_.subscribe("/visp_auto_tracker/object_position", 1000, &VS::poseCallback, this);
00072 subStatusTarget_ = nh_.subscribe("/visp_auto_tracker/status", 1000, &VS::statusCallback, this);
00073 subBiclopsOdom_ = nh_.subscribe("/biclops/odom", 1000, &VS::biclopsOdomCallback, this);
00074 pubTwistPioneer_ = nh_.advertise<geometry_msgs::Twist>("vs/pioneer/cmd_vel", 1000);
00075 pubTwistBiclops_ = nh_.advertise<geometry_msgs::Twist>("vs/biclops/cmd_vel", 1000);
00076 }
00077
00078 void VS::init_vs()
00079 {
00080 depth = 0.4;
00081 lambda = 1.;
00082 valid_pose = false;
00083 valid_pose_prev = false;
00084
00085 Z = Zd = depth;
00086
00087 v.resize(2);
00088 vi.resize(2);
00089 qm.resize(2);
00090 v = 0; vi = 0; qm = 0;
00091 mu = 4;
00092 qm_pan = 0;
00093
00094
00095 lambda_adapt.initStandard(3.5, 1.5, 15);
00096
00097 cam.initPersProjWithoutDistortion(800, 795, 320, 216);
00098
00099 task.setServo(vpServo::EYEINHAND_L_cVe_eJe) ;
00100 task.setInteractionMatrixType(vpServo::DESIRED, vpServo::PSEUDO_INVERSE) ;
00101 task.setLambda(lambda_adapt) ;
00102
00103 vpVelocityTwistMatrix cVe = robot.get_cVe();
00104
00105 robot.set_eJe(qm_pan);
00106
00107 vpMatrix eJe = robot.get_eJe();
00108 task.set_eJe( eJe );
00109
00110 vpImagePoint ip(0,0);
00111
00112
00113 vpFeatureBuilder::create(s_x, cam, ip);
00114
00115
00116 s_xd.buildFrom(0, 0, Zd);
00117
00118
00119 task.addFeature(s_x, s_xd, vpFeaturePoint::selectX()) ;
00120
00121 s_Z.buildFrom(s_x.get_x(), s_x.get_y(), Z , 0);
00122 s_Zd.buildFrom(s_x.get_x(), s_x.get_y(), Zd , 0);
00123
00124
00125 task.addFeature(s_Z, s_Zd) ;
00126
00127 }
00128
00129 void VS::statusCallback(const std_msgs::Int8ConstPtr& msg)
00130 {
00131 if (msg->data == 3)
00132 valid_pose = true;
00133 else
00134 valid_pose = false;
00135 }
00136
00137 void VS::biclopsOdomCallback(const geometry_msgs::PoseStampedConstPtr& msg)
00138 {
00139 geometry_msgs::PoseStamped position;
00140 qm[1] = position.pose.orientation.x;
00141 qm[0] = position.pose.orientation.y;
00142 }
00143
00144 void VS::poseCallback(const geometry_msgs::PoseStampedConstPtr& msg)
00145 {
00146 geometry_msgs::Twist out_cmd_vel;
00147 geometry_msgs::Twist pioneer_cmd_vel;
00148 geometry_msgs::Twist biclops_cmd_vel;
00149 try {
00150 t_start_loop = vpTime::measureTimeMs();
00151
00152 std::ostringstream strs;
00153 strs << "Receive a new pose" << std::endl;
00154 std::string str;
00155 str = strs.str();
00156 ROS_DEBUG("%s", str.c_str());
00157
00158 vpHomogeneousMatrix cMo = visp_bridge::toVispHomogeneousMatrix(msg->pose);
00159
00160 vpPoint origin;
00161 origin.setWorldCoordinates(0,0,0);
00162 origin.project(cMo);
00163 Z = origin.get_Z();
00164
00165 if (Z <= 0)
00166 ROS_DEBUG("Z <= 0");
00167
00168 if (! valid_pose || Z <= 0) {
00169 ROS_DEBUG("not valid pose");
00170
00171 out_cmd_vel.linear.x = 0;
00172 out_cmd_vel.linear.y = 0;
00173 out_cmd_vel.linear.z = 0;
00174 out_cmd_vel.angular.x = 0;
00175 out_cmd_vel.angular.y = 0;
00176 out_cmd_vel.angular.z = 0;
00177 pubTwistPioneer_.publish(out_cmd_vel);
00178 pubTwistBiclops_.publish(out_cmd_vel);
00179
00180 valid_pose = false;
00181 valid_pose_prev = valid_pose;
00182
00183 return;
00184 }
00185
00186
00187 s_x.set_xyZ(origin.p[0], origin.p[1], Z);
00188
00189
00190 s_Z.buildFrom(s_x.get_x(), s_x.get_y(), Z, log(Z/Zd)) ;
00191
00192 vpVelocityTwistMatrix cVe = robot.get_cVe();
00193 task.set_cVe( cVe );
00194
00195
00196 robot.set_eJe(qm_pan);
00197
00198 vpMatrix eJe = robot.get_eJe();
00199
00200 task.set_eJe(eJe);
00201
00202
00203 v = task.computeControlLaw() ;
00204
00205 static unsigned long iter = 0;
00206
00207 if (iter == 0) {
00208
00209 ROS_INFO("Reinit visual servo");
00210
00211 tinit = t_start_loop;
00212 vi = v;
00213 }
00214 iter ++;
00215
00216
00217 double max_linear_vel = 0.5;
00218 double max_angular_vel = vpMath::rad(50);
00219 vpColVector v_max(3);
00220 v_max[0] = max_linear_vel;
00221 v_max[1] = max_angular_vel;
00222 v_max[2] = max_angular_vel;
00223
00224 vpColVector v_sat = vpRobot::saturateVelocities(v, v_max);
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234 pioneer_cmd_vel.linear.x = v_sat[0];
00235 pioneer_cmd_vel.linear.y = 0;
00236 pioneer_cmd_vel.linear.z = 0;
00237 pioneer_cmd_vel.angular.x = 0;
00238 pioneer_cmd_vel.angular.y = 0;
00239 pioneer_cmd_vel.angular.z = v_sat[1];
00240
00241 biclops_cmd_vel.linear.x = 0;
00242 biclops_cmd_vel.linear.y = 0;
00243 biclops_cmd_vel.linear.z = 0;
00244 biclops_cmd_vel.angular.x = 0;
00245 biclops_cmd_vel.angular.y = v_sat[2];
00246 biclops_cmd_vel.angular.z = 0;
00247
00248 pubTwistPioneer_.publish(pioneer_cmd_vel);
00249 if (t_start_loop - tinit>2000)
00250 pubTwistBiclops_.publish(biclops_cmd_vel);
00251 valid_pose_prev = valid_pose;
00252
00253 valid_pose = false;
00254 }
00255 catch(...) {
00256 ROS_INFO("Catch an exception: set vel to 0");
00257 out_cmd_vel.linear.x = 0;
00258 out_cmd_vel.linear.y = 0;
00259 out_cmd_vel.linear.z = 0;
00260 out_cmd_vel.angular.x = 0;
00261 out_cmd_vel.angular.y = 0;
00262 out_cmd_vel.angular.z = 0;
00263 pubTwistPioneer_.publish(out_cmd_vel);
00264 pubTwistBiclops_.publish(out_cmd_vel);
00265 }
00266 }
00267
00268 int main(int argc, char **argv)
00269 {
00270 ros::init(argc, argv, "PioneerPan");
00271
00272 VS vs(argc, argv);
00273
00274 ros::spin();
00275 }
00276
00277