Skip to content

Commit

Permalink
Merge pull request #58 from utiasASRL/ros2-dev
Browse files Browse the repository at this point in the history
Get latest changes from ros2-vtr3 branch
  • Loading branch information
cheneyuwu authored Oct 27, 2021
2 parents e47e7d2 + 2e34d62 commit 7876e10
Show file tree
Hide file tree
Showing 7 changed files with 228 additions and 34 deletions.
40 changes: 7 additions & 33 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.16)
project(steam)

option(USE_AMENT "Use ament_cmake to build lgmath for ROS2." OFF)
option(USE_AMENT "Use ament_cmake to build lgmath for ROS2." ON)

# Compiler setup (assumed to be GNU)
set(CMAKE_CXX_STANDARD 17)
Expand Down Expand Up @@ -108,23 +108,17 @@ target_include_directories(${PROJECT_NAME}
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>)


ament_export_targets(export_${PROJECT_NAME} HAS_LIBRARY_TARGET)
# May need the following
ament_export_dependencies(
Eigen3 OpenMP
lgmath
)
ament_export_dependencies(eigen3_cmake_module)
ament_export_dependencies(OpenMP Eigen3 lgmath)

install(
DIRECTORY include/
DESTINATION include
)

install(
TARGETS
# Libraries
${PROJECT_NAME}
TARGETS ${PROJECT_NAME}
EXPORT export_${PROJECT_NAME}
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
Expand All @@ -135,41 +129,20 @@ install(
endif()

# Executables
link_libraries(${PROJECT_NAME})
add_executable(SimpleBAandTrajPrior samples/SimpleBAandTrajPrior.cpp)
target_link_libraries(SimpleBAandTrajPrior ${PROJECT_NAME})

add_executable(SimpleBAandCATrajPrior samples/SimpleBAandCATrajPrior.cpp)
target_link_libraries(SimpleBAandCATrajPrior ${PROJECT_NAME})

add_executable(SimpleBundleAdjustment samples/SimpleBundleAdjustment.cpp)
target_link_libraries(SimpleBundleAdjustment ${PROJECT_NAME})

add_executable(SimpleBundleAdjustmentFullRel samples/SimpleBundleAdjustmentFullRel.cpp)
target_link_libraries(SimpleBundleAdjustmentFullRel ${PROJECT_NAME})

add_executable(SimpleBundleAdjustmentRelLand samples/SimpleBundleAdjustmentRelLand.cpp)
target_link_libraries(SimpleBundleAdjustmentRelLand ${PROJECT_NAME})

add_executable(SimpleBundleAdjustmentRelLandX samples/SimpleBundleAdjustmentRelLandX.cpp)
target_link_libraries(SimpleBundleAdjustmentRelLandX ${PROJECT_NAME})

add_executable(SimplePoseGraphRelax samples/SimplePoseGraphRelax.cpp)
target_link_libraries(SimplePoseGraphRelax ${PROJECT_NAME})

add_executable(SimpleTrajectoryPrior samples/SimpleTrajectoryPrior.cpp)
target_link_libraries(SimpleTrajectoryPrior ${PROJECT_NAME})

add_executable(SpherePoseGraphRelax samples/SpherePoseGraphRelax.cpp)
target_link_libraries(SpherePoseGraphRelax ${PROJECT_NAME})

add_executable(TrustRegionExample samples/TrustRegionExample.cpp)
target_link_libraries(TrustRegionExample ${PROJECT_NAME})

add_executable(MotionDistortedP2PandCATrajPrior samples/MotionDistortedP2PandCATrajPrior.cpp)
target_link_libraries(MotionDistortedP2PandCATrajPrior ${PROJECT_NAME})

add_executable(SimpleP2PandCATrajPrior samples/SimpleP2PandCATrajPrior.cpp)
target_link_libraries(SimpleP2PandCATrajPrior ${PROJECT_NAME})
add_executable(SimplePointCloudAlignment samples/SimplePointCloudAlignment.cpp)

if (USE_AMENT)

Expand All @@ -188,6 +161,7 @@ install(
TrustRegionExample
MotionDistortedP2PandCATrajPrior
SimpleP2PandCATrajPrior
SimplePointCloudAlignment
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION lib/${PROJECT_NAME}
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ STEAM (Simultaneous Trajectory Estimation and Mapping) Engine is an optimization

[1] Barfoot, T. D. and Furgale, P. T., “_Associating Uncertainty with Three-Dimensional Poses for use in Estimation Problems_,” IEEE Transactions on Robotics, 2014.

**Note**: This branch is for VTR3, and the `USE_AMENT` flag is `ON` by default.

## Installation

### Dependencies
Expand Down
1 change: 1 addition & 0 deletions include/steam.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include <steam/evaluator/samples/LinearFuncErrorEval.hpp>
#include <steam/evaluator/samples/ImuErrorEval.hpp>
#include <steam/evaluator/samples/PointToPointErrorEval.hpp>
#include <steam/evaluator/samples/PointToPointErrorEval2.hpp>

// evaluator - block auto diff
#include <steam/evaluator/blockauto/EvalTreeNode.hpp>
Expand Down
69 changes: 69 additions & 0 deletions include/steam/evaluator/samples/PointToPointErrorEval2.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
//////////////////////////////////////////////////////////////////////////////////////////////
/// \file PointToPointErrorEval2.cpp
///
/// \author Yuchen Wu, ASRL
/// \brief This evaluator was developed in the context of ICP (Iterative
/// Closest Point) implementation. It is different from
/// PointToPointErrorEval in that it takes points in cartesian
/// coordinates instead of homogeneous coordinates.
//////////////////////////////////////////////////////////////////////////////////////////////

#ifndef STEAM_POINT_TO_POINT_ERROR_EVALUATOR_2_HPP
#define STEAM_POINT_TO_POINT_ERROR_EVALUATOR_2_HPP

#include <steam.hpp>

namespace steam {

//////////////////////////////////////////////////////////////////////////////////////////////
/// \brief The distance between two points living in their respective frame is
/// used as our error function.
//////////////////////////////////////////////////////////////////////////////////////////////
class PointToPointErrorEval2 : public ErrorEvaluator<3, 6>::type {
public:
/// Convenience typedefs
typedef boost::shared_ptr<PointToPointErrorEval2> Ptr;
typedef boost::shared_ptr<const PointToPointErrorEval2> ConstPtr;

//////////////////////////////////////////////////////////////////////////////////////////////
/// \brief Constructor
/// \param T_rq Transformation matrix from query to reference.
/// \param reference A point in the 'reference' frame expressed in cartesian
/// coordinates.
/// \param query A point in the 'query' frame expressed in cartesian
/// coordinates.
//////////////////////////////////////////////////////////////////////////////////////////////
PointToPointErrorEval2(const se3::TransformEvaluator::ConstPtr &T_rq,
const Eigen::Vector3d &reference,
const Eigen::Vector3d &query);

//////////////////////////////////////////////////////////////////////////////////////////////
/// \brief Returns whether or not an evaluator contains unlocked state
/// variables
//////////////////////////////////////////////////////////////////////////////////////////////
bool isActive() const override;

//////////////////////////////////////////////////////////////////////////////////////////////
/// \brief Evaluate the 3-d measurement error (x, y, z)
//////////////////////////////////////////////////////////////////////////////////////////////
Eigen::Matrix<double, 3, 1> evaluate() const override;

//////////////////////////////////////////////////////////////////////////////////////////////
/// \brief Evaluate the 3-d measurement error (x, y, z) and Jacobians
//////////////////////////////////////////////////////////////////////////////////////////////
virtual Eigen::Matrix<double, 3, 1> evaluate(
const Eigen::Matrix<double, 3, 3> &lhs,
std::vector<Jacobian<3, 6>> *jacs) const;

private:
se3::TransformEvaluator::ConstPtr T_rq_;

Eigen::Matrix<double, 3, 4> D_ = Eigen::Matrix<double, 3, 4>::Zero();

Eigen::Vector4d reference_ = Eigen::Vector4d::Constant(1);
Eigen::Vector4d query_ = Eigen::Vector4d::Constant(1);
};

} // namespace steam

#endif // STEAM_POINT_TO_POINT_ERROR_EVALUATOR_2_HPP
2 changes: 1 addition & 1 deletion include/steam/problem/NoiseModel-inl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ void BaseNoiseModel<MEAS_DIM>::assertPositiveDefiniteMatrix(
//////////////////////////////////////////////////////////////////////////////////////////////
template<int MEAS_DIM>
StaticNoiseModel<MEAS_DIM>::StaticNoiseModel(const Eigen::Matrix<double,MEAS_DIM,MEAS_DIM>& matrix,
MatrixType type)
MatrixType type)
: BaseNoiseModel<MEAS_DIM>::BaseNoiseModel(matrix,type) {

}
Expand Down
76 changes: 76 additions & 0 deletions samples/SimplePointCloudAlignment.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
//////////////////////////////////////////////////////////////////////////////////////////////
/// \file SimplePointCloudAlignment.cpp
/// \brief
///
/// \author Yuchen Wu, ASRL
//////////////////////////////////////////////////////////////////////////////////////////////

#include <iostream>

#include <lgmath.hpp>
#include <steam.hpp>

int main(int argc, char **argv) {
/// Reference points to align against
Eigen::Matrix<double, 4, 9> ref_pts;
// clang-format off
ref_pts << 0, 1, 1, 0, -1, -1, -1, 0, 1,
0, 0, 1, 1, 1, 0, -1, -1, -1,
0.1, 0.2, 0.3, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1;
// clang-format on

/// Ground truth pose
Eigen::Matrix<double, 6, 1> T_mq_vec;
T_mq_vec << 1, 1, 1, 1, 1, 1;
lgmath::se3::Transformation T_mq(T_mq_vec);

Eigen::Matrix<double, 4, 9> qry_pts = T_mq.inverse().matrix() * ref_pts;

// state and evaluator
steam::se3::TransformStateVar::Ptr T_mq_var(
new steam::se3::TransformStateVar());
steam::se3::TransformStateEvaluator::ConstPtr T_mq_eval =
steam::se3::TransformStateEvaluator::MakeShared(T_mq_var);

// shared noise and loss functions
steam::BaseNoiseModel<3>::Ptr noise_model(
new steam::StaticNoiseModel<3>(Eigen::MatrixXd::Identity(3, 3)));
steam::L2LossFunc::Ptr loss_func(new steam::L2LossFunc());

// cost terms
steam::ParallelizedCostTermCollection::Ptr cost_terms(
new steam::ParallelizedCostTermCollection());
for (int i = 0; i < ref_pts.cols(); i++) {
// Construct error function
steam::PointToPointErrorEval2::Ptr error_func(
new steam::PointToPointErrorEval2(T_mq_eval, ref_pts.block<3, 1>(0, i),
qry_pts.block<3, 1>(0, i)));

// Create cost term and add to problem
steam::WeightedLeastSqCostTerm<3, 6>::Ptr cost(
new steam::WeightedLeastSqCostTerm<3, 6>(error_func, noise_model,
loss_func));
cost_terms->add(cost);
}

// Initialize problem
steam::OptimizationProblem problem;
problem.addStateVariable(T_mq_var);
problem.addCostTerm(cost_terms);

typedef steam::VanillaGaussNewtonSolver SolverType;
SolverType::Params params;
params.verbose = true;

// Make solver
SolverType solver(&problem, params);

// Optimize
solver.optimize();

std::cout << "true T_mq:\n" << T_mq << std::endl;
std::cout << "estimated T_mq:\n" << T_mq_var->getValue() << std::endl;

return 0;
}
72 changes: 72 additions & 0 deletions src/evaluator/samples/PointToPointErrorEval2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
//////////////////////////////////////////////////////////////////////////////////////////////
/// \file PointToPointErrorEval2.cpp
///
/// \author Yuchen Wu, ASRL
/// \brief This evaluator was developed in the context of ICP (Iterative
/// Closest Point) implementation. It is different from
/// PointToPointErrorEval in that it takes points in cartesian
/// coordinates instead of homogeneous coordinates.
//////////////////////////////////////////////////////////////////////////////////////////////

#include <steam/evaluator/samples/PointToPointErrorEval2.hpp>

namespace steam {

//////////////////////////////////////////////////////////////////////////////////////////////
/// \brief Constructor
//////////////////////////////////////////////////////////////////////////////////////////////
PointToPointErrorEval2::PointToPointErrorEval2(
const se3::TransformEvaluator::ConstPtr &T_rq,
const Eigen::Vector3d &reference, const Eigen::Vector3d &query)
: T_rq_(T_rq) {
D_.block<3, 3>(0, 0) = Eigen::Matrix3d::Identity();
reference_.block<3, 1>(0, 0) = reference;
query_.block<3, 1>(0, 0) = query;
}

//////////////////////////////////////////////////////////////////////////////////////////////
/// \brief Returns whether or not an evaluator contains unlocked state variables
//////////////////////////////////////////////////////////////////////////////////////////////
bool PointToPointErrorEval2::isActive() const { return T_rq_->isActive(); }

//////////////////////////////////////////////////////////////////////////////////////////////
/// \brief Evaluate the 3-d measurement error (x, y, z)
//////////////////////////////////////////////////////////////////////////////////////////////
Eigen::Matrix<double, 3, 1> PointToPointErrorEval2::evaluate() const {
return D_ * (reference_ - T_rq_->evaluate() * query_);
}

//////////////////////////////////////////////////////////////////////////////////////////////
/// \brief Evaluate the 3-d measurement error (x, y, z) and Jacobians
//////////////////////////////////////////////////////////////////////////////////////////////
Eigen::Matrix<double, 3, 1> PointToPointErrorEval2::evaluate(
const Eigen::Matrix<double, 3, 3> &lhs,
std::vector<Jacobian<3, 6>> *jacs) const {
// Check and initialize jacobian array
if (jacs == NULL) {
throw std::invalid_argument(
"Null pointer provided to return-input 'jacs' in evaluate");
}
jacs->clear();

// Get evaluation tree
EvalTreeHandle<lgmath::se3::Transformation> blkAutoEvalPosOfTransformDiff =
T_rq_->getBlockAutomaticEvaluation();

// Get evaluation from tree
const lgmath::se3::Transformation T_rq =
blkAutoEvalPosOfTransformDiff.getValue();
Eigen::Matrix<double, 3, 1> error = D_ * (reference_ - T_rq * query_);

// Get Jacobians
const Eigen::Matrix<double, 3, 1> Tq = (T_rq * query_).block<3, 1>(0, 0);
const Eigen::Matrix<double, 3, 6> new_lhs =
-lhs * D_ * lgmath::se3::point2fs(Tq);
T_rq_->appendBlockAutomaticJacobians(
new_lhs, blkAutoEvalPosOfTransformDiff.getRoot(), jacs);

// Return evaluation
return error;
}

} // namespace steam

0 comments on commit 7876e10

Please sign in to comment.