00001
00002
00003
00004
00005
00006
00007
00008 #include "structure_learner_base.h"
00009 #include "utils.h"
00010
00011
00012 KinematicStructureLearner::KinematicStructureLearner():
00013 nh(),nh_local("~") {
00014 KinematicParams::LoadParams(nh_local);
00015
00016 model_pub = nh.advertise<ModelMsg> ("model", 0);
00017 marker_pub = nh.advertise<visualization_msgs::Marker> ("structure", 0);
00018
00019
00020 pose_sub1 = nh.subscribe("/marker/1", 5, &KinematicStructureLearner::poseCallback1,this);
00021 pose_sub2 = nh.subscribe("/marker/2", 5, &KinematicStructureLearner::poseCallback2,this);
00022 pose_sub3 = nh.subscribe("/marker/3", 5, &KinematicStructureLearner::poseCallback3,this);
00023 pose_sub4 = nh.subscribe("/marker/4", 5, &KinematicStructureLearner::poseCallback4,this);
00024 }
00025
00026
00027 KinematicGraph KinematicStructureLearner::getSpanningTree(bool increasing) {
00028
00029 map< int, map<int,GenericModelPtr> > E = models;
00030 vector<int> V;
00031 for(map< int, map<int,GenericModelPtr> >::iterator i=E.begin();
00032 i != E.end();i++) {
00033 if(!i->second.begin()->second) continue;
00034 V.push_back(i->first);
00035 }
00036 vector<int> V_new;
00037 KinematicGraph E_new;
00038
00039 if(V.size()==0) {
00040 ROS_INFO_STREAM("V.size()==0: empty graph");
00041 return KinematicGraph();
00042 }
00043
00044 V_new.push_back( V[0] );
00045 while(V_new.size() != V.size()) {
00046 map<double, pair< pair<int,int>,GenericModelPtr> > E_weighted;
00047
00048
00049 for(map< int, map<int,GenericModelPtr> >::iterator i=E.begin();
00050 i != E.end();i++) {
00051
00052 vector< int >::iterator result = find( V_new.begin(), V_new.end(), i->first );
00053 if (result == V_new.end()) {
00054 continue;
00055 }
00056 for(map<int,GenericModelPtr>::iterator j=i->second.begin();
00057 j != i->second.end();j++) {
00058
00059 if(increasing && i->first >= j->first) continue;
00060
00061 if(!j->second) continue;
00062
00063
00064 vector< int >::iterator result = find( V_new.begin(), V_new.end(), j->first );
00065 if (result == V_new.end()) {
00066 E_weighted[ j->second->getBIC() ] =
00067 pair< pair<int,int>,GenericModelPtr>(
00068 pair<int,int>(i->first,j->first),j->second );
00069 }
00070 }
00071 }
00072
00073 if(E_weighted.size()==0) {
00074 break;
00075 }
00076
00077 V_new.push_back( E_weighted.begin()->second.first.second);
00078 E_new.push_back( E_weighted.begin()->second );
00079 }
00080
00081 if(V_new.size() != V.size()) {
00082 ROS_INFO_STREAM("V.size()!=V_new.size(): disconnected subset exists");
00083 return KinematicGraph();
00084 }
00085 E_new.DOF = E_new.getNominalDOFs();
00086 E_new.evaluate(intersectionOfStamps(),*this,*this);
00087 return(E_new);
00088 }
00089
00090 void KinematicStructureLearner::sendModels(KinematicGraph E_new) {
00091 stringstream s;
00092 size_t id =0;
00093 for(KinematicGraphType::iterator
00094 it = E_new.begin(); it != E_new.end();it++) {
00095 s <<" ["<<it->first.first<<","<<it->first.second<<":"<<
00096 it->second->getModelName()<<"/"<<it->second->getSamples()<<"]";
00097
00098 it->second->projectConfigurationToPose();
00099 it->second->sampleConfigurationSpace( 0.1 );
00100 ModelMsg msg = it->second->getModel();
00101 msg.track.id = id;
00102 msg.id = id;
00103 msg.header.frame_id = boost::str(boost::format( "/pred/%1%") % it->first.first );
00104 model_pub.publish(msg);
00105 id++;
00106
00107 }
00108 static size_t old_ids = 0;
00109 size_t new_ids = id;
00110 while(id<old_ids) {
00111 ModelMsg msg;
00112 msg.track.id = id;
00113 msg.id = id;
00114 msg.header.frame_id = "/pred/1";
00115 model_pub.publish(msg);
00116 id++;
00117 }
00118 old_ids = new_ids;
00119
00120 ROS_INFO_STREAM("tree: "<<s.str());
00121 }
00122
00123 void KinematicStructureLearner::sendTreeTransforms(KinematicGraph graph) {
00124 if (graph.size() == 0)
00125 return;
00126
00127 double latestTimestamp = stampedMarker.rbegin()->first;
00128 PoseMap observation = getObservation(latestTimestamp);
00129 PoseMap predictionEmpty = getObservation(intersectionOfStamps().back());
00130 PoseMap prediction = graph.getPrediction(intersectionOfStamps().back(),observation,predictionEmpty,*this,*this);
00131
00132
00133 static tf::TransformBroadcaster br;
00134 const PoseStamped &latestPose =
00135 stampedMarker[latestTimestamp].begin()->second->pose;
00136 for (PoseMap::iterator it = prediction.begin(); it != prediction.end(); it++) {
00137 br.sendTransform(tf::StampedTransform(poseToTransform(it->second),
00138 latestPose.header.stamp, "/camera", boost::str(boost::format(
00139 "/pred/%1%") % it->first)));
00140 }
00141 }
00142
00143 void KinematicStructureLearner::saveGraphEval() {
00144 ofstream in_file;
00145 string pid = boost::str(boost::format( "%1%") % getpid() );
00146 in_file.open ((string("")+"graph_eval"+pid+".gnuplot").c_str());
00147 in_file.precision(10);
00148 in_file<<"set xlabel \"number of samples\""<<endl;
00149 in_file<<"set ylabel \"BIC\""<<endl;
00150 in_file<<"set key top left"<<endl;
00151 in_file<<"set output \"graph_eval"<<pid<<".eps\""<<endl;
00152 in_file<<"set terminal postscript eps enh color \"Times\""<<endl;
00153 in_file<<"set size 1.0,1.0"<<endl;
00154 in_file<<"plot \\"<<endl;
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164 map<int,int> x;
00165 for(std::map< std::string, EvalStruct>::iterator it=evalGraph.begin();it!=evalGraph.end();it++) {
00166 for(std::map<int,EvalStampStruct>::iterator j=it->second.stampEval.begin();j!=it->second.stampEval.end();j++) {
00167 x[j->first] = j->first;
00168 }
00169 }
00170 if(x.size()==0) return;
00171 map<int,int>::iterator j=x.begin(); j++;
00172 map<int,int>::iterator i=x.begin();
00173 while(j!=x.end()) {
00174 j->second = i->first;
00175 i++;
00176 j++;
00177 }
00178
00179
00180 for(std::map< std::string, EvalStruct>::iterator it=evalGraph.begin();it!=evalGraph.end();it++) {
00181 int segment = -1;
00182 int lastX = -1;
00183
00184 for(std::map<int,EvalStampStruct>::iterator j=it->second.stampEval.begin();j!=it->second.stampEval.end();j++) {
00185 if(lastX != x[j->first]) {
00186 segment++;
00187 }
00188
00189 lastX = j->first;
00190 j->second.segment = segment;
00191 j->second.segment = 0;
00192 }
00193 it->second.segments = segment+1;
00194 it->second.segments = 1;
00195
00196 }
00197
00198 bool first = true;
00199 int lt = 1;
00200 for(std::map< std::string, EvalStruct>::iterator it=evalGraph.begin();it!=evalGraph.end();it++) {
00201 if(it->second.stampEval.size()==0) continue;
00202 if(it->second.bestGraphOnce) continue;
00203 for(int i=0;i<it->second.segments;i++) {
00204 if(first) first = false; else in_file << ", \\"<< endl;
00205 in_file<<"'-' with lines ";
00206 in_file <<" lw 1 lt "<<lt<<" lc rgb '#7f7f7f' t''";
00207 }
00208 }
00209 if(!first) lt++;
00210 for(std::map< std::string, EvalStruct>::iterator it=evalGraph.begin();it!=evalGraph.end();it++) {
00211 if(it->second.stampEval.size()==0) continue;
00212 if(!it->second.bestGraphOnce) continue;
00213 for(int i=0;i<it->second.segments;i++) {
00214 if(first) first = false; else in_file << ", \\"<< endl;
00215 in_file<<"'-' with lines lt "<<lt;
00216 lt++;
00217 if(i==0) {
00218 if(it->second.stampEval.rbegin()->second.bestGraph) {
00219 in_file <<" lw 5 t'"<<it->first<<"*'";
00220 } else {
00221 in_file <<" lw 3 t'"<<it->first<<"'";
00222 }
00223 } else {
00224 if(it->second.stampEval.rbegin()->second.bestGraph) {
00225 in_file <<" lw 5 t''";
00226 } else {
00227 in_file <<" lw 3 t''";
00228 }
00229 }
00230 }
00231 }
00232 in_file<<endl<<endl;
00233 for(std::map< std::string, EvalStruct>::iterator it=evalGraph.begin();it!=evalGraph.end();it++) {
00234 if(it->second.stampEval.size()==0) continue;
00235 if(it->second.bestGraphOnce) continue;
00236 int lastSeg = 0;
00237 for( std::map<int,EvalStampStruct>::iterator j = it->second.stampEval.begin();j!=it->second.stampEval.end();j++ ) {
00238 in_file<< j->first <<"\t"<<j->second.BIC<<endl;
00239 if(lastSeg != j->second.segment) {
00240 in_file<<"e"<<endl;
00241 lastSeg = j->second.segment;
00242 }
00243 }
00244 in_file<<"e"<<endl;
00245 }
00246 for(std::map< std::string, EvalStruct>::iterator it=evalGraph.begin();it!=evalGraph.end();it++) {
00247 if(it->second.stampEval.size()==0) continue;
00248 if(!it->second.bestGraphOnce) continue;
00249 int lastSeg = 0;
00250 for( std::map<int,EvalStampStruct>::iterator j = it->second.stampEval.begin();j!=it->second.stampEval.end();j++ ) {
00251 in_file<< j->first <<"\t"<<j->second.BIC <<endl;
00252 if(lastSeg != j->second.segment) {
00253 in_file<<"e"<<endl;
00254 lastSeg = j->second.segment;
00255 }
00256 }
00257 in_file<<"e"<<endl;
00258 }
00259
00260 in_file.close();
00261 }
00262
00263 void saveIntDouble(ofstream &in_file,std::map< int, double> values) {
00264 for(std::map< int, double>::iterator i=values.begin();i!=values.end();i++) {
00265 in_file << i->first << " " << i->second<<endl;
00266 }
00267 in_file<<"e"<<endl;
00268 }
00269
00270 void KinematicStructureLearner::saveBICEval() {
00271 ofstream in_file;
00272 string pid = boost::str(boost::format( "%1%") % getpid() );
00273 in_file.open ((string("")+"bic_eval"+pid+".gnuplot").c_str());
00274 in_file.precision(10);
00275 in_file<<"set xlabel \"number of samples\""<<endl;
00276 in_file<<"set ylabel \"BIC\""<<endl;
00277 in_file<<"set key top left"<<endl;
00278 in_file<<"set output \"bic_eval"<<pid<<".eps\""<<endl;
00279 in_file<<"set terminal postscript eps enh color \"Times\""<<endl;
00280 in_file<<"set size 1.0,1.0"<<endl;
00281 in_file<<"plot \\"<<endl;
00282
00283 for(std::map< std::string, EvalStruct>::iterator it=evalGraph.begin();it!=evalGraph.end();it++) {
00284 if(it->second.stampEval.size()==0) continue;
00285 in_file<<"'-' with lines lw 1 lt 1 lc rgb '#7f7f7f' t'', \\"<<endl;
00286 }
00287
00288 in_file <<" '-' with lines lw 3 lt 1 lc rgb '#0000ff' t'spanning tree', \\"<<endl;
00289 in_file <<" '-' with lines lw 3 lt 2 lc rgb '#00ff00' t'greedy graph search', \\"<<endl;
00290 in_file <<" '-' with lines lw 3 lt 3 lc rgb '#ff0000' t'brute force graph search';"<<endl;
00291
00292 for(std::map< std::string, EvalStruct>::iterator it=evalGraph.begin();it!=evalGraph.end();it++) {
00293 for( std::map<int,EvalStampStruct>::iterator j = it->second.stampEval.begin();j!=it->second.stampEval.end();j++ ) {
00294 in_file<< j->first <<"\t"<<j->second.BIC<<endl;
00295 }
00296 in_file<<"e"<<endl;
00297 }
00298
00299 saveIntDouble(in_file,evalTreeBIC);
00300 saveIntDouble(in_file,evalFastBIC);
00301 saveIntDouble(in_file,evalGraphBIC);
00302
00303
00304 in_file.close();
00305 }
00306
00307 void KinematicStructureLearner::saveRuntimeEval() {
00308 ofstream in_file;
00309 string pid = boost::str(boost::format( "%1%") % getpid() );
00310 in_file.open ((string("")+"runtime_eval"+pid+".gnuplot").c_str());
00311 in_file.precision(10);
00312 in_file<<"set xlabel \"number of samples\""<<endl;
00313 in_file<<"set ylabel \"time [s]\""<<endl;
00314 in_file<<"set key top left"<<endl;
00315 in_file<<"set output \"runtime_eval"<<pid<<".eps\""<<endl;
00316 in_file<<"set terminal postscript eps enh color \"Times\""<<endl;
00317 in_file<<"set size 1.0,1.0"<<endl;
00318 in_file<<"plot \\"<<endl;
00319
00320 in_file <<" '-' with lines lw 3 lt 4 lc rgb '#000000' t'local models', \\"<<endl;
00321 in_file <<" '-' with lines lw 3 lt 1 lc rgb '#0000ff' t'spanning tree', \\"<<endl;
00322 in_file <<" '-' with lines lw 3 lt 2 lc rgb '#00ff00' t'greedy graph search', \\"<<endl;
00323 in_file <<" '-' with lines lw 3 lt 3 lc rgb '#ff0000' t'brute force graph search';"<<endl;
00324
00325 saveIntDouble(in_file,evalModelsRuntime);
00326 saveIntDouble(in_file,evalTreeRuntime);
00327 saveIntDouble(in_file,evalFastRuntime);
00328 saveIntDouble(in_file,evalGraphRuntime);
00329
00330 in_file.close();
00331 }
00332
00333 void KinematicStructureLearner::saveDOFLinkEval() {
00334 ofstream in_file;
00335 string pid = boost::str(boost::format( "%1%") % getpid() );
00336 in_file.open ((string("")+"doflink_eval"+pid+".gnuplot").c_str());
00337 in_file.precision(10);
00338 in_file<<"set xlabel \"number of samples\""<<endl;
00339 in_file<<"set ylabel \"time [s]\""<<endl;
00340 in_file<<"set key top left"<<endl;
00341 in_file<<"set output \"doflink_eval"<<pid<<".eps\""<<endl;
00342 in_file<<"set terminal postscript eps enh color \"Times\""<<endl;
00343 in_file<<"set size 1.0,1.0"<<endl;
00344 in_file<<"plot \\"<<endl;
00345
00346 in_file <<" '-' with lines lw 3 lt 4 lc rgb '#000000' t'DOFs', \\"<<endl;
00347 in_file <<" '-' with lines lw 3 lt 1 lc rgb '#0000ff' t'Links'"<<endl;
00348
00349 saveIntDouble(in_file,evalDOF);
00350 saveIntDouble(in_file,evalLinks);
00351
00352 in_file.close();
00353 }
00354
00355
00356 void KinematicStructureLearner::sendStructureVisualization(KinematicGraph graph) {
00357
00358 if(!graph.size()) return;
00359
00360 std::vector<double> stamps = intersectionOfStamps();
00361 PoseMap observationMarkers = getObservation(stamps.back());
00362 PoseMap predictionEmpty = getObservation(intersectionOfStamps().back());
00363 PoseMap predictedMarkers = graph.getPrediction(stamps.back(),observationMarkers,predictionEmpty,*this,*this);
00364
00365 static tf::TransformListener listener;
00366
00367 visualization_msgs::Marker marker;
00368 marker.header.frame_id = "/camera";
00369 marker.header.stamp = ros::Time::now();
00370 marker.ns = "structure";
00371 marker.id = 0;
00372 marker.type = visualization_msgs::Marker::LINE_LIST;
00373 marker.action = visualization_msgs::Marker::ADD;
00374 marker.pose.orientation.w = 1.0;
00375 marker.scale.x = 0.005;
00376 marker.scale.y = 0.005;
00377 marker.scale.z = 0.005;
00378 marker.color.r = 0.0f;
00379 marker.color.g = 0.0f;
00380 marker.color.b = 1.0f;
00381 marker.color.a = 1.0;
00382 marker.lifetime = ros::Duration();
00383
00384 visualization_msgs::Marker text_marker = marker;
00385 text_marker.type = visualization_msgs::Marker::TEXT_VIEW_FACING;
00386 text_marker.ns = "model_names";
00387 text_marker.scale.x = 0.035;
00388 text_marker.scale.y = 0.035;
00389 text_marker.scale.z = 0.035;
00390
00391 static int old_marker_id = 0;
00392 static int old_text_marker_id = 0;
00393 int model_count=0;
00394 for(KinematicGraphType::iterator
00395 it = graph.begin(); it != graph.end();it++)
00396 {
00397 double model_r = model_count / (double)graph.size();
00398
00399 if(it->second->model.track.pose_projected.size()==0) continue;
00400
00401 if(it->second->getModelName() == "rigid") {
00402 marker.color = HSV_to_RGB(0.0,0.0,model_r/3 + 0.3);
00403 marker.id++;
00404 marker.points.clear();
00405 marker.points.push_back(predictedMarkers[it->first.first ].position);
00406 marker.points.push_back(predictedMarkers[it->first.second].position);
00407 marker_pub.publish(marker);
00408
00409 } else
00410 if(it->second->getModelName() == "prismatic") {
00411 marker.color = HSV_to_RGB((model_r-0.5)/6 + 0.15,1.0,1.0);
00412 marker.id++;
00413 marker.points.clear();
00414 marker.points.push_back(predictedMarkers[it->first.first ].position);
00415 marker.points.push_back(predictedMarkers[it->first.second].position);
00416 marker_pub.publish(marker);
00417 } else
00418 if(it->second->getModelName() == "rotational") {
00419 geometry_msgs::Point rot_center = vectorToPosition( poseToTransform(predictedMarkers[it->first.first ])*
00420 boost::static_pointer_cast<RotationalModel>(it->second)->rot_center);
00421
00422 marker.color = HSV_to_RGB((model_r-0.5)/6 + 0.66,0.5,0.5);
00423
00424 marker.id++;
00425 marker.points.clear();
00426 marker.points.push_back(predictedMarkers[it->first.first ].position);
00427 marker.points.push_back(rot_center );
00428 marker_pub.publish(marker);
00429
00430 marker.color = HSV_to_RGB((model_r-0.5)/6 + 0.66,1.0,1.0);
00431
00432 marker.id++;
00433 marker.points.clear();
00434 marker.points.push_back(rot_center );
00435 marker.points.push_back(predictedMarkers[it->first.second].position);
00436 marker_pub.publish(marker);
00437
00438 } else
00439 if(it->second->getModelName() == "pca_gp") {
00440 marker.color = HSV_to_RGB((model_r-0.5)/6 + 0.33,1.0,1.0);
00441 marker.id++;
00442 marker.points.clear();
00443 marker.points.push_back(predictedMarkers[it->first.first ].position);
00444 marker.points.push_back(predictedMarkers[it->first.second].position);
00445 marker_pub.publish(marker);
00446 } else
00447 {
00448 marker.color = HSV_to_RGB(0,0,0);
00449 marker.id++;
00450 marker.points.clear();
00451 marker.points.push_back(predictedMarkers[it->first.first ].position);
00452 marker.points.push_back(predictedMarkers[it->first.second].position);
00453 marker_pub.publish(marker);
00454 }
00455
00456
00457 text_marker.id++;
00458 text_marker.text = it->second->getModelName();
00459 text_marker.pose.position.x = (predictedMarkers[it->first.first ].position.x + predictedMarkers[it->first.second ].position.x)/2;
00460 text_marker.pose.position.y = (predictedMarkers[it->first.first ].position.y + predictedMarkers[it->first.second ].position.y)/2;
00461 text_marker.pose.position.z = (predictedMarkers[it->first.first ].position.z + predictedMarkers[it->first.second ].position.z)/2;
00462 text_marker.color = marker.color;
00463 marker_pub.publish(text_marker);
00464
00465 model_count++;
00466 }
00467
00468 text_marker.pose.position.x = 0;
00469 text_marker.pose.position.y = +0.16;
00470 text_marker.pose.position.z = 1;
00471 text_marker.color.r=1.0;
00472 text_marker.color.g=1.0;
00473 text_marker.color.b=1.0;
00474 text_marker.scale.x = 0.025;
00475 text_marker.scale.y = 0.025;
00476 text_marker.scale.z = 0.025;
00477 text_marker.text = boost::str(boost::format( "selected model: %d DOF, %d links") % graph.DOF % graph.size() );
00478 text_marker.id++;
00479 marker_pub.publish(text_marker);
00480 text_marker.pose.position.y += 0.028;
00481
00482 text_marker.text = boost::str(boost::format( "global error: %0.3fm, %0.3frad (%d samples)") % graph.avg_pos_err % graph.avg_orient_err % intersectionOfStamps().size());
00483 text_marker.id++;
00484 marker_pub.publish(text_marker);
00485 text_marker.pose.position.y += 0.028;
00486
00487 text_marker.scale.x = 0.02;
00488 text_marker.scale.y = 0.02;
00489 text_marker.scale.z = 0.02;
00490 text_marker.text = boost::str(boost::format( "kinematic structure: %s") % graph.getTreeName(true,true,false) );
00491 text_marker.id++;
00492 marker_pub.publish(text_marker);
00493
00494
00495 int new_marker_id = marker.id;
00496 int new_text_marker_id = text_marker.id;
00497 while(marker.id < old_marker_id) {
00498 marker.id++;
00499 marker.action = visualization_msgs::Marker::DELETE;
00500 marker_pub.publish(marker);
00501 }
00502
00503 while(text_marker.id < old_text_marker_id) {
00504 text_marker.id++;
00505 text_marker.action = visualization_msgs::Marker::DELETE;
00506 marker_pub.publish(text_marker);
00507 }
00508 old_marker_id = new_marker_id;
00509 old_text_marker_id = new_text_marker_id;
00510
00511 }
00512
00513 std::vector<double> KinematicStructureLearner::downsampleStamps(std::vector<double> vec,size_t num) {
00514 std::vector<int> idx;
00515 for(size_t i=0;i<vec.size();i++) idx.push_back(i);
00516 random_shuffle( idx.begin(), idx.end() );
00517 if(num<vec.size())
00518 idx.erase(idx.begin()+num,idx.end());
00519 sort(idx.begin(),idx.end());
00520 std::vector<double> res;
00521 for(size_t i=0;i<vec.size() && i<num;i++)
00522 res.push_back( vec[ idx[i] ] );
00523 return(res);
00524 }
00525
00526 int dist(string a,string b) {
00527 int d = fabs(a.length()-b.length());
00528 for(size_t i=0;i<a.length() && i<b.length();i++) {
00529 if(a[i] != b[i]) d++;
00530 }
00531 return( d );
00532 }
00533
00534 void KinematicStructureLearner::addPreviousGraphs() {
00535 cout <<"adding previous graphs, n="<<previousGraphs.size()<<endl;
00536
00537 for(map< string, KinematicGraph >::iterator it= previousGraphs.begin();it!=previousGraphs.end();it++) {
00538 if(graphMap.find(it->first) != graphMap.end()) continue;
00539
00540 KinematicGraph graph(it->second,true);
00541 bool skip_this = false;
00542 for(KinematicGraph::iterator j=graph.begin();j!=graph.end();j++) {
00543 bool updated = false;
00544 for(std::vector<articulation_models::GenericModelPtr>::iterator
00545 k=models_all[j->first.first][j->first.second].begin();k!=models_all[j->first.first][j->first.second].end();k++) {
00546 if(k->get()->getModelName() == j->second->getModelName()) {
00547 j->second = *k;
00548 updated = true;
00549 break;
00550 }
00551 }
00552 if(!updated) {
00553 skip_this = true;
00554 cout <<"skipping model because not all models updatable:"<<graph.getTreeName(true,false,true)<<endl;
00555 break;
00556 }
00557 }
00558 if(!skip_this) {
00559 graphMap[ it->first ] = graph;
00560 cout <<"adding previous "<<graph.getTreeName(true,false,true)<<endl;
00561 }
00562 }
00563 }
00564
00565 void KinematicStructureLearner::selectSceneModel() {
00566 std::vector<double> stamps= intersectionOfStamps();
00567
00568 if(stamps.size()==0) {
00569 cout <<"no intersecting timestamps.."<<endl;
00570 return;
00571 }
00572
00573 if(full_eval=="tree") {
00574 evalTree();
00575 }
00576
00577 if(full_eval=="full") {
00578 evalFull();
00579 } else
00580
00581 if(full_eval=="fast") {
00582
00583 evalFast(true);
00584 } else {
00585 cerr <<"warning!!! unknown evaluation type: full_eval="<<full_eval<<endl;
00586 }
00587 }
00588
00589 void KinematicStructureLearner::evalTree() {
00590 ros::Time t = ros::Time::now();
00591
00592 std::vector<double> stamps= intersectionOfStamps();
00593 currentGraph = getSpanningTree(true);
00594 currentGraph.evaluate(stamps,*this,*this);
00595 evalTreeRuntime[stamps.size()] = (ros::Time::now() - t).toSec();
00596
00597 evalDOF[stamps.size()] = currentGraph.DOF;
00598 evalLinks[stamps.size()] = currentGraph.size();
00599
00600 sendTreeTransforms(currentGraph);
00601
00602 evalGraph[currentGraph.getTreeName(true,false,true)].stampEval[stamps.size()].bestTree = true;
00603 evalGraph[currentGraph.getTreeName(true,false,true)].stampEval[stamps.size()].BIC = currentGraph.BIC;
00604 evalTreeBIC[stamps.size()] = currentGraph.BIC;
00605 saveGraphEval();
00606 saveBICEval();
00607 saveRuntimeEval();
00608
00609 }
00610
00611 void KinematicStructureLearner::evalFull() {
00612 ros::Time t = ros::Time::now();
00613
00614 std::vector<double> stamps= intersectionOfStamps();
00615 KinematicGraph tree;
00616
00617 KinematicGraph bestGraph;
00618 enumerateGraphs();
00619 addPreviousGraphs();
00620
00621 for(map< string, KinematicGraph >::iterator j=graphMap.begin();j!=graphMap.end();j++) {
00622 KinematicGraph& copyOfTree = j->second;
00623 string gname_short = copyOfTree.getTreeName(false,false,true);
00624 string gname_models = copyOfTree.getTreeName(true,false,true);
00625 string gname_models_samples = copyOfTree.getTreeName(true,false,true);
00626 copyOfTree.evaluate(stamps,*this,*this);
00627 if(evalGraph.find(gname_models) == evalGraph.end()) {
00628
00629
00630
00631
00632 string previous_model;
00633 int previous_time=0;
00634 for(std::map< std::string, EvalStruct>::iterator k=evalGraph.begin();k != evalGraph.end();k++) {
00635 int t = 0;
00636 for(std::map<int,EvalStampStruct>::iterator l=k->second.stampEval.begin();l!=k->second.stampEval.end();l++) {
00637 if(l->first > t && l->first < (int)stamps.size())
00638 t = l->first;
00639 }
00640 if( k->second.stampEval.find(t) != k->second.stampEval.end() && (t>previous_time || dist(previous_model,gname_models) > dist(k->first,gname_models)) ) {
00641 previous_model = k->first;
00642 previous_time = t;
00643 }
00644 }
00645 if(previous_model.length()) {
00646 evalGraph[gname_models].stampEval[previous_time] = evalGraph[previous_model].stampEval[previous_time];
00647 }
00648
00649 }
00650 evalGraph[gname_models].stampEval[stamps.size()].BIC = copyOfTree.BIC;
00651
00652 if(copyOfTree.BIC < bestGraph.BIC) {
00653 bestGraph = copyOfTree;
00654 }
00655 cout <<"adding "<<copyOfTree.getTreeName(true,true,true)<<endl;;
00656
00657
00658 static ros::NodeHandle n;
00659 if(!n.ok()) return;
00660
00661 }
00662
00663 currentGraph = bestGraph;
00664 if(currentGraph.DOF != -1) {
00665 string gname_models = currentGraph.getTreeName(true,false,true);
00666 evalGraph[gname_models].stampEval[stamps.size()].BIC = currentGraph.BIC;
00667 cout <<"*** STORING evalGraph"<<gname_models<<" bic" <<currentGraph.BIC<<endl;
00668 evalGraph[gname_models].stampEval[stamps.size()].bestGraph = true;
00669 evalGraph[gname_models].bestGraphOnce= true;
00670
00671 evalDOF[stamps.size()] = currentGraph.DOF;
00672 evalLinks[stamps.size()] = currentGraph.size();
00673
00674 previousGraphs[currentGraph.getTreeName(true,false,true)] = currentGraph;
00675
00676 evalGraphBIC[stamps.size()] = currentGraph.BIC;
00677 }
00678 evalGraphRuntime[stamps.size()] = (ros::Time::now() - t).toSec();
00679
00680 showEvaluation();
00681
00682
00683 evalFast(false);
00684
00685 saveGraphEval();
00686 saveBICEval();
00687 saveRuntimeEval();
00688 saveDOFLinkEval();
00689 }
00690
00691 void KinematicStructureLearner::evalFast(bool setCurrent) {
00692 ros::Time t = ros::Time::now();
00693
00694 std::vector<double> stamps= intersectionOfStamps();
00695 if(setCurrent)
00696 enumerateGraphs();
00697
00698
00699 KinematicGraph tree = getSpanningTree(true);
00700 tree.evaluate(stamps,*this,*this);
00701 evalTreeRuntime[stamps.size()] = (ros::Time::now() - t).toSec();
00702
00703 cout <<"spanning tree: "<<tree.getTreeName(true,false,true)<<endl;
00704
00705 string current;
00706 for(map< string, KinematicGraph >::iterator j=graphMap.begin();j!=graphMap.end();j++) {
00707
00708 if(tree.distanceTo(j->second)==0) {
00709 current = j->second.getTreeName(true,false,true);
00710 break;
00711 }
00712 }
00713 cout <<"starting from current graph: "<<current<<endl;
00714 cout <<"finding neighbors, total graphs = "<<graphMap.size()<<endl;
00715
00716 if(graphMap.find(current)==graphMap.end()) {
00717 cout <<"current graph is not in graphMap???"<<endl;
00718 return;
00719 }
00720
00721 graphMap[current].evaluate(stamps,*this,*this);
00722 evalGraph[current].stampEval[stamps.size()].BIC = graphMap[current].BIC;
00723 evalGraph[current].stampEval[stamps.size()].bestTree = true;
00724 evalGraph[current].stampEval[stamps.size()].evalInFastSearch = true;
00725 evalTreeBIC[stamps.size()] = graphMap[current].BIC;
00726
00727
00728
00729
00730
00731
00732 int evals = 0;
00733 cout <<" starting "<<graphMap[current].BIC<<" "<<current<<" pos="<<graphMap[current].avg_pos_err<<" orient="<<graphMap[current].avg_orient_err<< endl;
00734 string previous;
00735 while(current!=previous) {
00736 previous = current;
00737
00738
00739 for(map< string, KinematicGraph >::iterator j=graphMap.begin();j!=graphMap.end();j++) {
00740 if(graphMap[current].distanceTo(j->second)==1) {
00741 evals ++;
00742
00743 j->second.evaluate(stamps,*this,*this);
00744 evalGraph[j->second.getTreeName(true,false,true)].stampEval[stamps.size()].BIC = j->second.BIC;
00745
00746 evalGraph[j->second.getTreeName(true,false,true)].stampEval[stamps.size()].evalInFastSearch = true;
00747 cout <<" evaluating "<< j->second.BIC<<" ("<< evalGraph[j->second.getTreeName(true,true,true)].stampEval[stamps.size()].BIC <<"): "<<j->second.getTreeName(true,true,true)<<" pos="<<j->second.avg_pos_err<<" orient="<<j->second.avg_orient_err<< endl;
00748 if(j->second.BIC < graphMap[current].BIC) {
00749 current = j->second.getTreeName(true,false,true);
00750 break;
00751 }
00752 } else {
00753
00754 }
00755 }
00756 cout <<graphMap[current].BIC<<" "<<current<<endl;
00757 }
00758 evalGraph[current].stampEval[stamps.size()].bestFast = true;
00759 evalFastBIC[stamps.size()] = graphMap[current].BIC;
00760
00761 cout <<"final: "<<graphMap[current].BIC<<" "<<current<<" pos="<<graphMap[current].avg_pos_err<<" orient="<<graphMap[current].avg_orient_err<< " stamps="<<stamps.size()<<endl;
00762 cout <<" evals: "<<evals;
00763 cout << endl;
00764
00765 if(setCurrent) {
00766 currentGraph = graphMap[current];
00767 evalDOF[stamps.size()] = currentGraph.DOF;
00768 evalLinks[stamps.size()] = currentGraph.size();
00769
00770 saveGraphEval();
00771 saveBICEval();
00772 saveRuntimeEval();
00773 saveDOFLinkEval();
00774 }
00775 evalFastRuntime[stamps.size()] = (ros::Time::now() - t).toSec();
00776 }
00777
00778 void KinematicStructureLearner::enumerateGraphs() {
00779
00780 graphMap.clear();
00781 KinematicGraph tree;
00782 map<int,int> marker_to_vertex;
00783 map<int,int> vertex_to_marker;
00784 int n=0;
00785 for(map<int,double>::iterator it = latestTimestamp.begin();
00786 it != latestTimestamp.end(); it++ ) {
00787 marker_to_vertex[it->first] = n;
00788 vertex_to_marker[n] = it->first;
00789 n++;
00790 }
00791
00792 int vertices = models.size();
00793 int edges = vertices*vertices;
00794
00795
00796
00797 for(long graph=1; graph < (1<<(edges-1)); graph++) {
00798
00799 std::vector<bool> connected(vertex_to_marker.size(),false);
00800 connected[0] = true;
00801 tree.clear();
00802 for(int e=0;e<edges;e++) {
00803 if((graph & (1<<e))>0) {
00804
00805 int e_from = vertex_to_marker[e / vertices];
00806 int e_to = vertex_to_marker[e % vertices];
00807 if(e_from>=e_to){
00808 tree.clear();
00809 break;
00810 }
00811 connected[e % vertices] = connected[e / vertices];
00812 if(!models[e_from][e_to]) {
00813 tree.clear();
00814 break;
00815 }
00816 if(!models[e_to][e_from]) {
00817 tree.clear();
00818 break;
00819 }
00820 tree.push_back(pair< pair<int,int>,GenericModelPtr>(pair<int,int>(e_from,e_to),models[e_from][e_to]));
00821
00822 }
00823 }
00824 tree.DOF = tree.getNominalDOFs();
00825 if((int)tree.size()<vertices-1) continue;
00826 if( restrict_graphs ) {
00827 if(
00828 (restricted_graphs.find(" "+tree.getTreeName(false,false,false)+" ")==restricted_graphs.npos) &&
00829 (restricted_graphs.find(" "+tree.getTreeName(true,false,false)+" ")==restricted_graphs.npos) &&
00830 (restricted_graphs.find(" "+tree.getTreeName(true,true,false)+" ")==restricted_graphs.npos) &&
00831 (restricted_graphs.find(" "+tree.getTreeName(true,true,true)+" ")==restricted_graphs.npos) )
00832 continue;
00833 }
00834
00835 bool allConnected = true;
00836 for(size_t i=0;i<connected.size();i++) {
00837 if(!connected[i]) allConnected=false;
00838 }
00839 if(allConnected) {
00840
00841
00842 KinematicGraph basetree = tree;
00843 tree.clear();
00844 int combination_total = 1;
00845 for(KinematicGraphType::iterator it=basetree.begin();it!=basetree.end();it++) {
00846 combination_total *= models_all[it->first.first][it->first.second].size();
00847 }
00848
00849 for(int combination=0;combination<combination_total;combination++) {
00850 if(search_all_models) {
00851 tree.clear();
00852 int c_tmp = combination;
00853 for(KinematicGraphType::iterator it=basetree.begin();it!=basetree.end();it++) {
00854 int idx = c_tmp % models_all[it->first.first][it->first.second].size();
00855 tree.push_back( pair< pair<int,int>,GenericModelPtr> ( pair<int,int>(it->first.first,it->first.second), models_all[it->first.first][it->first.second][idx]));
00856 c_tmp /= models_all[it->first.first][it->first.second].size();
00857 }
00858 } else {
00859 tree = basetree;
00860 }
00861
00862 int DOFs = tree.getNominalDOFs();
00863 tree.DOF = DOFs;
00864
00865 for(int reducedDOFs=(reduce_dofs?(DOFs==0?0:1):DOFs);reducedDOFs<=DOFs;reducedDOFs++) {
00866 KinematicGraph copyOfTree(tree,true);
00867 copyOfTree.DOF = reducedDOFs;
00868 graphMap[copyOfTree.getTreeName(true,false,true)] = KinematicGraph(copyOfTree,true);
00869 }
00870 if(!search_all_models) break;
00871 }
00872 }
00873 }
00874 }
00875
00876 void KinematicStructureLearner::showEvaluation() {
00877 cout <<"Evaluation @ t="<<intersectionOfStamps().size()<<endl;
00878 map<double, KinematicGraph> sorted;
00879 for(map< string, KinematicGraph >::iterator it = graphMap.begin();it!=graphMap.end();it++) {
00880 sorted[it->second.BIC] = it->second;
00881 }
00882 for(map<double, KinematicGraph>::iterator it = sorted.begin();it!=sorted.end();it++) {
00883 cout << it->first <<" " << it->second.getTreeName(true,true,true)<<" pos="<<it->second.avg_pos_err<<" orient="<<it->second.avg_orient_err<< endl;
00884 }
00885 cout <<"---"<<endl;
00886 }
00887
00888 void KinematicStructureLearner::sendSceneModel() {
00889
00890 sendTreeTransforms(currentGraph);
00891 sendModels(currentGraph);
00892 sendStructureVisualization(currentGraph);
00893 }
00894
00895 void KinematicStructureLearner::poseCallback(const PoseStampedIdMsgConstPtr& pose) {
00896
00897 boost::mutex::scoped_lock a(frame_mutex_);
00898 double stamp = pose->pose.header.stamp.toSec();
00899 size_t id = pose->id;
00900
00901
00902 tf::Transform seen_marker = poseToTransform(pose->pose.pose);
00903 for (map<int, map<double, PoseStampedIdMsgConstPtr> >::iterator it =
00904 markerStamped.begin(); it != markerStamped.end(); it++) {
00905 if((size_t)it->first == id) continue;
00906 if(it->second.size()==0) continue;
00907
00908 Pose p;
00909 p = it->second.rbegin()->second->pose.pose;
00910 tf::Transform other_marker = poseToTransform( p );
00911 tf::Transform diff_to_known = seen_marker.inverseTimes( other_marker);
00912 double diff_position = diff_to_known.getOrigin().length();
00913
00914
00915 if(diff_position < sigma_position) {
00916 cout <<"skipping false positive marker detection"<<endl;
00917 return;
00918 }
00919
00920 }
00921
00922
00923
00924
00925 for (map<int, PoseStampedIdMsgConstPtr>::iterator it =
00926 stampedMarker[stamp].begin(); it != stampedMarker[stamp].end(); it++) {
00927 if (it->second->id == id)
00928 continue;
00929 addPose(pose->pose, it->second->pose, id, it->second->id,*this);
00930 addPose(it->second->pose, pose->pose, it->second->id, id,*this);
00931
00932 static tf::TransformBroadcaster br;
00933 br.sendTransform( tf::StampedTransform(
00934 poseToTransform( pose->pose.pose ),
00935 pose->pose.header.stamp,
00936 "/camera",
00937 boost::str(boost::format( "/marker/%1%") % pose->id)
00938 ));
00939
00940 }
00941
00942 stampedMarker[stamp][pose->id] = pose;
00943 markerStamped[pose->id][stamp] = pose;
00944 }
00945
00946 void KinematicStructureLearner::poseCallback(const PoseStampedConstPtr& pose, size_t id) {
00947 latestTimestamp[id] = pose->header.stamp.toSec();
00948
00949 bool invalid = false;
00950 if(pose->pose.position.x == 0 && pose->pose.position.y == 0 && pose->pose.position.z == 0 &&
00951 pose->pose.orientation.x == 0 && pose->pose.orientation.y == 0 && pose->pose.orientation.z == 0 && pose->pose.orientation.w == 0
00952 ) invalid = true;
00953
00954 if(!invalid) {
00955 PoseStampedIdMsgPtr p = boost::make_shared<PoseStampedIdMsg>();
00956 p->pose = *pose;
00957 p->id = id;
00958 poseCallback(p);
00959 }
00960
00961 bool allDone = true;
00962
00963 for(map<int, double >::iterator it=latestTimestamp.begin();it!=latestTimestamp.end();it++) {
00964 if(latestTimestamp.begin()->second != it->second) allDone = false;
00965
00966 }
00967
00968
00969
00970 static size_t last_stamp = 0;
00971 if(allDone) {
00972 int a = ((int)pow(intersectionOfStamps().size(),1.00/eval_every_power));
00973 int b = (((int)pow(last_stamp,1.00/eval_every_power)));
00974 if ( (a%eval_every == 0)
00975 && ( a>b ) ) {
00976
00977 last_stamp = intersectionOfStamps().size();
00978 b = (((int)pow(last_stamp,1.00/eval_every_power)));
00979 cout << "stamps="<<intersectionOfStamps().size()<<endl;
00980 ros::Time t1 = ros::Time::now();
00981 cout << "updating models.."<<endl;
00982
00983 for(map< int, map<int,TrackMsgPtr> >::iterator i=trajectories.begin();
00984 i != trajectories.end();i++) {
00985 for(map<int,TrackMsgPtr >::iterator j = i->second.begin();
00986 j != i->second.end();j++) {
00987
00988 updateModel(i->first,j->first,*this);
00989
00990 }
00991 }
00992 ros::Time t2 = ros::Time::now();
00993 evalModelsRuntime[last_stamp] = (t2-t1).toSec();
00994
00995 cout << "selecting scene model.."<<endl;
00996 selectSceneModel();
00997 ros::Time t3 = ros::Time::now();
00998 cout <<"updating models took "<< (t2-t1).toSec() <<"s, graph selection took "<<(t3-t2).toSec()<<"s"<<endl;
00999 sendSceneModel();
01000 }
01001 }
01002 }
01003
01004
01005 void KinematicStructureLearner::poseCallback1(const PoseStampedConstPtr& pose) {
01006 poseCallback( pose,1 );
01007 }
01008
01009 void KinematicStructureLearner::poseCallback2(const PoseStampedConstPtr& pose) {
01010 poseCallback( pose,2);
01011 }
01012
01013 void KinematicStructureLearner::poseCallback3(const PoseStampedConstPtr& pose) {
01014 poseCallback( pose,3 );
01015 }
01016
01017 void KinematicStructureLearner::poseCallback4(const PoseStampedConstPtr& pose) {
01018 poseCallback( pose,4 );
01019 }
01020
01021 void KinematicStructureLearner::analyzeTopologyOfGraphs() {
01022
01023 map<string,bool> isHead;
01024 for(map< string, KinematicGraph >::iterator i=graphMap.begin();i!=graphMap.end();i++) {
01025
01026 isHead[i->second.getTreeName(true,false,true)] = true;
01027 for(map< string, KinematicGraph >::iterator j=graphMap.begin();j!=graphMap.end();j++) {
01028
01029
01030 if(i->second.distanceTo(j->second)<=1) {
01031
01032 if(j->second.BIC < i->second.BIC) {
01033 isHead[i->second.getTreeName(true,false,true)] = false;
01034 }
01035 }
01036 }
01037 }
01038
01039
01040 cout <<"found heads: ";
01041 for(map<string,bool>::iterator i=isHead.begin();i!=isHead.end();i++) {
01042 if(i->second) {
01043 cout <<" "<<i->first;
01044 if(i->first == currentGraph.getTreeName(true,false,true) ) {
01045 cout <<"*";
01046 }
01047 cout<<endl;
01048 }
01049 }
01050 cout <<"---"<<endl;
01051
01052
01053 KinematicGraph tree = getSpanningTree(true);
01054 string current = tree.getTreeName(true,false,true);
01055 string previous;
01056 cout <<"spanning tree: "<<current<<endl;
01057
01058 for(map< string, KinematicGraph >::iterator j=graphMap.begin();j!=graphMap.end();j++) {
01059 if(tree.distanceTo(j->second)==0) {
01060 current = j->first;
01061 cout <<"distance zero. "<<current<<endl;
01062 break;
01063 }
01064 }
01065 cout <<"(modified) spanning tree: "<<current<<endl;
01066
01067 if(graphMap.find(current)==graphMap.end()) {
01068 cout <<"spanning tree not in graphMap???"<<endl;
01069 return;
01070 }
01071 int evals = 0;
01072 cout <<graphMap[current].BIC<<" "<<current<<endl;
01073 while(current!=previous) {
01074 previous = current;
01075 for(map< string, KinematicGraph >::iterator j=graphMap.begin();j!=graphMap.end();j++) {
01076 if(graphMap[current].distanceTo(j->second)<=1) {
01077 evals ++;
01078 if(j->second.BIC < graphMap[current].BIC) {
01079 current = j->second.getTreeName(true,false,true);
01080 break;
01081 }
01082 }
01083 }
01084 cout <<graphMap[current].BIC<<" "<<current<<endl;
01085 }
01086 cout <<"finished: ";
01087 if(current == currentGraph.getTreeName(true,false,true) ) {
01088 cout <<" optimal!!";
01089 } else {
01090 cout <<" not optimal!!";
01091 cout <<"currently best graph is: "<<currentGraph.getTreeName(true,false,true);
01092 }
01093 cout <<" evals: "<<evals;
01094 cout << endl;
01095 }