Coverage Control Library
Loading...
Searching...
No Matches
generate_world_map.cu
Go to the documentation of this file.
1/*
2 * This file is part of the CoverageControl library
3 *
4 * Author: Saurav Agarwal
5 * Contact: sauravag@seas.upenn.edu, agr.saurav1@gmail.com
6 * Repository: https://github.com/KumarRobotics/CoverageControl
7 *
8 * Copyright (c) 2024, Saurav Agarwal
9 *
10 * The CoverageControl library is free software: you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or (at your
13 * option) any later version.
14 *
15 * The CoverageControl library is distributed in the hope that it will be
16 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
18 * Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along with
21 * CoverageControl library. If not, see <https://www.gnu.org/licenses/>.
22 */
23
29/*
30 * RTX 2080 Ti: CUDA Cores 4352, compute capablity: 7.5
31 * 68 SMs, 64 CUDA Cores/SM
32 * Block size: 32 x 32 = 1024 threads
33 * mean_x, mean_y, sigma, scale, rho: 5 * # of distributions
34 * resolution, size: 2
35 * map: pWorldMapSize * pWorldMapSize
36 */
37
38#include <cuda_runtime.h>
39#include <thrust/device_ptr.h>
40#include <thrust/extrema.h>
41
42#include <cmath>
43#include <sstream>
44
47#include "CoverageControl/extern/cuda_helpers/helper_cuda.h"
49
50namespace CoverageControl {
51__device__ __constant__ int cu_num_dists;
52__device__ __constant__ int cu_map_size;
53__device__ __constant__ float cu_resolution;
54__device__ __constant__ float cu_truncation;
55__device__ __constant__ float cu_trun_sq;
56__device__ __constant__ float cu_OneBySqrt2;
57__device__ __constant__ float cu_normalization_factor;
58__device__ __constant__ int cu_polygons_num_pts;
59__device__ __constant__ int cu_num_polygons;
60
61__device__ float2 TransformPoint(BND_Cuda const *device_dists, int i,
62 float2 const &in_point) {
63 float2 pt;
64 auto bnd = device_dists[i];
65 if (bnd.rho == 0) {
66 pt.x = (in_point.x - bnd.mean_x) / bnd.sigma_x;
67 pt.y = (in_point.y - bnd.mean_y) / bnd.sigma_y;
68 return pt;
69 }
70 pt.x = (in_point.x - bnd.mean_x) / bnd.sigma_x;
71 pt.y = (in_point.y - bnd.mean_y) / bnd.sigma_y;
72 pt.x = (pt.x - bnd.rho * pt.y) / (sqrt(1 - bnd.rho * bnd.rho));
73 return pt;
74}
75
76__device__ float IntegrateQuarterPlane(BND_Cuda const &bnd,
77 float2 const &in_point) {
78 float2 pt;
79 if (bnd.rho == 0) {
80 pt.x = (in_point.x - bnd.mean_x) / bnd.sigma_x;
81 pt.y = (in_point.y - bnd.mean_y) / bnd.sigma_y;
82 } else {
83 pt.x = (in_point.x - bnd.mean_x) / bnd.sigma_x;
84 pt.y = (in_point.y - bnd.mean_y) / bnd.sigma_y;
85 pt.x = (pt.x - bnd.rho * pt.y) / (sqrt(1 - bnd.rho * bnd.rho));
86 }
87 /* auto transformed_point = TransformPoint(i, in_point); */
88 float sc = bnd.scale;
89 /* return sc; */
90 return sc * erfc(pt.x * cu_OneBySqrt2) * erfc(pt.y * cu_OneBySqrt2) / 4.f;
91}
92
93__device__ float ComputeImportanceBND(BND_Cuda const *device_dists,
94 float2 const &bottom_left,
95 float2 const &top_right,
96 float2 const &mid_pt_cell) {
97 float2 bottom_right = make_float2(top_right.x, bottom_left.y);
98 float2 top_left = make_float2(bottom_left.x, top_right.y);
99
100 float total_importance = 0;
101 for (int i = 0; i < cu_num_dists; ++i) {
102 auto const &bnd = device_dists[i];
103 float2 mid_pt;
104 if (bnd.rho == 0) {
105 mid_pt.x = (mid_pt_cell.x - bnd.mean_x) / bnd.sigma_x;
106 mid_pt.y = (mid_pt_cell.y - bnd.mean_y) / bnd.sigma_y;
107 } else {
108 mid_pt.x = (mid_pt_cell.x - bnd.mean_x) / bnd.sigma_x;
109 mid_pt.y = (mid_pt_cell.y - bnd.mean_y) / bnd.sigma_y;
110 mid_pt.x =
111 (mid_pt.x - bnd.rho * mid_pt.y) / (sqrt(1 - bnd.rho * bnd.rho));
112 }
113 if (mid_pt.x * mid_pt.x + mid_pt.y * mid_pt.y > cu_trun_sq) {
114 continue;
115 }
116 total_importance += IntegrateQuarterPlane(bnd, bottom_left);
117 total_importance -= IntegrateQuarterPlane(bnd, bottom_right);
118 total_importance -= IntegrateQuarterPlane(bnd, top_left);
119 total_importance += IntegrateQuarterPlane(bnd, top_right);
120 }
121 return total_importance;
122}
123
124__device__ float ComputeImportancePoly(Polygons_Cuda const &device_polygons,
125 float2 const &mid_pt_cell) {
126 float total_importance = 0;
127 int start = 0;
128 auto &x = device_polygons.x;
129 auto &y = device_polygons.y;
130 for (int i = 0; i < cu_num_polygons; ++i) {
131 auto const &bounds = device_polygons.bounds[i];
132 if ((mid_pt_cell.x < bounds.xmin) || (mid_pt_cell.x > bounds.xmax) ||
133 (mid_pt_cell.y < bounds.ymin) || (mid_pt_cell.y > bounds.ymax)) {
134 start += device_polygons.sz[i];
135 continue;
136 }
137 int sz = device_polygons.sz[i];
138 if (IsPointInMonotonePolygon(&x[start], &y[start], sz, mid_pt_cell)) {
139 total_importance = fmaxf(total_importance, device_polygons.imp[i]);
140 }
141 start += sz;
142 }
143 return total_importance;
144}
145
146__global__ void kernel(BND_Cuda const *device_dists,
147 Polygons_Cuda const device_polygons,
148 float *importance_vec) {
149 int idx = blockIdx.x * blockDim.x + threadIdx.x;
150 int idy = blockIdx.y * blockDim.y + threadIdx.y;
151 int vec_idx = idx * cu_map_size + idy;
152 if (not(idx < cu_map_size and idy < cu_map_size)) {
153 return;
154 }
155 float2 bottom_left = make_float2(idx * cu_resolution, idy * cu_resolution);
156 float2 top_right = make_float2(idx * cu_resolution + cu_resolution,
158 float2 mid_pt_cell = make_float2((bottom_left.x + top_right.x) / 2.,
159 (bottom_left.y + top_right.y) / 2.);
160 float poly_importance = ComputeImportancePoly(device_polygons, mid_pt_cell);
161 importance_vec[vec_idx] =
162 ComputeImportanceBND(device_dists, bottom_left, top_right, mid_pt_cell) +
163 poly_importance;
164}
165
166__global__ void normalize(float *importance_vec) {
167 int idx = blockIdx.x * blockDim.x + threadIdx.x;
168 int idy = blockIdx.y * blockDim.y + threadIdx.y;
169 int vec_idx = idx * cu_map_size + idy;
170 if (not(idx < cu_map_size and idy < cu_map_size)) {
171 return;
172 }
173 importance_vec[vec_idx] *= cu_normalization_factor;
174}
176 Polygons_Cuda_Host const &host_polygons,
177 int const num_dists, int const map_size,
178 float const resolution, float const truncation,
179 float const pNorm, float *host_importance_vec,
180 float &normalization_factor) {
181 checkCudaErrors(cudaDeviceSynchronize());
182
183 checkCudaErrors(cudaMemcpyToSymbol(cu_num_dists, &num_dists, sizeof(int)));
184 checkCudaErrors(cudaMemcpyToSymbol(cu_map_size, &map_size, sizeof(int)));
185 checkCudaErrors(
186 cudaMemcpyToSymbol(cu_resolution, &resolution, sizeof(float)));
187 checkCudaErrors(
188 cudaMemcpyToSymbol(cu_truncation, &truncation, sizeof(float)));
189 float trun_sq = truncation * truncation;
190 checkCudaErrors(cudaMemcpyToSymbol(cu_trun_sq, &trun_sq, sizeof(float)));
191 float f_OneBySqrt2 = static_cast<float>(1. / std::sqrt(2.));
192 checkCudaErrors(
193 cudaMemcpyToSymbol(cu_OneBySqrt2, &f_OneBySqrt2, sizeof(float)));
194
195 BND_Cuda *device_dists;
196 checkCudaErrors(cudaMalloc(&device_dists, num_dists * sizeof(BND_Cuda)));
197 checkCudaErrors(cudaMemcpy(device_dists, host_dists,
198 num_dists * sizeof(BND_Cuda),
199 cudaMemcpyHostToDevice));
200
201 Polygons_Cuda device_polygons;
202 checkCudaErrors(
203 cudaMalloc(&(device_polygons.x), host_polygons.num_pts * sizeof(float)));
204 checkCudaErrors(
205 cudaMalloc(&(device_polygons.y), host_polygons.num_pts * sizeof(float)));
206 checkCudaErrors(cudaMalloc(&(device_polygons.imp),
207 host_polygons.num_polygons * sizeof(float)));
208 checkCudaErrors(cudaMalloc(&(device_polygons.sz),
209 host_polygons.num_polygons * sizeof(int)));
210 checkCudaErrors(cudaMalloc(&(device_polygons.bounds),
211 host_polygons.num_polygons * sizeof(Bounds)));
212
213 checkCudaErrors(cudaMemcpy(device_polygons.x, host_polygons.x.data(),
214 host_polygons.num_pts * sizeof(float),
215 cudaMemcpyHostToDevice));
216 checkCudaErrors(cudaMemcpy(device_polygons.y, host_polygons.y.data(),
217 host_polygons.num_pts * sizeof(float),
218 cudaMemcpyHostToDevice));
219 checkCudaErrors(cudaMemcpy(device_polygons.imp, host_polygons.imp.data(),
220 host_polygons.num_polygons * sizeof(float),
221 cudaMemcpyHostToDevice));
222 checkCudaErrors(cudaMemcpy(device_polygons.sz, host_polygons.sz.data(),
223 host_polygons.num_polygons * sizeof(int),
224 cudaMemcpyHostToDevice));
225 checkCudaErrors(cudaMemcpy(
226 device_polygons.bounds, host_polygons.bounds.data(),
227 host_polygons.num_polygons * sizeof(Bounds), cudaMemcpyHostToDevice));
228 checkCudaErrors(cudaMemcpyToSymbol(cu_polygons_num_pts,
229 &host_polygons.num_pts, sizeof(int)));
230 checkCudaErrors(cudaMemcpyToSymbol(cu_num_polygons,
231 &host_polygons.num_polygons, sizeof(int)));
232
233 float *device_importance_vec;
234 checkCudaErrors(
235 cudaMalloc(&device_importance_vec, map_size * map_size * sizeof(float)));
236
237 /* dim3 dimBlock(1, 1, 1); */
238 /* dim3 dimGrid(1,1,1); */
239
240 dim3 dimBlock(32, 32, 1);
241 dim3 dimGrid(map_size / dimBlock.x, map_size / dimBlock.x, 1);
242
243 kernel<<<dimGrid, dimBlock>>>(device_dists, device_polygons,
244 device_importance_vec);
245
246 cudaDeviceSynchronize();
247
248 thrust::device_ptr<float> d_ptr =
249 thrust::device_pointer_cast(device_importance_vec);
250 float max = *(thrust::max_element(d_ptr, d_ptr + map_size * map_size));
251
252 if (max < kEps) {
253 normalization_factor = pNorm;
254 } else {
255 normalization_factor = pNorm / max;
256 }
257 if (normalization_factor > 1e-5) {
258 checkCudaErrors(cudaMemcpyToSymbol(cu_normalization_factor,
259 &normalization_factor, sizeof(float)));
260 normalize<<<dimGrid, dimBlock>>>(device_importance_vec);
261 }
262
263 checkCudaErrors(cudaMemcpy(host_importance_vec, device_importance_vec,
264 map_size * map_size * sizeof(float),
265 cudaMemcpyDeviceToHost));
266
267 checkCudaErrors(cudaFree(device_dists));
268 checkCudaErrors(cudaFree(device_importance_vec));
269 checkCudaErrors(cudaFree(device_polygons.x));
270 checkCudaErrors(cudaFree(device_polygons.y));
271 checkCudaErrors(cudaFree(device_polygons.sz));
272 checkCudaErrors(cudaFree(device_polygons.bounds));
273
274 cudaError_t error = cudaGetLastError();
275 if (error != cudaSuccess) {
276 std::stringstream strstr;
277 strstr << "run_kernel launch failed" << std::endl;
278 throw strstr.str();
279 }
280}
281} /* namespace CoverageControl */
Constants for the CoverageControl library.
Contains structs and functions to interface with the CUDA code to generate the world map.
CUDA supported functions to check whether a point is inside a monotone polygon.
double const kEps
Definition constants.h:48
Namespace for the CoverageControl library.
__device__ __constant__ int cu_map_size
__device__ float ComputeImportancePoly(Polygons_Cuda const &device_polygons, float2 const &mid_pt_cell)
__device__ __constant__ float cu_OneBySqrt2
__device__ __constant__ float cu_truncation
__device__ __constant__ int cu_polygons_num_pts
__device__ float ComputeImportanceBND(BND_Cuda const *device_dists, float2 const &bottom_left, float2 const &top_right, float2 const &mid_pt_cell)
__device__ __constant__ int cu_num_polygons
__device__ __constant__ float cu_trun_sq
__device__ __constant__ float cu_normalization_factor
__device__ float IntegrateQuarterPlane(BND_Cuda const &bnd, float2 const &in_point)
__device__ float2 TransformPoint(BND_Cuda const *device_dists, int i, float2 const &in_point)
__device__ __constant__ int cu_num_dists
__global__ void kernel(BND_Cuda const *device_dists, Polygons_Cuda const device_polygons, float *importance_vec)
__device__ __constant__ float cu_resolution
__host__ __device__ bool IsPointInMonotonePolygon(float *x, float *y, int sz, float2 const &r)
__global__ void normalize(float *importance_vec)
void generate_world_map_cuda(BND_Cuda *, Polygons_Cuda_Host const &, int const, int const, float const, float const, float const, float *importance_vec, float &)
Function to generate the world map on the device.
Structure to store the parameters of the Bivariate Normal Distribution.
Structure to store the rectangular bounds of the polygons.
Structure to store the parameters of the polygons on the host.
Structure to store the parameters of the polygons on the device.