|
13 | 13 | import unittest |
14 | 14 |
|
15 | 15 | import gtsam |
16 | | -from gtsam import ShonanAveraging3, ShonanAveragingParameters3 |
| 16 | +from gtsam import ( |
| 17 | + BetweenFactorPose2, |
| 18 | + LevenbergMarquardtParams, |
| 19 | + Rot2, |
| 20 | + Pose2, |
| 21 | + ShonanAveraging2, |
| 22 | + ShonanAveragingParameters2, |
| 23 | + ShonanAveraging3, |
| 24 | + ShonanAveragingParameters3 |
| 25 | +) |
17 | 26 | from gtsam.utils.test_case import GtsamTestCase |
18 | 27 |
|
19 | 28 | DEFAULT_PARAMS = ShonanAveragingParameters3( |
20 | 29 | gtsam.LevenbergMarquardtParams.CeresDefaults()) |
21 | 30 |
|
22 | 31 |
|
23 | | -def fromExampleName(name: str, parameters=DEFAULT_PARAMS): |
| 32 | +def fromExampleName( |
| 33 | + name: str, parameters: ShonanAveragingParameters3 = DEFAULT_PARAMS |
| 34 | +) -> ShonanAveraging3: |
24 | 35 | g2oFile = gtsam.findExampleDataFile(name) |
25 | 36 | return ShonanAveraging3(g2oFile, parameters) |
26 | 37 |
|
@@ -133,6 +144,57 @@ def test_PriorWeights(self): |
133 | 144 | self.assertAlmostEqual(3.0756, shonan.cost(initial), places=3) |
134 | 145 | result, _lambdaMin = shonan.run(initial, 3, 3) |
135 | 146 | self.assertAlmostEqual(0.0015, shonan.cost(result), places=3) |
| 147 | + |
| 148 | + def test_constructorBetweenFactorPose2s(self) -> None: |
| 149 | + """Check if ShonanAveraging2 constructor works when not initialized from g2o file.""" |
| 150 | + # map (i1,i2) pair to theta in degrees that parameterizes Rot2 object i2Ri1 |
| 151 | + i2Ri1_dict = { |
| 152 | + (1, 2): -43.86342, |
| 153 | + (1, 5): -135.06351, |
| 154 | + (2, 4): 72.64527, |
| 155 | + (3, 5): 117.75967, |
| 156 | + (6, 7): -31.73934, |
| 157 | + (7, 10): 177.45901, |
| 158 | + (6, 9): -133.58713, |
| 159 | + (7, 8): -90.58668, |
| 160 | + (0, 3): 127.02978, |
| 161 | + (8, 10): -92.16361, |
| 162 | + (4, 8): 51.63781, |
| 163 | + (4, 6): 173.96384, |
| 164 | + (4, 10): 139.59445, |
| 165 | + (2, 3): 151.04022, |
| 166 | + (3, 4): -78.39495, |
| 167 | + (1, 4): 28.78185, |
| 168 | + (6, 8): -122.32602, |
| 169 | + (0, 2): -24.01045, |
| 170 | + (5, 7): -53.93014, |
| 171 | + (4, 5): -163.84535, |
| 172 | + (2, 5): -91.20009, |
| 173 | + (1, 3): 107.17680, |
| 174 | + (7, 9): -102.35615, |
| 175 | + (0, 1): 19.85297, |
| 176 | + (5, 8): -144.51682, |
| 177 | + (5, 6): -22.19079, |
| 178 | + (5, 10): -56.56016, |
| 179 | + } |
| 180 | + i2Ri1_dict = {(i1,i2): Rot2.fromDegrees(theta_deg) for (i1,i2), theta_deg in i2Ri1_dict.items()} |
| 181 | + lm_params = LevenbergMarquardtParams.CeresDefaults() |
| 182 | + shonan_params = ShonanAveragingParameters2(lm_params) |
| 183 | + shonan_params.setUseHuber(False) |
| 184 | + shonan_params.setCertifyOptimality(True) |
| 185 | + |
| 186 | + noise_model = gtsam.noiseModel.Unit.Create(3) |
| 187 | + between_factors = gtsam.BetweenFactorPose2s() |
| 188 | + for (i1, i2), i2Ri1 in i2Ri1_dict.items(): |
| 189 | + i2Ti1 = Pose2(i2Ri1, np.zeros(2)) |
| 190 | + between_factors.append(BetweenFactorPose2(i2, i1, i2Ti1, noise_model)) |
| 191 | + |
| 192 | + obj = ShonanAveraging2(between_factors, shonan_params) |
| 193 | + initial = obj.initializeRandomly() |
| 194 | + result_values, _ = obj.run(initial, p_min, self._p_max) |
| 195 | + |
| 196 | + for i in range(11): |
| 197 | + wRi = result_values.atRot2(i) |
136 | 198 |
|
137 | 199 |
|
138 | 200 | if __name__ == '__main__': |
|
0 commit comments