The range adaptor scheme did not work for std::map TERMS in creating a JacobianFacor. Hence, I removed it - which I think is more readable - and replaced it with an explicit creationg of dimensions. I also added a test with std::map, which works.
							parent
							
								
									6532966f62
								
							
						
					
					
						commit
						20b9c31465
					
				|  | @ -19,10 +19,6 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <gtsam/linear/linearExceptions.h> | ||||
| #include <boost/assign/list_of.hpp> | ||||
| #include <boost/range/adaptor/transformed.hpp> | ||||
| #include <boost/range/algorithm/for_each.hpp> | ||||
| #include <boost/foreach.hpp> | ||||
| 
 | ||||
| namespace gtsam { | ||||
| 
 | ||||
|  | @ -59,20 +55,10 @@ namespace gtsam { | |||
|     model_ = model; | ||||
|   } | ||||
| 
 | ||||
|   /* ************************************************************************* */ | ||||
|   namespace internal { | ||||
|     static inline DenseIndex getColsJF(const std::pair<Key,Matrix>& p) { | ||||
|       return p.second.cols(); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /* ************************************************************************* */ | ||||
|   template<typename TERMS> | ||||
|   void JacobianFactor::fillTerms(const TERMS& terms, const Vector& b, const SharedDiagonal& noiseModel) | ||||
|   { | ||||
|     using boost::adaptors::transformed; | ||||
|     namespace br = boost::range; | ||||
| 
 | ||||
|     // Check noise model dimension
 | ||||
|     if(noiseModel && (DenseIndex)noiseModel->dim() != b.size()) | ||||
|       throw InvalidNoiseModel(b.size(), noiseModel->dim()); | ||||
|  | @ -80,25 +66,31 @@ namespace gtsam { | |||
|     // Resize base class key vector
 | ||||
|     Base::keys_.resize(terms.size()); | ||||
| 
 | ||||
|     // Construct block matrix - this uses the boost::range 'transformed' construct to apply
 | ||||
|     // internal::getColsJF (defined just above here in this file) to each term.  This
 | ||||
|     // transforms the list of terms into a list of variable dimensions, by extracting the
 | ||||
|     // number of columns in each matrix.  This is done to avoid separately allocating an
 | ||||
|     // array of dimensions before constructing the VerticalBlockMatrix.
 | ||||
|     Ab_ = VerticalBlockMatrix(terms | transformed(&internal::getColsJF), b.size(), true); | ||||
|     // Get dimensions of matrices
 | ||||
|     std::vector<size_t> dimensions; | ||||
|     for(typename TERMS::const_iterator it = terms.begin(); it != terms.end(); ++it) { | ||||
|       const std::pair<Key, Matrix>& term = *it; | ||||
|       const Matrix& Ai = term.second; | ||||
|       dimensions.push_back(Ai.cols()); | ||||
|     } | ||||
| 
 | ||||
|     // Construct block matrix
 | ||||
|     Ab_ = VerticalBlockMatrix(dimensions, b.size(), true); | ||||
| 
 | ||||
|     // Check and add terms
 | ||||
|     DenseIndex i = 0; // For block index
 | ||||
|     for(typename TERMS::const_iterator termIt = terms.begin(); termIt != terms.end(); ++termIt) { | ||||
|       const std::pair<Key, Matrix>& term = *termIt; | ||||
|     for(typename TERMS::const_iterator it = terms.begin(); it != terms.end(); ++it) { | ||||
|       const std::pair<Key, Matrix>& term = *it; | ||||
|       Key key = term.first; | ||||
|       const Matrix& Ai = term.second; | ||||
| 
 | ||||
|       // Check block rows
 | ||||
|       if(term.second.rows() != Ab_.rows()) | ||||
|         throw InvalidMatrixBlock(Ab_.rows(), term.second.rows()); | ||||
|       if(Ai.rows() != Ab_.rows()) | ||||
|         throw InvalidMatrixBlock(Ab_.rows(), Ai.rows()); | ||||
| 
 | ||||
|       // Assign key and matrix
 | ||||
|       Base::keys_[i] = term.first; | ||||
|       Ab_(i) = term.second; | ||||
|       Base::keys_[i] = key; | ||||
|       Ab_(i) = Ai; | ||||
| 
 | ||||
|       // Increment block index
 | ||||
|       ++ i; | ||||
|  |  | |||
|  | @ -105,6 +105,24 @@ TEST(JacobianFactor, constructors_and_accessors) | |||
|     EXPECT(noise == expected.get_model()); | ||||
|     EXPECT(noise == actual.get_model()); | ||||
|   } | ||||
|   { | ||||
|     // Test three-term constructor with std::map
 | ||||
|     JacobianFactor expected( | ||||
|       boost::make_iterator_range(terms.begin(), terms.begin() + 3), b, noise); | ||||
|     map<Key,Matrix> mapTerms; | ||||
|     // note order of insertion plays no role: order will be determined by keys
 | ||||
|     mapTerms.insert(terms[2]); | ||||
|     mapTerms.insert(terms[1]); | ||||
|     mapTerms.insert(terms[0]); | ||||
|     JacobianFactor actual(mapTerms, b, noise); | ||||
|     EXPECT(assert_equal(expected, actual)); | ||||
|     LONGS_EQUAL((long)terms[2].first, (long)actual.keys().back()); | ||||
|     EXPECT(assert_equal(terms[2].second, actual.getA(actual.end() - 1))); | ||||
|     EXPECT(assert_equal(b, expected.getb())); | ||||
|     EXPECT(assert_equal(b, actual.getb())); | ||||
|     EXPECT(noise == expected.get_model()); | ||||
|     EXPECT(noise == actual.get_model()); | ||||
|   } | ||||
|   { | ||||
|     // VerticalBlockMatrix constructor
 | ||||
|     JacobianFactor expected( | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue