00001
00002
00003
00004
00005
00006
00007
00008 #include "ArticulatedObject.h"
00009 #include "articulation_structure/PoseStampedIdMsg.h"
00010
00011 using namespace articulation_msgs;
00012 using namespace articulation_models;
00013 using namespace articulation_structure;
00014 using namespace geometry_msgs;
00015 using namespace std;
00016 using namespace boost;
00017
00018 ArticulatedObject::ArticulatedObject() {
00019
00020 }
00021
00022 ArticulatedObject::ArticulatedObject(const KinematicParams &other):
00023 KinematicParams(other) {
00024 }
00025
00026 void ArticulatedObject::SetObjectModel(const ArticulatedObjectMsg &msg,ros::NodeHandle* nh_local) {
00027 object_msg = msg;
00028
00029
00030 if(object_msg.parts.size()>0) {
00031 for(size_t part=1;part < object_msg.parts.size();part++) {
00032 ROS_ASSERT(object_msg.parts[0].pose.size() == object_msg.parts[part].pose.size());
00033 }
00034 ROS_INFO("ArticulatedObject::SetObjectModel with %d parts and %d obs each",(int)object_msg.parts.size(),(int)object_msg.parts[0].pose.size());
00035 }
00036
00037
00038
00039
00040
00041 if(hasParam(object_msg.params,"sigma_position")) {
00042 this->sigma_position = getParam(object_msg.params,"sigma_position");
00043 this->sigmax_position = getParam(object_msg.params,"sigma_position");
00044 }
00045 if(hasParam(object_msg.params,"sigma_orientation")) {
00046 this->sigma_orientation = getParam(object_msg.params,"sigma_orientation");
00047 this->sigmax_orientation = getParam(object_msg.params,"sigma_orientation");
00048 }
00049 if(hasParam(object_msg.params,"sigmax_position"))
00050 this->sigmax_position = getParam(object_msg.params,"sigmax_position");
00051 if(hasParam(object_msg.params,"sigmax_orientation"))
00052 this->sigmax_orientation = getParam(object_msg.params,"sigmax_orientation");
00053
00054 if(hasParam(object_msg.params,"reduce_dofs"))
00055 this->reduce_dofs = getParam(object_msg.params,"reduce_dofs")!=0;
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065 for(size_t part=0;part < object_msg.parts.size();part++) {
00066 if(object_msg.parts[part].pose.size())
00067 latestTimestamp[part] = ros::Time( object_msg.parts[part].pose.size()-1 ).toSec();
00068
00069 for(size_t obs=0;obs<object_msg.parts[part].pose.size();obs++) {
00070
00071 PoseStamped pose;
00072 pose.pose = object_msg.parts[part].pose[obs];
00073 pose.header.stamp = ros::Time( obs );
00074 double stamp = pose.header.stamp.toSec();
00075
00076 for(size_t part2=0;part2 < object_msg.parts.size();part2++) {
00077 PoseStamped pose2;
00078 pose2.pose = object_msg.parts[part2].pose[obs];
00079 pose2.header.stamp = ros::Time( obs );
00080
00081 if (part >= part2)
00082 continue;
00083 addPose(pose, pose2, part,part2,*this);
00084 }
00085
00086 PoseStampedIdMsg pose_id;
00087 pose_id.pose = pose;
00088 pose_id.id = part;
00089 PoseStampedIdMsgConstPtr pose_id_ptr = boost::make_shared<PoseStampedIdMsg>(pose_id);
00090 stampedMarker[stamp][part] = pose_id_ptr;
00091 markerStamped[part][stamp] = pose_id_ptr;
00092 }
00093 }
00094
00095
00096 for(vector<ModelMsg>::iterator m=object_msg.models.begin();m!=object_msg.models.end();m++) {
00097 int from = m->id / object_msg.parts.size();
00098 int to = m->id % object_msg.parts.size();
00099
00100 models[from][to] = factory.restoreModel(*m);
00101 currentGraph.push_back(
00102 std::pair< std::pair<int,int>,articulation_models::GenericModelPtr>(
00103 std::pair<int,int>(from,to),
00104 models[from][to]) );
00105 }
00106 }
00107
00108 ArticulatedObjectMsg& ArticulatedObject::GetObjectModel() {
00109
00110 for(size_t part=0;part<object_msg.parts.size();part++) {
00111 object_msg.parts[part].pose_projected.resize(object_msg.parts[part].pose.size());
00112 for(size_t obs=0;obs<object_msg.parts[part].pose.size();obs++) {
00113 if(stampedMarkerProjected[obs][part]) {
00114 object_msg.parts[part].pose_projected[obs] = stampedMarkerProjected[obs][part]->pose.pose;
00115 }
00116 }
00117 }
00118
00119
00120 object_msg.models.clear();
00121 for(KinematicGraph::iterator m=currentGraph.begin();m!=currentGraph.end();m++) {
00122 m->second->model.id = m->first.first * object_msg.parts.size() + m->first.second;
00123
00124 m->second->model.track.id = m->first.first * object_msg.parts.size() + m->first.second;
00125 m->second->model.track.header = object_msg.header;
00126 object_msg.models.push_back(m->second->getModel());
00127
00128 }
00129 return object_msg;
00130 }
00131
00132 void ArticulatedObject::FitModels() {
00133
00134 ros::Time t1 = ros::Time::now();
00135 for(size_t part=0;part < object_msg.parts.size();part++) {
00136 for(size_t part2=0;part2 < object_msg.parts.size();part2++) {
00137 if (part >= part2)
00138 continue;
00139 updateModel(part,part2,*this);
00140 }
00141 }
00142 currentGraph.clear();
00143 for(std::map< int, std::map<int,std::vector<articulation_models::GenericModelPtr> > >::iterator i=models_all.begin();i!=models_all.end();i++) {
00144 for(std::map<int,std::vector<articulation_models::GenericModelPtr> >::iterator j=i->second.begin();j!=i->second.end();j++) {
00145 for(std::vector<articulation_models::GenericModelPtr> ::iterator k=j->second.begin();k!=j->second.end();k++) {
00146 currentGraph.push_back(
00147 std::pair< std::pair<int,int>,articulation_models::GenericModelPtr>(
00148 std::pair<int,int>(i->first,j->first),
00149 *k)
00150 );
00151 }
00152 }
00153 }
00154 setParam(object_msg.params,
00155 "runtime_fitting",
00156 (ros::Time::now() - t1).toSec(),
00157 articulation_msgs::ParamMsg::EVAL);
00158 setParam(object_msg.params,
00159 "object_parts",
00160 object_msg.parts.size(),
00161 articulation_msgs::ParamMsg::EVAL);
00162 setParam(object_msg.params,
00163 "object_samples",
00164 intersectionOfStamps().size(),
00165 articulation_msgs::ParamMsg::EVAL);
00166 }
00167
00168 class EdgeModel {
00169 public:
00170 EdgeModel(int from,int to,GenericModelPtr model)
00171 :from(from),to(to),model(model)
00172 {
00173 }
00174 int from;
00175 int to;
00176 GenericModelPtr model;
00177 bool operator<(const EdgeModel &other) const { return model->bic < other.model->bic; }
00178 };
00179
00180 KinematicGraph ArticulatedObject::getSpanningTree() {
00181 vector< EdgeModel > edges;
00182 for(std::map< int, std::map<int,articulation_models::GenericModelPtr> >::iterator i=models.begin();i!=models.end();i++)
00183 for(std::map<int,articulation_models::GenericModelPtr>::iterator j=i->second.begin();j!=i->second.end();j++)
00184 if(j->second)
00185 edges.push_back( EdgeModel(i->first,j->first,j->second) );
00186
00187 vector< EdgeModel > edges_accepted;
00188 vector< int > vertices;
00189 vertices.push_back(0);
00190 while(true) {
00191
00192 vector< EdgeModel > edge_candidates;
00193 for(vector< EdgeModel >::iterator i=edges.begin();i!=edges.end();i++) {
00194 bool from_seen = false;
00195 bool to_seen = false;
00196 for(vector< int >::iterator j=vertices.begin();j!=vertices.end();j++) {
00197 if(i->from == *j) from_seen = true;
00198 if(i->to == *j) to_seen = true;
00199 }
00200 if((from_seen && !to_seen) || (!from_seen && to_seen)) {
00201 edge_candidates.push_back(*i);
00202 }
00203 }
00204 if(edge_candidates.size()==0)
00205 break;
00206
00207
00208 sort(edge_candidates.begin(),edge_candidates.end());
00209
00210
00211
00212 edges_accepted.push_back(edge_candidates.front());
00213 vertices.push_back(edge_candidates.front().from);
00214 vertices.push_back(edge_candidates.front().to);
00215 }
00216
00217 KinematicGraph E_new;
00218 for(vector< EdgeModel >::iterator i=edges_accepted.begin();i!=edges_accepted.end();i++) {
00219 E_new.push_back(
00220 std::pair< std::pair<int,int>,articulation_models::GenericModelPtr> (
00221 std::pair<int,int>(i->from,i->to),
00222 i->model
00223 ) );
00224 }
00225 E_new.DOF = E_new.getNominalDOFs();
00226 E_new.evaluate(intersectionOfStamps(),*this,*this);
00227
00228
00229 return(E_new);
00230 }
00231
00232
00233 void ArticulatedObject::ComputeSpanningTree() {
00234 ros::Time t1 = ros::Time::now();
00235
00236 currentGraph = getSpanningTree();
00237 setParam(object_msg.params,
00238 "bic[\""+currentGraph.getTreeName(true,false,true)+"\"]",
00239 currentGraph.BIC,
00240 articulation_msgs::ParamMsg::EVAL);
00241 setParam(object_msg.params,
00242 "bic_spanningtree",
00243 currentGraph.BIC,
00244 articulation_msgs::ParamMsg::EVAL);
00245 setParam(object_msg.params,
00246 "evals_spanningtree",
00247 1,
00248 articulation_msgs::ParamMsg::EVAL);
00249 setParam(object_msg.params,
00250 "runtime_spanningtree",
00251 (ros::Time::now() - t1).toSec(),
00252 articulation_msgs::ParamMsg::EVAL);
00253 setParam(object_msg.params,"spanningtree.dof",currentGraph.DOF,articulation_msgs::ParamMsg::EVAL);
00254 setParam(object_msg.params,"spanningtree.dof.nominal",currentGraph.getNominalDOFs(),articulation_msgs::ParamMsg::EVAL);
00255
00256 saveEval();
00257 }
00258
00259 void ArticulatedObject::getFastGraph() {
00260 ros::Time t1 = ros::Time::now();
00261
00262 enumerateGraphs();
00263 std::vector<double> stamps= intersectionOfStamps();
00264
00265
00266 KinematicGraph tree = getSpanningTree();
00267 tree.evaluate(stamps,*this,*this);
00268
00269 cout <<"spanning tree: "<<tree.getTreeName(true,false,true)<<endl;
00270
00271 string current;
00272 for(std::map< std::string, KinematicGraph >::iterator j=graphMap.begin();j!=graphMap.end();j++) {
00273
00274 if(tree.distanceTo(j->second)==0) {
00275 current = j->second.getTreeName(true,false,true);
00276 break;
00277 }
00278 }
00279 cout <<"starting from current graph: "<<current<<endl;
00280 cout <<"finding neighbors, total graphs = "<<graphMap.size()<<endl;
00281
00282 if(graphMap.find(current)==graphMap.end()) {
00283 cout <<"current graph is not in graphMap???"<<endl;
00284 return;
00285 }
00286 graphMap[current].evaluate(stamps,*this,*this);
00287
00288 int evals = 0;
00289 cout <<" starting "<<graphMap[current].BIC<<" "<<current<<" pos="<<graphMap[current].avg_pos_err<<" orient="<<graphMap[current].avg_orient_err<< endl;
00290 string previous;
00291
00292 vector< string > v;
00293 for(std::map< std::string, KinematicGraph >::iterator j=graphMap.begin();j!=graphMap.end();j++)
00294 v.push_back(j->first);
00295
00296 while(current!=previous) {
00297 previous = current;
00298
00299 setParam(object_msg.params,
00300 "fastgraph_eval[\""+current+"\"]",
00301 graphMap[current].BIC,
00302 articulation_msgs::ParamMsg::EVAL);
00303
00304
00305 for(size_t i=0;i<v.size();i++) {
00306 if(graphMap[current].distanceTo(graphMap[ v[i] ])==1) {
00307 graphMap[ v[i] ].evaluate(stamps,*this,*this);
00308
00309 setParam(object_msg.params,
00310 "bic[\""+graphMap[ v[i] ].getTreeName(true,false,true)+"\"]",
00311 graphMap[ v[i] ].BIC,
00312 articulation_msgs::ParamMsg::EVAL);
00313 evals ++;
00314 cout <<" evaluating "<< graphMap[ v[i] ].BIC<<
00315 " ("<<graphMap[ v[i] ].getTreeName(true,true,true)<<
00316 " pos="<<graphMap[ v[i] ].avg_pos_err<<
00317 " orient="<<graphMap[ v[i] ].avg_orient_err<<
00318 endl;
00319 if(graphMap[ v[i] ].BIC < graphMap[current].BIC) {
00320 current = graphMap[ v[i] ].getTreeName(true,false,true);
00321
00322 }
00323 } else {
00324
00325 }
00326 }
00327 cout <<graphMap[current].BIC<<" "<<current<<endl;
00328 }
00329
00330 cout <<"final: "<<graphMap[current].BIC<<" "<<current<<" pos="<<graphMap[current].avg_pos_err<<" orient="<<graphMap[current].avg_orient_err<< " stamps="<<stamps.size()<<endl;
00331 cout <<" evals: "<<evals;
00332 cout << endl;
00333
00334 currentGraph = graphMap[current];
00335 currentGraph.evaluate(stamps,*this,*this);
00336 saveEval();
00337
00338 setParam(object_msg.params,
00339 "evals_fastgraph",
00340 evals,
00341 articulation_msgs::ParamMsg::EVAL);
00342 setParam(object_msg.params,
00343 "runtime_fastgraph",
00344 (ros::Time::now() - t1).toSec(),
00345 articulation_msgs::ParamMsg::EVAL);
00346 setParam(object_msg.params,
00347 "bic_fastgraph",
00348 currentGraph.BIC,
00349 articulation_msgs::ParamMsg::EVAL);
00350 setParam(object_msg.params,"fastgraph.dof",currentGraph.DOF,articulation_msgs::ParamMsg::EVAL);
00351 setParam(object_msg.params,"fastgraph.dof.nominal",currentGraph.getNominalDOFs(),articulation_msgs::ParamMsg::EVAL);
00352
00353 }
00354
00355 void ArticulatedObject::enumerateGraphs() {
00356
00357 graphMap.clear();
00358 map<int,int> marker_to_vertex;
00359 map<int,int> vertex_to_marker;
00360 int n=0;
00361
00362 for(map<int,double>::iterator it = latestTimestamp.begin();
00363 it != latestTimestamp.end(); it++ ) {
00364
00365 marker_to_vertex[it->first] = n;
00366 vertex_to_marker[n] = it->first;
00367 n++;
00368 }
00369
00370 int vertices = object_msg.parts.size();
00371 int edges = vertices*vertices;
00372
00373
00374
00375 for(long graph=1; graph < (1<<(edges-1)); graph++) {
00376
00377
00378 KinematicGraph tree;
00379 for(int e=0;e<edges;e++) {
00380 if((graph & (1<<e))>0) {
00381
00382 int e_from = vertex_to_marker[e / vertices];
00383 int e_to = vertex_to_marker[e % vertices];
00384 if(!models[e_from][e_to]) {
00385
00386 tree.clear();
00387 break;
00388 }
00389 tree.push_back(pair< pair<int,int>,GenericModelPtr>(pair<int,int>(e_from,e_to),models[e_from][e_to]));
00390
00391 }
00392 }
00393 std::vector<bool> connected(vertex_to_marker.size(),false);
00394 connected[0] = true;
00395 bool connected_changed=true;
00396 while(connected_changed) {
00397 connected_changed = false;
00398 for(KinematicGraph::iterator i =tree.begin();i!=tree.end();i++) {
00399 if( (connected[i->first.first] && !connected[i->first.second]) ||
00400 (!connected[i->first.first] && connected[i->first.second]) ) {
00401 connected[i->first.first] = connected[i->first.second] = true;
00402 connected_changed = true;
00403 }
00404 }
00405 }
00406 bool allConnected = true;
00407 for(size_t i=0;i<connected.size();i++) {
00408 if(!connected[i]) allConnected=false;
00409 }
00410
00411 tree.DOF = tree.getNominalDOFs();
00412 if((int)tree.size()<vertices-1) {
00413
00414 continue;
00415 }
00416 if( restrict_graphs ) {
00417 if(
00418 (restricted_graphs.find(" "+tree.getTreeName(false,false,false)+" ")==restricted_graphs.npos) &&
00419 (restricted_graphs.find(" "+tree.getTreeName(true,false,false)+" ")==restricted_graphs.npos) &&
00420 (restricted_graphs.find(" "+tree.getTreeName(true,true,false)+" ")==restricted_graphs.npos) &&
00421 (restricted_graphs.find(" "+tree.getTreeName(true,true,true)+" ")==restricted_graphs.npos) ) {
00422
00423 continue;
00424 }
00425 }
00426
00427
00428
00429
00430 if(allConnected) {
00431
00432
00433
00434 KinematicGraph basetree = tree;
00435 tree.clear();
00436 int combination_total = 1;
00437 for(KinematicGraphType::iterator it=basetree.begin();it!=basetree.end();it++) {
00438 combination_total *= models_all[it->first.first][it->first.second].size();
00439 }
00440
00441 for(int combination=0;combination<combination_total;combination++) {
00442 if(search_all_models) {
00443 tree.clear();
00444 int c_tmp = combination;
00445 for(KinematicGraphType::iterator it=basetree.begin();it!=basetree.end();it++) {
00446 int idx = c_tmp % models_all[it->first.first][it->first.second].size();
00447 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]));
00448 c_tmp /= models_all[it->first.first][it->first.second].size();
00449 }
00450 } else {
00451 tree = basetree;
00452 }
00453
00454 int DOFs = tree.getNominalDOFs();
00455 tree.DOF = DOFs;
00456
00457 for(int reducedDOFs=(reduce_dofs?(DOFs==0?0:1):DOFs);reducedDOFs<=DOFs;reducedDOFs++) {
00458 KinematicGraph copyOfTree(tree,true);
00459 copyOfTree.DOF = reducedDOFs;
00460 graphMap[copyOfTree.getTreeName(true,false,true)] = KinematicGraph(copyOfTree,true);
00461 }
00462 if(!search_all_models) break;
00463 }
00464 }
00465 }
00466 }
00467
00468 void ArticulatedObject::getGraph() {
00469 ros::Time t1 = ros::Time::now();
00470
00471 enumerateGraphs();
00472 std::vector<double> stamps= intersectionOfStamps();
00473
00474 string current;
00475 int evals = 0;
00476
00477 vector< string > v;
00478 for(std::map< std::string, KinematicGraph >::iterator j=graphMap.begin();j!=graphMap.end();j++)
00479 v.push_back(j->first);
00480
00481
00482 for(size_t i=0;i<v.size();i++) {
00483 graphMap[ v[i] ].evaluate(stamps,*this,*this);
00484
00485
00486 setParam(object_msg.params,
00487 "bic[\""+graphMap[ v[i] ].getTreeName(true,false,true)+"\"]",
00488 graphMap[ v[i] ].BIC,
00489 articulation_msgs::ParamMsg::EVAL);
00490 evals ++;
00491 cout <<" evaluating "<< graphMap[ v[i] ].BIC<<" ("<<graphMap[ v[i] ].getTreeName(true,true,true)<<" pos="<<graphMap[ v[i] ].avg_pos_err<<" orient="<<graphMap[ v[i] ].avg_orient_err;
00492 if(current == "" || (graphMap[ v[i] ].BIC < graphMap[current].BIC)) {
00493 current = graphMap[ v[i] ].getTreeName(true,false,true);
00494 cout <<"*";
00495 }
00496 cout << endl;
00497 }
00498
00499 cout <<"final: "<<graphMap[current].BIC<<" "<<current<<" pos="<<graphMap[current].avg_pos_err<<" orient="<<graphMap[current].avg_orient_err<< " stamps="<<stamps.size()<<endl;
00500 cout <<" evals: "<<evals;
00501 cout << endl;
00502
00503 currentGraph = graphMap[current];
00504 currentGraph.evaluate(stamps,*this,*this);
00505
00506 setParam(object_msg.params,
00507 "evals_graph",
00508 evals,
00509 articulation_msgs::ParamMsg::EVAL);
00510 setParam(object_msg.params,
00511 "runtime_graph",
00512 (ros::Time::now() - t1).toSec(),
00513 articulation_msgs::ParamMsg::EVAL);
00514 setParam(object_msg.params,
00515 "bic_graph",
00516 currentGraph.BIC,
00517 articulation_msgs::ParamMsg::EVAL);
00518 setParam(object_msg.params,"graph.dof",currentGraph.DOF,articulation_msgs::ParamMsg::EVAL);
00519 setParam(object_msg.params,"graph.dof.nominal",currentGraph.getNominalDOFs(),articulation_msgs::ParamMsg::EVAL);
00520
00521 saveEval();
00522 }
00523
00524 void ArticulatedObject::saveEval() {
00525
00526 setParam(object_msg.params,"bic",currentGraph.BIC,articulation_msgs::ParamMsg::EVAL);
00527 setParam(object_msg.params,"dof",currentGraph.DOF,articulation_msgs::ParamMsg::EVAL);
00528 setParam(object_msg.params,"dof.nominal",currentGraph.getNominalDOFs(),articulation_msgs::ParamMsg::EVAL);
00529 setParam(object_msg.params,"loglikelihood",currentGraph.loglh,articulation_msgs::ParamMsg::EVAL);
00530 setParam(object_msg.params,"complexity",currentGraph.k,articulation_msgs::ParamMsg::EVAL);
00531 setParam(object_msg.params,"avg_error_position",currentGraph.avg_pos_err,articulation_msgs::ParamMsg::EVAL);
00532 setParam(object_msg.params,"avg_error_orientation",currentGraph.avg_orient_err,articulation_msgs::ParamMsg::EVAL);
00533 }