Open3D (C++ API)  0.18.0
RobustKernelImpl.h
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - Open3D: www.open3d.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2023 www.open3d.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 #pragma once
9 
10 #include <cmath>
11 
12 #include "open3d/core/CUDAUtils.h"
15 
16 #ifndef __CUDACC__
17 using std::abs;
18 using std::exp;
19 using std::max;
20 using std::min;
21 using std::pow;
22 #endif
23 
25 
35 #define DISPATCH_ROBUST_KERNEL_FUNCTION(METHOD, scalar_t, scaling_parameter, \
36  shape_parameter, ...) \
37  [&] { \
38  scalar_t scale = static_cast<scalar_t>(scaling_parameter); \
39  if (METHOD == RobustKernelMethod::L2Loss) { \
40  auto GetWeightFromRobustKernel = \
41  [=] OPEN3D_HOST_DEVICE(scalar_t residual) -> scalar_t { \
42  return 1.0; \
43  }; \
44  return __VA_ARGS__(); \
45  } else if (METHOD == RobustKernelMethod::L1Loss) { \
46  auto GetWeightFromRobustKernel = \
47  [=] OPEN3D_HOST_DEVICE(scalar_t residual) -> scalar_t { \
48  return 1.0 / abs(residual); \
49  }; \
50  return __VA_ARGS__(); \
51  } else if (METHOD == RobustKernelMethod::HuberLoss) { \
52  auto GetWeightFromRobustKernel = \
53  [=] OPEN3D_HOST_DEVICE(scalar_t residual) -> scalar_t { \
54  return scale / max(abs(residual), scale); \
55  }; \
56  return __VA_ARGS__(); \
57  } else if (METHOD == RobustKernelMethod::CauchyLoss) { \
58  auto GetWeightFromRobustKernel = \
59  [=] OPEN3D_HOST_DEVICE(scalar_t residual) -> scalar_t { \
60  return 1.0 / (1.0 + Square(residual / scale)); \
61  }; \
62  return __VA_ARGS__(); \
63  } else if (METHOD == RobustKernelMethod::GMLoss) { \
64  auto GetWeightFromRobustKernel = \
65  [=] OPEN3D_HOST_DEVICE(scalar_t residual) -> scalar_t { \
66  return scale / Square(scale + Square(residual)); \
67  }; \
68  return __VA_ARGS__(); \
69  } else if (METHOD == RobustKernelMethod::TukeyLoss) { \
70  auto GetWeightFromRobustKernel = \
71  [=] OPEN3D_HOST_DEVICE(scalar_t residual) -> scalar_t { \
72  return Square(1.0 - Square(min((scalar_t)1.0, \
73  abs(residual) / scale))); \
74  }; \
75  return __VA_ARGS__(); \
76  } else if (METHOD == RobustKernelMethod::GeneralizedLoss) { \
77  if (open3d::IsClose(shape_parameter, 2.0, 1e-3)) { \
78  auto const_val = 1.0 / Square(scale); \
79  auto GetWeightFromRobustKernel = \
80  [=] OPEN3D_HOST_DEVICE( \
81  scalar_t residual) -> scalar_t { \
82  return const_val; \
83  }; \
84  return __VA_ARGS__(); \
85  } else if (open3d::IsClose(shape_parameter, 0.0, 1e-3)) { \
86  auto GetWeightFromRobustKernel = \
87  [=] OPEN3D_HOST_DEVICE( \
88  scalar_t residual) -> scalar_t { \
89  return 2.0 / (Square(residual) + 2 * Square(scale)); \
90  }; \
91  return __VA_ARGS__(); \
92  } else if (shape_parameter < -1e7) { \
93  auto GetWeightFromRobustKernel = \
94  [=] OPEN3D_HOST_DEVICE( \
95  scalar_t residual) -> scalar_t { \
96  return exp(Square(residual / scale) / (-2.0)) / \
97  Square(scale); \
98  }; \
99  return __VA_ARGS__(); \
100  } else { \
101  auto GetWeightFromRobustKernel = \
102  [=] OPEN3D_HOST_DEVICE( \
103  scalar_t residual) -> scalar_t { \
104  return pow((Square(residual / scale) / \
105  abs(shape_parameter - 2.0) + \
106  1), \
107  ((shape_parameter / 2.0) - 1.0)) / \
108  Square(scale); \
109  }; \
110  return __VA_ARGS__(); \
111  } \
112  } else { \
113  utility::LogError("Unsupported method."); \
114  } \
115  }()
116 
122 #define DISPATCH_DUAL_ROBUST_KERNEL_FUNCTION(scalar_t, METHOD_1, \
123  scaling_parameter_1, METHOD_2, \
124  scaling_parameter_2, ...) \
125  [&] { \
126  scalar_t scale_1 = static_cast<scalar_t>(scaling_parameter_1); \
127  scalar_t scale_2 = static_cast<scalar_t>(scaling_parameter_2); \
128  if (METHOD_1 == RobustKernelMethod::L2Loss && \
129  METHOD_2 == RobustKernelMethod::L2Loss) { \
130  auto GetWeightFromRobustKernelFirst = \
131  [=] OPEN3D_HOST_DEVICE(scalar_t residual) -> scalar_t { \
132  return 1.0; \
133  }; \
134  auto GetWeightFromRobustKernelSecond = \
135  [=] OPEN3D_HOST_DEVICE(scalar_t residual) -> scalar_t { \
136  return 1.0; \
137  }; \
138  return __VA_ARGS__(); \
139  } else if (METHOD_1 == RobustKernelMethod::L2Loss && \
140  METHOD_2 == RobustKernelMethod::TukeyLoss) { \
141  auto GetWeightFromRobustKernelFirst = \
142  [=] OPEN3D_HOST_DEVICE(scalar_t residual) -> scalar_t { \
143  return 1.0; \
144  }; \
145  auto GetWeightFromRobustKernelSecond = \
146  [=] OPEN3D_HOST_DEVICE(scalar_t residual) -> scalar_t { \
147  return Square(1.0 - Square(min((scalar_t)1.0, \
148  abs(residual) / scale_2))); \
149  }; \
150  return __VA_ARGS__(); \
151  } else if (METHOD_1 == RobustKernelMethod::TukeyLoss && \
152  METHOD_2 == RobustKernelMethod::L2Loss) { \
153  auto GetWeightFromRobustKernelFirst = \
154  [=] OPEN3D_HOST_DEVICE(scalar_t residual) -> scalar_t { \
155  return Square(1.0 - Square(min((scalar_t)1.0, \
156  abs(residual) / scale_1))); \
157  }; \
158  auto GetWeightFromRobustKernelSecond = \
159  [=] OPEN3D_HOST_DEVICE(scalar_t residual) -> scalar_t { \
160  return 1.0; \
161  }; \
162  return __VA_ARGS__(); \
163  } else if (METHOD_1 == RobustKernelMethod::TukeyLoss && \
164  METHOD_2 == RobustKernelMethod::TukeyLoss) { \
165  auto GetWeightFromRobustKernelFirst = \
166  [=] OPEN3D_HOST_DEVICE(scalar_t residual) -> scalar_t { \
167  return Square(1.0 - Square(min((scalar_t)1.0, \
168  abs(residual) / scale_1))); \
169  }; \
170  auto GetWeightFromRobustKernelSecond = \
171  [=] OPEN3D_HOST_DEVICE(scalar_t residual) -> scalar_t { \
172  return Square(1.0 - Square(min((scalar_t)1.0, \
173  abs(residual) / scale_2))); \
174  }; \
175  return __VA_ARGS__(); \
176  } else { \
177  utility::LogError("Unsupported method."); \
178  } \
179  }()
Common CUDA utilities.
RobustKernelMethod
Definition: RobustKernel.h:15