NASA Astrobee Robot Software  0.19.1
Flight software for the Astrobee robots operating inside the International Space Station.
between_factor_node_adder_model.h
Go to the documentation of this file.
1 /* Copyright (c) 2017, United States Government, as represented by the
2  * Administrator of the National Aeronautics and Space Administration.
3  *
4  * All rights reserved.
5  *
6  * The Astrobee platform is licensed under the Apache License, Version 2.0
7  * (the "License"); you may not use this file except in compliance with the
8  * License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15  * License for the specific language governing permissions and limitations
16  * under the License.
17  */
18 
19 #ifndef NODE_ADDERS_BETWEEN_FACTOR_NODE_ADDER_MODEL_H_
20 #define NODE_ADDERS_BETWEEN_FACTOR_NODE_ADDER_MODEL_H_
21 
24 #include <node_adders/utilities.h>
26 
27 #include <gtsam/inference/Key.h>
28 #include <gtsam/geometry/Pose3.h>
29 #include <gtsam/nonlinear/NonlinearFactorGraph.h>
30 #include <gtsam/slam/BetweenFactor.h>
31 
32 #include <utility>
33 #include <vector>
34 
35 namespace node_adders {
36 // Node adder model that adds GTSAM between factors as relative factors and GTSAM prior factors as priors
37 // for a given node type.
38 template <typename NodeType, typename NodeAdderModelType>
39 class BetweenFactorNodeAdderModel : public NodeAdderModelType {
40  public:
42  using Base = NodeAdderModelType;
44  virtual ~BetweenFactorNodeAdderModel() = default;
45  // Adds prior factors for a given node using provided noise models.
46  void AddPriors(const NodeType& node, const std::vector<gtsam::SharedNoiseModel>& noise_models,
47  const localization_common::Time timestamp, const NodesType& nodes,
48  gtsam::NonlinearFactorGraph& factors) const final;
49 
50  // Adds nodes for provided timestamps and connects them with between factors.
52  const localization_common::Time timestamp_b, NodesType& nodes,
53  gtsam::NonlinearFactorGraph& factors) const final;
54 
55  // Connects nodes at given timestamps with between factors.
56  bool AddRelativeFactors(const localization_common::Time timestamp_a, const localization_common::Time timestamp_b,
57  const NodesType& nodes, gtsam::NonlinearFactorGraph& factors) const final;
58 
59  bool RemoveRelativeFactors(const localization_common::Time timestamp_a, const localization_common::Time timestamp_b,
60  const NodesType& nodes, gtsam::NonlinearFactorGraph& factors) const final;
61 
62  private:
63  // Connects nodes at given keys with between factors.
64  bool AddRelativeFactors(const gtsam::KeyVector& keys_a, const localization_common::Time timestamp_a,
65  const gtsam::KeyVector& keys_b, const localization_common::Time timestamp_b,
66  gtsam::NonlinearFactorGraph& factors) const;
67 
68  // Adds a node at the given timestamp.
69  // Needs to be implemented by the child class
70  virtual gtsam::KeyVector AddNode(const localization_common::Time timestamp, NodesType& nodes) const = 0;
71 
72  // Creates a node with noise at timestamp_b relative to timestamp_a.
73  // Needs to be implemented by the child class
74  virtual boost::optional<std::pair<NodeType, gtsam::SharedNoiseModel>> RelativeNodeAndNoise(
75  const localization_common::Time timestamp_a, const localization_common::Time timestamp_b) const = 0;
76 
77  // Serialization function
79  template <class Archive>
80  void serialize(Archive& ar, const unsigned int file_version) {
81  ar& BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base);
82  }
83 };
84 
85 // Implementation
86 template <typename NodeType, typename NodeAdderModelType>
88  const NodeType& node, const std::vector<gtsam::SharedNoiseModel>& noise_models,
89  const localization_common::Time timestamp, const NodesType& nodes, gtsam::NonlinearFactorGraph& factors) const {
90  const auto keys = nodes.Keys(timestamp);
91  if (keys.empty()) {
92  LogError("AddPriors: Failed to get keys.");
93  return;
94  }
95  // TODO(rsoussan): Ensure symbols not used by other node adders
96  gtsam::PriorFactor<NodeType> prior_factor(keys[0], node, noise_models[0]);
97  factors.push_back(prior_factor);
98 }
99 
100 template <typename NodeType, typename NodeAdderModelType>
102  const localization_common::Time timestamp_a, const localization_common::Time timestamp_b, NodesType& nodes,
103  gtsam::NonlinearFactorGraph& factors) const {
104  if (!nodes.Contains(timestamp_b)) {
105  const auto keys = AddNode(timestamp_b, nodes);
106  if (keys.empty()) {
107  LogError("AddNodesAndRelativeFactors: Failed to add node.");
108  return false;
109  }
110  }
111 
112  if (!AddRelativeFactors(timestamp_a, timestamp_b, nodes, factors)) {
113  LogError("AddNodesAndRelativeFactors: Failed to add relative factor.");
114  return false;
115  }
116  return true;
117 }
118 
119 template <typename NodeType, typename NodeAdderModelType>
121  const localization_common::Time timestamp_a, const localization_common::Time timestamp_b, const NodesType& nodes,
122  gtsam::NonlinearFactorGraph& factors) const {
123  const auto keys_a = nodes.Keys(timestamp_a);
124  if (keys_a.empty()) {
125  LogError("AddRelativeFactors: Failed to get keys a.");
126  return false;
127  }
128  const auto keys_b = nodes.Keys(timestamp_b);
129  if (keys_b.empty()) {
130  LogError("AddRelativeFactors: Failed to get keys b.");
131  return false;
132  }
133  if (!AddRelativeFactors(keys_a, timestamp_a, keys_b, timestamp_b, factors)) {
134  LogError("AddRelativeFactor: Failed to add relative factor.");
135  return false;
136  }
137  return true;
138 }
139 
140 template <typename NodeType, typename NodeAdderModelType>
142  const gtsam::KeyVector& keys_a, const localization_common::Time timestamp_a, const gtsam::KeyVector& keys_b,
143  const localization_common::Time timestamp_b, gtsam::NonlinearFactorGraph& factors) const {
144  const auto relative_node_and_noise = RelativeNodeAndNoise(timestamp_a, timestamp_b);
145  if (!relative_node_and_noise) {
146  LogError("AddRelativeFactor: Failed to add relative node and noise.");
147  return false;
148  }
149 
150  typename gtsam::BetweenFactor<NodeType>::shared_ptr relative_factor(new gtsam::BetweenFactor<NodeType>(
151  keys_a[0], keys_b[0], relative_node_and_noise->first, relative_node_and_noise->second));
152  factors.push_back(relative_factor);
153  return true;
154 }
155 
156 template <typename NodeType, typename NodeAdderModelType>
158  const localization_common::Time timestamp_a, const localization_common::Time timestamp_b, const NodesType& nodes,
159  gtsam::NonlinearFactorGraph& factors) const {
160  return RemoveRelativeFactor<gtsam::BetweenFactor<NodeType>>(timestamp_a, timestamp_b, nodes, factors);
161 }
162 
163 // Specialization helpers
164 template <typename MeasurementType, typename NodeType>
167 
168 template <typename NodeType>
171 } // namespace node_adders
172 
173 #endif // NODE_ADDERS_BETWEEN_FACTOR_NODE_ADDER_MODEL_H_
node_adders::BetweenFactorNodeAdderModel::AddNodesAndRelativeFactors
bool AddNodesAndRelativeFactors(const localization_common::Time timestamp_a, const localization_common::Time timestamp_b, NodesType &nodes, gtsam::NonlinearFactorGraph &factors) const final
Definition: between_factor_node_adder_model.h:101
node_adders::BetweenFactorNodeAdderModel::NodesType
nodes::TimestampedNodes< NodeType > NodesType
Definition: between_factor_node_adder_model.h:41
node_adders::BetweenFactorNodeAdderModel::Base
NodeAdderModelType Base
Definition: between_factor_node_adder_model.h:42
node_adders::BetweenFactorNodeAdderModel::BetweenFactorNodeAdderModel
BetweenFactorNodeAdderModel(const TimestampedNodeAdderModelParams &params)
Definition: between_factor_node_adder_model.h:43
node_adders::BetweenFactorNodeAdderModel::RemoveRelativeFactors
bool RemoveRelativeFactors(const localization_common::Time timestamp_a, const localization_common::Time timestamp_b, const NodesType &nodes, gtsam::NonlinearFactorGraph &factors) const final
Definition: between_factor_node_adder_model.h:157
LogError
#define LogError(msg)
Definition: logger.h:55
nodes
Definition: combined_nav_state_nodes.h:24
node_adders
Definition: between_factor_node_adder_model.h:35
node_adders::BetweenFactorNodeAdderModel::access
friend class boost::serialization::access
Definition: between_factor_node_adder_model.h:78
utilities.h
node_adders::BetweenFactorNodeAdderModel::AddPriors
void AddPriors(const NodeType &node, const std::vector< gtsam::SharedNoiseModel > &noise_models, const localization_common::Time timestamp, const NodesType &nodes, gtsam::NonlinearFactorGraph &factors) const final
Definition: between_factor_node_adder_model.h:87
node_adders::BetweenFactorNodeAdderModel::~BetweenFactorNodeAdderModel
virtual ~BetweenFactorNodeAdderModel()=default
measurement_based_timestamped_node_adder_model.h
node_adders::BetweenFactorNodeAdderModel
Definition: between_factor_node_adder_model.h:39
timestamped_nodes.h
nodes::TimestampedNodes
Definition: timestamped_nodes.h:28
node_adders::BetweenFactorNodeAdderModel::AddRelativeFactors
bool AddRelativeFactors(const localization_common::Time timestamp_a, const localization_common::Time timestamp_b, const NodesType &nodes, gtsam::NonlinearFactorGraph &factors) const final
Definition: between_factor_node_adder_model.h:120
node_adders::MeasurementBasedTimestampedNodeAdderModel
Definition: measurement_based_timestamped_node_adder_model.h:32
node_adders::TimestampedNodeAdderModelParams
Definition: timestamped_node_adder_model_params.h:24
localization_common::Time
double Time
Definition: time.h:23
timestamped_node_adder_model.h