UFO 1.0.0
An Efficient Probabilistic 3D Mapping Framework That Embraces the Unknown
Loading...
Searching...
No Matches
render4d.cpp
1#ifdef UFO_TBB
2// #undef UFO_TBB
3#endif
4#ifdef UFO_OMP
5// #undef UFO_OMP
6#endif
7
8// UFO
9#include <ufo/map/color/map.hpp>
10#include <ufo/map/occupancy/map.hpp>
11#include <ufo/map/ufomap.hpp>
12#include <ufo/numeric/trans2.hpp>
13#include <ufo/vision/image.hpp>
14// #include <ufo/util/timing.hpp>
15#include <ufo/execution/execution.hpp>
16#include <ufo/pcl/cloud.hpp>
17#include <ufo/vision/camera.hpp>
18
19// STL
20#include <bitset>
21#include <cstddef>
22#include <cstdint>
23#include <cstdio>
24#include <filesystem>
25#include <fstream>
26#include <future>
27#include <iostream>
28#include <limits>
29#include <random>
30#include <string>
31#include <vector>
32
33// OpenCV
34#include <opencv2/core.hpp>
35#include <opencv2/highgui.hpp>
36
37// Happly
38#include <ufo/happly.h>
39
40using namespace ufo;
41
42int main(int argc, char* argv[])
43{
44 // Vec4f v1;
45 // Vec4f v2;
46
47 // Mat4x4f m;
48 // std::cout << "Before\n" << m << '\n';
49 // std::cout << "After\n" << inverse(m) << '\n';
50 // exit(1);
51
53
54 // ufo::Timing timer;
55
56 Vec3f min(100000, 100000, 100000);
57 Vec3f max(-100000, -100000, -100000);
58
59 happly::PLYData ply_in(RESOURCE_DIR "/scene0000_00_vh_clean.ply");
60 auto v_pos = ply_in.getVertexPositions();
61 auto v_col = ply_in.getVertexColors();
62 auto f_ind = ply_in.getFaceIndices<std::size_t>();
63 std::unordered_map<HexCode, std::vector<Color>> points;
64 for (auto f : f_ind) {
65 Triangle3 t(Vec3f(v_pos[f[0]][0], v_pos[f[0]][1], v_pos[f[0]][2]),
66 Vec3f(v_pos[f[1]][0], v_pos[f[1]][1], v_pos[f[1]][2]),
67 Vec3f(v_pos[f[2]][0], v_pos[f[2]][1], v_pos[f[2]][2]));
68
69 std::array c{Color(v_col[f[0]][0], v_col[f[0]][1], v_col[f[0]][2]),
70 Color(v_col[f[1]][0], v_col[f[1]][1], v_col[f[1]][2]),
71 Color(v_col[f[2]][0], v_col[f[2]][1], v_col[f[2]][2])};
72
73 for (std::size_t i{}; 3 > i; ++i) {
74 min = ufo::min(min, t[i]);
75 max = ufo::max(max, t[i]);
76 points[map.code(Vec4f(t[i], 0.004f))].emplace_back(c[i]);
77 points[map.code(Vec4f(t[i], 1.004f))].emplace_back(255, c[i].green, c[i].blue,
78 c[i].alpha);
79 points[map.code(Vec4f(t[i], 2.004f))].emplace_back(c[i].red, 255, c[i].blue,
80 c[i].alpha);
81 points[map.code(Vec4f(t[i], 3.004f))].emplace_back(c[i].red, c[i].green, 255,
82 c[i].alpha);
83 }
84 }
85
86 auto f = std::async(std::launch::async, [&map, &points]() {
87 for (auto const& [code, colors] : points) {
88 map.occupancySet(code, 1.0, true);
89 map.colorSet(code, Color::blend(colors, ColorBlendingMode::SQ_MEAN), true);
90 }
91 });
92
93 // f.wait();
94
95 // std::ofstream xyzrgb("/home/dduberg/ufo/xyzrgb.txt");
96 // for (auto node : map.query(pred::Leaf() && pred::Occupied())) {
97 // auto center = map.center(node.index());
98 // auto color = map.color(node.index());
99 // xyzrgb << center.x << ' ' << center.y << ' ' << 0.0f << ' ' << +color.red << ' '
100 // << +color.green << ' ' << +color.blue << '\n';
101 // }
102 // xyzrgb.close();
103
104 // auto inner_f = [&map](auto node, Ray2 /* ray */, float /* distance */) -> bool {
105 // return map.containsOccupied(node);
106 // };
107
108 // auto hit_f = [&map](auto node, Ray2 ray,
109 // float distance) -> std::pair<bool, std::pair<Vec2f, Color>> {
110 // float max_distance = 7.0f;
111 // return std::make_pair(map.isLeaf(node) && map.containsOccupied(node),
112 // std::make_pair(map.center(node), map.color(node)));
113 // };
114
115 // Ray2 ray(Vec2f(max - min) / 2.0f, Vec2f(1, 0));
116 // for (float theta{}; 2 * numbers::pi_v<float> > theta;
117 // theta += (2 * numbers::pi_v<float>) / 360.0f) {
118 // ray.direction.x = std::cos(theta);
119 // ray.direction.y = std::sin(theta);
120
121 // auto [p, c] = map.trace(
122 // ray, inner_f, hit_f,
123 // std::make_pair(Vec2f(std::numeric_limits<float>::quiet_NaN()), Color()));
124
125 // if (std::isnan(p.x)) {
126 // continue;
127 // }
128
129 // xyzrgb << p.x << ' ' << p.y << ' ' << 0.0f << ' ' << +c.red << ' ' << +c.green << '
130 // '
131 // << +c.blue << '\n';
132 // }
133 // xyzrgb.close();
134
135 Camera camera;
136 camera.vertical_fov = radians(60.0f);
137 camera.near_clip = 0.01;
138 camera.far_clip = 100.0;
139
140 std::size_t rows = 720; // 360; // 720; // 1080;
141 std::size_t cols = 1280; // 640; // 1280; // 1920;
142
143 std::size_t output_rows = rows / 1;
144 std::size_t output_cols = cols / 1;
145
146 rows /= 2;
147 cols /= 2;
148
149 double fps = 30.0;
150
151 std::vector<std::size_t> row_idx(rows);
152 std::iota(row_idx.begin(), row_idx.end(), 0);
153
154 std::vector<std::size_t> output_row_idx(output_rows);
155 std::iota(output_row_idx.begin(), output_row_idx.end(), 0);
156
157 Image<std::pair<Color, Color>> image(rows, cols);
158
159 cv::Mat img(output_rows, output_cols * 2, CV_8UC3);
160
161 double ufo_total_ms{};
162 double interpolate_total_ms{};
163 std::size_t iterations{};
164
165 float angle_x = 0.0f;
166 float angle_y = M_PI_2;
167 float zoom = -0.0f;
168
169 float w = 0.004f;
170
171 for (iterations = 1; true; ++iterations) {
172 auto const t1 = std::chrono::high_resolution_clock::now();
173
174 if (0 == iterations % 50) {
175 w = w + 1.0f;
176 if (4 < w) {
177 w = 0.004f;
178 }
179 }
180
181 Vec3f center(5.0f, 4.0f, 1.5f);
182
183 // camera.pose.translation = position; // (max - min) / 2.0f;
184 float cx = std::cos(angle_x);
185 float cy = std::cos(angle_y);
186 float sx = std::sin(angle_x);
187 float sy = std::sin(angle_y);
188 Vec3f offset = Vec3f(sy * cx, sy * sx, cy) * std::exp(-zoom);
189 // camera.lookAt(position + offset);
190 camera.pose =
191 static_cast<Trans3f>(lookAt<float, true>(center, center + offset, camera.up));
192 angle_x += 0.01f;
193
194 map.render(
195 execution::par, w, camera, image,
196 [&map](auto node, Ray4 /* ray */, float /* distance */) -> bool {
197 return map.containsOccupied(node);
198 },
199 [&map](auto node, Ray4 ray,
200 float distance) -> std::pair<bool, std::pair<Color, Color>> {
201 float max_distance = 7.0f;
202 return std::make_pair(
203 map.isLeaf(node) && map.containsOccupied(node),
204 std::make_pair(map.color(node),
205 Color(256 - 256 * distance / max_distance,
206 256 - 256 * distance / max_distance,
207 256 - 256 * distance / max_distance)));
208 },
209 std::make_pair(Color{}, Color{}));
210
211 auto const t2 = std::chrono::high_resolution_clock::now();
212
213 double row_scale = image.rows() / static_cast<double>(output_rows);
214 double col_scale = image.cols() / static_cast<double>(output_cols);
215
216 auto f = [&](std::size_t i) {
217 for (std::size_t j{}; j < output_cols; ++j) {
218 std::size_t i_scaled = std::floor(i * row_scale);
219 std::size_t j_scaled = std::floor(j * col_scale);
220 img.at<cv::Vec3b>(i, j)[2] = image(i_scaled, j_scaled).first.red;
221 img.at<cv::Vec3b>(i, j)[1] = image(i_scaled, j_scaled).first.green;
222 img.at<cv::Vec3b>(i, j)[0] = image(i_scaled, j_scaled).first.blue;
223 img.at<cv::Vec3b>(i, output_cols + j)[2] = image(i_scaled, j_scaled).second.red;
224 img.at<cv::Vec3b>(i, output_cols + j)[1] = image(i_scaled, j_scaled).second.green;
225 img.at<cv::Vec3b>(i, output_cols + j)[0] = image(i_scaled, j_scaled).second.blue;
226 }
227 };
228
229#if defined(UFO_TBB)
230 std::for_each(std::execution::par_unseq, output_row_idx.begin(), output_row_idx.end(),
231 f);
232#else
233#if defined(UFO_OMP)
234#pragma omp parallel for
235#endif
236 for (std::size_t i = 0; i < output_rows; ++i) {
237 f(i);
238 }
239#endif
240
241 auto const t3 = std::chrono::high_resolution_clock::now();
242 std::chrono::duration<double, std::milli> const ufo_ms = t2 - t1;
243 std::chrono::duration<double, std::milli> const interpolate_ms = t3 - t2;
244
245 ufo_total_ms += ufo_ms.count();
246 interpolate_total_ms += interpolate_ms.count();
247
248 std::chrono::duration<double, std::milli> const total_ms = t3 - t1;
249
250 std::cout << std::setw(28) << std::left
251 << "UFO took: " << (ufo_total_ms / iterations) << " ms\n";
252 std::cout << std::setw(28) << std::left
253 << "Interpolate took: " << (interpolate_total_ms / iterations) << " ms\n";
254 std::cout << std::setw(28) << std::left << "Total: "
255 << ((ufo_total_ms + interpolate_total_ms) / iterations) << " ms\n";
256
257 cv::imshow("UFOMap Rendered View", img);
258 std::cout << "Wait "
259 << std::max(1, static_cast<int>(1000 * (1.0 / fps) - total_ms.count()))
260 << " ms\n";
261 // Wait for a keystroke in the window
262 int k =
263 cv::waitKey(std::max(1, static_cast<int>(1000 * (1.0 / fps) - total_ms.count())));
264
265 // cv::waitKey();
266 }
267
268 return 0;
269}
Image class for storing and manipulating 2D pixel data.
Definition image.hpp:78
constexpr T radians(T deg) noexcept
Converts degrees to radians.
Definition math.hpp:86
All vision-related classes and functions.
Definition cloud.hpp:49
constexpr T green(Lrgb< T, Flags > color) noexcept
Returns the un-weighted green channel value.
Definition lrgb.hpp:309
constexpr Vec< Geometry::dimension(), typename Geometry::value_type > max(Geometry const &g)
Returns the maximum coordinate of the minimum spanning axis-aligned bounding box of a geometry.
Definition fun.hpp:72
constexpr T blue(Lrgb< T, Flags > color) noexcept
Returns the un-weighted blue channel value.
Definition lrgb.hpp:325
constexpr alpha_type_t< C > alpha(C color) noexcept
Returns the un-weighted alpha of color.
Definition alpha.hpp:105
constexpr T red(Lrgb< T, Flags > color) noexcept
Returns the un-weighted red channel value.
Definition lrgb.hpp:293
constexpr Vec< Geometry::dimension(), typename Geometry::value_type > min(Geometry const &g)
Returns the minimum coordinate of the minimum spanning axis-aligned bounding box of a geometry.
Definition fun.hpp:58
constexpr auto distance(A const &a, B const &b)
Computes the minimum distance between two shapes.
Definition distance.hpp:61
Ray in Dim-dimensional space.
Definition ray.hpp:66
Triangle in Dim-dimensional space.
Definition triangle.hpp:70