constraint_app
/home/jbrooksh/drc/software/perception/constraint_app/src/test/ca_test.cpp
Go to the documentation of this file.
00001 #include <stdio.h>
00002 #include <inttypes.h>
00003 #include <lcm/lcm.h>
00004 #include <iostream>
00005 #include <lcmtypes/visualization.h>
00006 #include <path_util/path_util.h>
00007 #include <boost/shared_ptr.hpp>
00008 #include <boost/thread.hpp>
00009 #include <boost/format.hpp>
00010 #include <lcmtypes/drc_lcmtypes.hpp>
00011 #include <lcm/lcm-cpp.hpp>
00012 #include <urdf/model.h>
00013 #include <kdl/tree.hpp>
00014 #include <kdl_parser/kdl_parser.hpp>
00015 #include <forward_kinematics/treefksolverposfull_recursive.hpp>
00016 #include <otdf_parser/otdf_parser.h>
00017 #include <otdf_parser/otdf_urdf_converter.h>
00018 #include "mytreefksolverpos_recursive.hpp"
00019 #include <bot_lcmgl_client/lcmgl.h>
00020 #include <GL/gl.h>
00021 #include <GL/glu.h>
00022 #include <lcmtypes/bot_param/update_t.hpp>
00023 #include <math.h>
00024 
00025 boost::mutex idMutex;
00026 boost::condition_variable idCondition;
00027 boost::mutex readyMutex;
00028 boost::condition_variable readyCondition;
00029 volatile bool idValid = false;
00030 volatile bool matlabReady = false;
00031 volatile int affordance_id = 0;
00032 KDL::Tree tree;
00033 
00034 void print_kdl_tree(const KDL::Tree& tree, 
00035                     const KDL::TreeElement& segment,
00036                     unsigned int depth) 
00037 {
00038   for ( unsigned int i = 0; i < depth; i++ ) {
00039     std::cout << " ";
00040   }
00041   std::cout << segment.segment.getName() 
00042             << ", joint " << segment.segment.getJoint().getName() 
00043             << " of type " << segment.segment.getJoint().getTypeName()
00044             << std::endl;
00045   for ( unsigned int i = 0; i < segment.children.size(); i++ ) {
00046     print_kdl_tree(tree, segment.children[i]->second, depth+1);
00047   }
00048 }
00049 
00050 void loadTree(const std::string& filename)
00051 {
00052   // load the OTDF file
00053   std::string xml_string;
00054   if ( !otdf::get_xml_string_from_file(filename, xml_string) ) {
00055     std::cerr << "unable to get_xml_string_from_file " << filename << std::endl;
00056     exit(-1);
00057   }
00058 
00059   //convert OTDF to URDF
00060   boost::shared_ptr<otdf::ModelInterface> otdf_instance(otdf::parseOTDF(xml_string));
00061   std::string urdf_xml_string(otdf::convertObjectInstanceToCompliantURDFstring(otdf_instance));
00062   
00063   // Parse KDL tree
00064   if ( !kdl_parser::treeFromString(urdf_xml_string,tree) ) {
00065     std::cerr << "ERROR: Failed to extract kdl tree from "  << otdf_instance->name_ 
00066               << " otdf object instance "<< std::endl; 
00067   }
00068 
00069   std::cout << "created KDL object with " << tree.getNrOfJoints() << " joints and " 
00070             << tree.getNrOfSegments() << " segments" << std::endl;
00071   print_kdl_tree(tree, tree.getRootSegment()->second, 0);
00072 }
00073 
00074 void runPopulate(lcm::LCM* lcm)
00075 {
00076   bot_lcmgl_t* lcmgl = bot_lcmgl_init(lcm->getUnderlyingLCM(), "ca_test");
00077 
00078   std::string otdf_name("fixed_valve_task_wall3");
00079 
00080   loadTree(otdf_name);
00081   MyTreeFkSolverPos_recursive fk(tree);
00082 
00083   drc::affordance_plus_t affordance_plus;
00084   drc::affordance_plus_t affordance_plus_truth;
00085   drc::affordance_t& affordance(affordance_plus.aff);
00086   affordance.utime = 0;
00087   affordance.otdf_type = otdf_name;
00088   affordance.friendly_name = "test";
00089   affordance.uid = affordance_id;
00090   affordance.aff_store_control = drc::affordance_t::NEW;
00091   affordance.origin_xyz[0] = 0.0;
00092   affordance.origin_xyz[1] = 0.0;
00093   affordance.origin_xyz[2] = 0.0;
00094   affordance.origin_rpy[0] = 3.14;
00095   affordance.origin_rpy[1] = 0.0;
00096   affordance.origin_rpy[2] = 0.0;
00097   affordance.nparams = 0;
00098 
00099   affordance.nstates = tree.getNrOfJoints();
00100   affordance.states.resize(affordance.nstates);
00101   affordance.state_names.resize(affordance.nstates);
00102   KDL::JntArray joints(tree.getNrOfJoints());
00103   for ( int i = 0; i < tree.getNrOfJoints(); i++ ) {
00104     affordance.states[i] = 0.0;
00105     affordance.state_names[i] = boost::str(boost::format("base_joint%i") % i);
00106     joints(i) = affordance.states[i];
00107   }
00108 
00109   affordance.bounding_xyz[0] = 0.0;
00110   affordance.bounding_xyz[1] = 0.0;
00111   affordance.bounding_xyz[2] = 0.0;
00112   affordance.bounding_rpy[0] = 0.0;
00113   affordance.bounding_rpy[1] = 0.0;
00114   affordance.bounding_rpy[2] = 0.0;
00115   affordance.bounding_lwh[0] = 0.0;
00116   affordance.bounding_lwh[1] = 0.0;
00117   affordance.bounding_lwh[2] = 0.0;
00118   affordance_plus.npoints = 0;
00119   affordance_plus.ntriangles = 0;
00120 
00121   //wait for matlab to be ready
00122   {
00123     boost::mutex::scoped_lock lock(readyMutex);
00124     while ( !matlabReady ) {
00125       std::cout << "waiting on matlab to be ready" << std::endl;
00126       boost::system_time timeout = boost::get_system_time() + 
00127         boost::posix_time::milliseconds(1000);
00128       readyCondition.timed_wait(lock, timeout);
00129     }
00130   }
00131 
00132   // publish to the affordance server
00133   std::cout << "publishing AFFORDANCE_FIT for id=" << affordance_plus.aff.uid << std::endl;
00134   lcm->publish("AFFORDANCE_FIT", &affordance_plus);  //this will draw it in the viewer for debugging
00135 
00136   //wait for the next response message and retrieve the uid
00137   {
00138     boost::mutex::scoped_lock lock(idMutex);
00139     while ( !idValid ) {
00140       std::cout << "waiting on lcm message from affordance server" << std::endl;
00141       boost::system_time timeout = boost::get_system_time() + 
00142         boost::posix_time::milliseconds(1000);
00143       idCondition.timed_wait(lock, timeout);
00144     }
00145   }
00146 
00147   //start using this uid
00148   affordance.uid = affordance_id;
00149   std::cout << "publishing CAM_AFFORDANCE_FIT for id=" << affordance_plus.aff.uid << std::endl;
00150   lcm->publish("CAM_AFFORDANCE_FIT", &affordance_plus); //this will initialize our tracker with the fit
00151 
00152 
00153   int ring_segs[3] = {0, 6, 12};
00154   KDL::Frame base_expressedIn_world;
00155   base_expressedIn_world.p[0] = affordance.origin_xyz[0];
00156   base_expressedIn_world.p[1] = affordance.origin_xyz[1];
00157   base_expressedIn_world.p[2] = affordance.origin_xyz[2];
00158   base_expressedIn_world.M = KDL::Rotation::RPY(affordance.origin_rpy[0], affordance.origin_rpy[1], affordance.origin_rpy[2]);
00159 
00160   affordance_plus_truth = affordance_plus;
00161   affordance_plus_truth.aff.uid++;
00162   affordance_plus_truth.aff.aff_store_control = drc::affordance_t::NEW;
00163   affordance_plus_truth.aff.origin_xyz[2] += 1.0;
00164 
00165   for ( int i = 0; i < 20; i ++ ) {
00166     
00167     std::cout << "publishing" << std::endl;
00168 
00169     affordance.aff_store_control = drc::affordance_t::UPDATE;
00170     for ( int j = 0; j < tree.getNrOfJoints(); j++ ) {
00171       affordance.states[j] = fmod(i / 10.0 + j, 2.0 * M_PI);
00172       if ( affordance.states[j] > M_PI ) {
00173         affordance.states[j] = affordance.states[j] - 2.0 * M_PI;
00174       }
00175       joints(j) = affordance.states[j];
00176     }
00177 
00178     std::cout << "publishing ground truth " << affordance_plus_truth.aff.uid << std::endl;
00179     affordance_plus_truth.aff.states = affordance.states;
00180     lcm->publish("AFFORDANCE_FIT", &affordance_plus_truth);
00181     affordance_plus_truth.aff.aff_store_control = drc::affordance_t::UPDATE;
00182 
00183     MyTreeFkSolverPos_recursive::SegmentToPoseMap map;
00184     int fkret = fk.JntToCart(joints, map);
00185     if ( fkret < 0 ) {
00186       std::cout << "error while getting forward kinematics: " << fkret << std::endl;
00187       continue;
00188     }
00189 
00190     bot_lcmgl_enable(lcmgl, GL_DEPTH_TEST);
00191     bot_lcmgl_color3f(lcmgl, 1, 0, 0);
00192     bot_lcmgl_point_size(lcmgl, 3);
00193     bot_lcmgl_begin(lcmgl, LCMGL_LINES);
00194 
00195     drc::affordance_track_collection_t tracks;
00196     tracks.utime = 0;
00197     tracks.uid = affordance.uid;
00198 
00199     for ( MyTreeFkSolverPos_recursive::SegmentToPoseMap::const_iterator iter = map.begin();
00200           iter != map.end(); ++iter ) {
00201       
00202       for ( int j = 0; j < (otdf_name == "fixed_valve_task_wall" ? 2 : 3); j++ ) {
00203         for ( int s = 0; s < 3; s++ ) {
00204           //std::string seg( (j==0) ? boost::str(boost::format("RING_%i") % ring_segs[s] ) : 
00205           //               boost::str(boost::format("RING%i_%i") % (j+1) % ring_segs[s]) );
00206           std::string spoke(boost::str(boost::format("Spokes%i_%i") % j % s));
00207           if ( spoke == iter->first ) {
00208 
00209             const KDL::Frame& pt_expressedIn_base(iter->second);
00210             double xyzrpw[6] = { pt_expressedIn_base.p[0], pt_expressedIn_base.p[1], pt_expressedIn_base.p[2], 0.0, 0.0, 0.0 };
00211             pt_expressedIn_base.M.GetRPY(xyzrpw[3], xyzrpw[4], xyzrpw[5]);
00212             KDL::Frame pt_expressedIn_world = base_expressedIn_world * pt_expressedIn_base;
00213             KDL::Frame pt2_expressedIn_pt;
00214             pt2_expressedIn_pt.p[0] = 0.3;
00215             KDL::Frame pt3_expressedIn_pt;
00216             pt3_expressedIn_pt.p[2] = 0.3;
00217             KDL::Frame pt2_expressedIn_world = base_expressedIn_world * pt_expressedIn_base * pt2_expressedIn_pt;
00218             KDL::Frame pt3_expressedIn_world = base_expressedIn_world * pt_expressedIn_base * pt3_expressedIn_pt;
00219             std::cout << "   " << iter->first << ", " << joints(j) << std::endl;            
00220            
00221             bot_lcmgl_vertex3f(lcmgl, pt_expressedIn_world.p[0], pt_expressedIn_world.p[1], pt_expressedIn_world.p[2]); 
00222             bot_lcmgl_vertex3f(lcmgl, pt2_expressedIn_world.p[0], pt2_expressedIn_world.p[1], pt2_expressedIn_world.p[2]); 
00223 
00224             bot_lcmgl_vertex3f(lcmgl, pt_expressedIn_world.p[0], pt_expressedIn_world.p[1], pt_expressedIn_world.p[2]); 
00225             bot_lcmgl_vertex3f(lcmgl, pt3_expressedIn_world.p[0], pt3_expressedIn_world.p[1], pt3_expressedIn_world.p[2]); 
00226 
00227             drc::affordance_track_t track;
00228             track.segment = iter->first;
00229             track.position.x = pt_expressedIn_world.p[0];
00230             track.position.y = pt_expressedIn_world.p[1];
00231             track.position.z = pt_expressedIn_world.p[2];
00232             track.id = 0;
00233 
00234             tracks.tracks.push_back(track);
00235           }
00236         }
00237       }
00238     }
00239 
00240     tracks.ntracks = tracks.tracks.size();
00241     lcm->publish("AFFORDANCE_DETECTIONS", &tracks);
00242 
00243     bot_lcmgl_end(lcmgl);
00244     bot_lcmgl_switch_buffer(lcmgl);
00245 
00246     boost::this_thread::sleep(boost::posix_time::seconds(2));
00247   }
00248 
00249   std::cout << "done publishing" << std::endl;
00250   bot_lcmgl_destroy(lcmgl);
00251 
00252   exit(0);
00253 }
00254 
00255 class dummy {
00256 public:
00257 void handleAffordanceCollection(const lcm::ReceiveBuffer* rbuf, 
00258                                 const std::string& channel,
00259                                 const drc::affordance_plus_collection_t *affordance_plus_col)
00260 {
00261   boost::mutex::scoped_lock lock(idMutex);
00262 
00263   std::cout << "got a collection" << std::endl;
00264 
00265   if ( idValid ) {
00266     std::cout << "ignoring collection" << std::endl;
00267     return;
00268   }
00269 
00270   if ( affordance_plus_col->naffs == 0 ) return;
00271   
00272   for ( int i = 0; i < affordance_plus_col->naffs; i++ ) {
00273     if ( affordance_plus_col->affs_plus[i].aff.friendly_name == "test" ) {
00274       int this_uid = affordance_plus_col->affs_plus[i].aff.uid;
00275       if ( this_uid >= affordance_id ) {
00276         affordance_id = this_uid;
00277         std::cout << " " << affordance_id << std::endl;
00278       }
00279     }
00280   }
00281 
00282   idValid = true;
00283   idCondition.notify_all();
00284 }
00285 
00286 void handleTrackPFStatus(const lcm::ReceiveBuffer* rbuf, 
00287                          const std::string& channel,
00288                          const bot_param::update_t *update)
00289 {
00290   if ( update->params == "READY" ) {
00291     boost::mutex::scoped_lock lock(readyMutex);
00292     matlabReady = true;
00293     readyCondition.notify_all();
00294   }
00295 }
00296 };
00297 
00298 int main(int argc, char ** argv)
00299 {
00300   lcm::LCM lcm;
00301   dummy d;
00302 
00303   lcm.subscribe("AFFORDANCE_PLUS_COLLECTION", &dummy::handleAffordanceCollection, &d);
00304   lcm.subscribe("TRACK_PF_STATUS", &dummy::handleTrackPFStatus, &d);
00305 
00306   std::cout << "starting..." << std::endl;
00307   boost::thread populateThread = boost::thread(runPopulate, &lcm);
00308 
00309   while (0 == lcm.handle()) {
00310 
00311 
00312   }
00313 
00314   return 0;
00315 }
 All Classes Files Functions Variables Typedefs