constraint_app
/home/jbrooksh/drc/software/perception/constraint_app/src/matlab_mex/FastFKSolver.h
Go to the documentation of this file.
00001 #ifndef FASTFKSOLVER_H
00002 #define FASTFKSOLVER_H
00003 
00004 #include <iostream>
00005 #include <kdl/frames_io.hpp>
00006 #include <boost/graph/adjacency_list.hpp>
00007 #include <boost/tuple/tuple.hpp>
00008 #include <boost/utility.hpp>
00009 #include <boost/property_map/property_map.hpp>
00010 
00011 class FastFKSolver {
00012  public:
00013   class Data {
00014   public:
00015   Data(const KDL::TreeElement& _element) : name(_element.segment.getName()), 
00016       element(_element), frameValid(false) {}
00017 
00018     std::string name;
00019     KDL::TreeElement element;
00020 
00021     KDL::Frame frame;
00022     bool frameValid;
00023   };
00024 
00025   typedef boost::adjacency_list<boost::listS, boost::listS, boost::bidirectionalS, Data> SegmentGraph;
00026   typedef boost::graph_traits<SegmentGraph>::vertex_descriptor SegmentGraphVertex;
00027   typedef boost::graph_traits<SegmentGraph>::out_edge_iterator SegmentGraphOutEdges;
00028   typedef std::map<std::string, SegmentGraphVertex> VertexMap;
00029   
00030  FastFKSolver(const KDL::Tree& tree) : m_tree(tree), 
00031     m_log("/tmp/cam2.log", std::ios::trunc|std::ios::binary)  {
00032 
00033     m_graph.clear();
00034     m_rootVertex = buildGraph(m_tree.getRootSegment());
00035 
00036     printGraph();
00037   }
00038 
00039   SegmentGraphVertex buildGraph(const KDL::SegmentMap::const_iterator thisSegment) {
00040     m_log << "buildGraph: adding node " << thisSegment->first 
00041           << ", with " << thisSegment->second.children.size() << " children" << std::endl;
00042     m_log.flush();
00043 
00044     Data d(thisSegment->second);
00045     SegmentGraphVertex thisVertex = add_vertex(d, m_graph);
00046     
00047     m_map.insert(std::pair<std::string, SegmentGraphVertex>(d.name, thisVertex));
00048 
00049     for ( std::vector<KDL::SegmentMap::const_iterator>::const_iterator child = 
00050             thisSegment->second.children.begin(); 
00051           child != thisSegment->second.children.end(); 
00052           ++child ) {
00053       SegmentGraphVertex childVertex = buildGraph(*child);
00054       add_edge(thisVertex, childVertex, m_graph);
00055     }
00056     
00057     return thisVertex;
00058   }
00059 
00060   void printGraph() {
00061 
00062     //loop through the verticies
00063     SegmentGraph::vertex_iterator iter, end;
00064     for ( boost::tie(iter, end) = vertices(m_graph); iter != end; ++iter ) { 
00065       SegmentGraphVertex thisVertex = *iter;
00066       m_log << m_graph[thisVertex].name << std::endl;
00067 
00068       //loop through all outgoing edges
00069       SegmentGraph::out_edge_iterator out_begin, out_end;
00070       for (boost::tie(out_begin, out_end) = out_edges(thisVertex, m_graph); 
00071            out_begin != out_end; ++out_begin) {   
00072         SegmentGraphVertex t = target(*out_begin, m_graph);
00073         m_log << "   out:" << m_graph[t].name << std::endl;
00074       }
00075 
00076       //loop through all incoming edges
00077       SegmentGraph::in_edge_iterator in_begin, in_end;
00078       for (boost::tie(in_begin, in_end) = in_edges(thisVertex, m_graph); 
00079            in_begin != in_end; ++in_begin) { 
00080         SegmentGraphVertex s = source(*in_begin, m_graph);
00081         m_log << "    in:" << m_graph[s].name << std::endl;
00082       }
00083       m_log << std::endl;
00084     }
00085   }
00086 
00087   bool getFrame(const std::string& segmentName, 
00088                 KDL::Frame& frame) {
00089     VertexMap::const_iterator iter = m_map.find(segmentName);
00090     if ( iter == m_map.end() ) return false;
00091 
00092     //m_log << "getFrame for " << segmentName << std::endl;
00093 
00094     typedef std::list<SegmentGraphVertex> VertexList;
00095     VertexList pendingVertices;
00096 
00097     SegmentGraphVertex currentVertex = iter->second;    
00098 
00099     while ( !m_graph[currentVertex].frameValid ) {
00100       pendingVertices.push_back(currentVertex);
00101 
00102       SegmentGraph::in_edge_iterator in_begin, in_end;
00103       boost::tie(in_begin, in_end) = in_edges(currentVertex, m_graph);
00104 
00105       if ( in_begin == in_end ) {
00106         m_log << "ERROR: we reached the root vertex without it being known" << std::endl
00107               << m_graph[currentVertex].name << " has no parents, but frameValid=false" << std::endl;
00108         return false;
00109       }
00110 
00111       currentVertex = source(*in_begin, m_graph);
00112     }
00113 
00114     //at this point, we know that m_graph[currentVertex].frame is correctly calculated
00115     //  and we can follow the kinematic chain starting at the back of pendingVertices
00116     frame = m_graph[currentVertex].frame;
00117     for ( VertexList::const_reverse_iterator iter = pendingVertices.rbegin();
00118           iter != pendingVertices.rend(); ++iter ) {
00119       KDL::TreeElement& currentElement(m_graph[*iter].element);
00120       KDL::Frame currentFrame = currentElement.segment.pose(m_currentJoints(currentElement.q_nr));
00121       frame = frame * currentFrame;
00122 
00123       //m_log << "  calculating frame " << m_graph[*iter].name << std::endl;
00124 
00125       m_graph[*iter].frameValid = true;
00126       m_graph[*iter].frame = frame;
00127     }
00128 
00129     return true;
00130 
00131     /*
00132     SegmentGraphVertex currentVertex = iter->second;
00133     KDL::TreeElement currentElement = m_graph[currentVertex].element;
00134     KDL::Frame currentFrame = currentElement.segment.pose(m_currentJoints(currentElement.q_nr));
00135 
00136     //m_log << "starting with frame: " << m_graph[currentVertex].name << std::endl;
00137     frame = currentFrame;
00138 
00139     SegmentGraph::in_edge_iterator in_begin, in_end;
00140     boost::tie(in_begin, in_end) = in_edges(currentVertex, m_graph); 
00141 
00142     // follow the tree back up the incoming edges
00143     while ( in_begin != in_end ) {
00144       currentVertex = source(*in_begin, m_graph);
00145       currentElement = m_graph[currentVertex].element;
00146       currentFrame = currentElement.segment.pose(m_currentJoints(currentElement.q_nr));
00147 
00148       frame = currentFrame * frame;
00149       //m_log << "  linked from: " << m_graph[currentVertex].name << std::endl;
00150 
00151       boost::tie(in_begin, in_end) = in_edges(currentVertex, m_graph); 
00152     }
00153     
00154     return true;
00155     */
00156   }
00157 
00158   void setJointPositions(const KDL::JntArray& q_in) {
00159     m_currentJoints = q_in;
00160 
00161     //loop through the verticies and clear all the frames
00162     SegmentGraph::vertex_iterator iter, end;
00163     for ( boost::tie(iter, end) = vertices(m_graph); iter != end; ++iter ) { 
00164       SegmentGraphVertex thisVertex = *iter;
00165       m_graph[thisVertex].frameValid = false;
00166     }
00167 
00168     // by construction, every frame links to the rootVertex
00169     m_graph[m_rootVertex].frameValid = true;
00170     m_graph[m_rootVertex].frame = KDL::Frame::Identity();
00171   }
00172 
00173   KDL::JntArray m_currentJoints;
00174   KDL::Tree m_tree;
00175   SegmentGraph m_graph;
00176   VertexMap m_map;
00177   SegmentGraphVertex m_rootVertex;
00178   std::ofstream m_log;
00179 };
00180 
00181 
00182 #endif
 All Classes Files Functions Variables Typedefs