Converts pixel coordinates in a ZED2i pointcloud into global UTM coordinates, given the rover's current pose and a point cloud from the camera.
56 {
57
58 if (nNeighborhoodSize < 1)
59 {
60 LOG_WARNING(logging::g_qSharedLogger, "GeolocateBox: Invalid neighborhood size {}, defaulting to 5x5", nNeighborhoodSize);
61 nNeighborhoodSize = 5;
62 }
63
64
65 int nHalfSize = nNeighborhoodSize / 2;
66
67
68 std::vector<float> vX, vY, vZ, vDistances;
69
70
71 for (int nOffsetY = -nHalfSize; nOffsetY <= nHalfSize; ++nOffsetY)
72 {
73 for (int nOffsetX = -nHalfSize; nOffsetX <= nHalfSize; ++nOffsetX)
74 {
75
76 int nCurrY = cvPixel.
y + nOffsetY;
77 int nCurrX = cvPixel.
x + nOffsetX;
78
79
80 if (nCurrY < 0 || nCurrY >= cvPointcloud.
rows || nCurrX < 0 || nCurrX >= cvPointcloud.
cols)
81 {
82 continue;
83 }
84
85
87
88
89 if (cvPoint[2] > 0 && std::isfinite(cvPoint[0]) && std::isfinite(cvPoint[1]) && std::isfinite(cvPoint[2]))
90 {
91
92 vX.push_back(cvPoint[0]);
93 vY.push_back(cvPoint[1]);
94 vZ.push_back(cvPoint[2]);
95 }
96 }
97 }
98
99
100 if (vX.empty())
101 {
102 LOG_DEBUG(logging::g_qSharedLogger,
"GeolocateBox: No valid points found in neighborhood around pixel ({}, {})", cvPixel.
x, cvPixel.
y);
103
105 }
106
107
108 float fAvgX = std::accumulate(vX.begin(), vX.end(), 0.0f) / vX.size();
109 float fAvgY = std::accumulate(vY.begin(), vY.end(), 0.0f) / vY.size();
110 float fAvgZ = std::accumulate(vZ.begin(), vZ.end(), 0.0f) / vZ.size();
111
112
114
115 double dHeadingRad = dAdjustedHeading * M_PI / 180.0;
116
117
119
120
121
122
123
124
125
126
127 double dEasting = stRoverUTM.dEasting + (fAvgZ *
cos(dHeadingRad) + fAvgX *
sin(dHeadingRad));
128 double dNorthing = stRoverUTM.dNorthing + (fAvgZ *
sin(dHeadingRad) - fAvgX *
cos(dHeadingRad));
129
130
131 double dAltitude = stRoverUTM.dAltitude + fAvgY;
132
133
134 geoops::UTMCoordinate stObjectUTM(dEasting, dNorthing, stRoverUTM.nZone, stRoverUTM.bWithinNorthernHemisphere, dAltitude);
135
136
137 double dRadius = 0.0;
138 if (vX.size() > 1)
139 {
140
141 for (size_t siI = 0; siI < vX.size(); ++siI)
142 {
143 double dX = vX[siI] - fAvgX;
144 double dY = vY[siI] - fAvgY;
145 double dZ = vZ[siI] - fAvgZ;
146 vDistances.push_back(
sqrt(dX * dX + dY * dY + dZ * dZ));
147 }
148
149
150 std::sort(vDistances.begin(), vDistances.end());
151 if (vDistances.size() % 2 == 0)
152 {
153 dRadius = (vDistances[vDistances.size() / 2 - 1] + vDistances[vDistances.size() / 2]) / 2.0;
154 }
155 else
156 {
157 dRadius = vDistances[vDistances.size() / 2];
158 }
159
160
161 dRadius *= 1.5;
162 }
163
164
165 return geoops::Waypoint(stObjectUTM, geoops::WaypointType::eUNKNOWN, dRadius);
166 }
void sqrt(InputArray src, OutputArray dst)
__device__ __forceinline__ float1 cos(const uchar1 &a)
__device__ __forceinline__ float4 sin(const uchar4 &a)
constexpr T InputAngleModulus(T tValue, T tMinValue, T tMaxValue)
Calculates the modulus of an input angle.
Definition NumberOperations.hpp:165
double GetCompassHeading() const
Accessor for the Compass Heading private member.
Definition GeospatialOperations.hpp:756
const geoops::UTMCoordinate & GetUTMCoordinate() const
Accessor for the geoops::UTMCoordinate member variable.
Definition GeospatialOperations.hpp:736
This struct stores/contains information about a UTM coordinate.
Definition GeospatialOperations.hpp:195
This struct is used by the WaypointHandler class to store location, size, and type information about ...
Definition GeospatialOperations.hpp:392