iterative closest points
CEV ICP algorithm library
Loading...
Searching...
No Matches
main.cpp
Go to the documentation of this file.
1// Copyright (C) 2024 Ethan Uppal. All rights reserved.
2
3#include <iostream>
4extern "C" {
5#include <cmdapp/cmdapp.h>
6#include <config/config.h>
7}
8#include <chrono>
9#include <numeric>
10#include <algorithm>
11#include <sdlwrapper/gui/window.h>
12#include <optional>
13#include "view_config.h"
14#include "lidar_view.h"
15#include "icp/impl/vanilla.h"
16#include "icp/impl/trimmed.h"
17#include "icp/driver.h"
18#include "parse_scan.h"
19
20void set_config_param(const char* var, const char* data, [[maybe_unused]] void* user_data) {
21 if (strcmp(var, "x_displace") == 0) {
22 view_config::x_displace = std::stod(data);
23 } else if (strcmp(var, "y_displace") == 0) {
24 view_config::y_displace = std::stod(data);
25 } else if (strcmp(var, "window_width") == 0) {
26 view_config::window_width = std::stoi(data);
27 } else if (strcmp(var, "window_height") == 0) {
28 view_config::window_height = std::stoi(data);
29 }
30}
31
32void parse_config(const char* path) {
33 FILE* file = fopen(path, "r");
34 if (!file) {
35 perror("parse_config: fopen");
36 std::exit(1);
37 }
38
39 if (conf_parse_file(file, set_config_param, nullptr) != 0) {
40 perror("parse_config: conf_parse_file");
41 std::exit(1);
42 }
43
44 fclose(file);
45}
46
47void assert_opt(bool* opt_result) {
48 if (!opt_result) {
49 std::exit(1);
50 }
51}
52
53void launch_gui(LidarView* view, std::string visualized = "LiDAR scans") {
54 Window window("Scan Matching", view_config::window_width, view_config::window_height);
55
56 window.attach_view(view);
57
58 std::cout << "SCAN MATCHING : ITERATIVE CLOSEST POINT\n";
59 std::cout << "=======================================\n";
60 std::cout << "* Visualizing: " << visualized << '\n';
61 std::cout << "* Press the red <X> on the window to exit\n";
62 std::cout << "* Press SPACE to toggle the simulation\n";
63 std::cout << "* Press D to display the current transform\n";
64 std::cout << "* Press I to step forward a single iteration\n";
65
66 window.present();
67}
68
69int main(int argc, const char** argv) {
70 if (ca_init(argc, argv) != 0) {
71 perror("ca_init");
72 return 1;
73 }
74
75 ca_description("Driver program for Ethan's ICP implementation.");
76 ca_author("Ethan Uppal");
77 ca_year(2024);
78 ca_version(0, 0, 0);
79 ca_versioning_info("All rights reserved.");
80
81 ca_synopsis("[-h|-v]");
82 ca_synopsis("-S FILE -D FILE [-l]");
83 ca_synopsis("-b METHOD [-l]");
84
85 bool* enable_log = NULL;
86 bool* read_scan_files = NULL;
87 bool* basic_mode = NULL; // for gbody people
88 const char* f_src = NULL;
89 const char* f_dst = NULL;
90 const char* config_file = "view.conf";
91 const char* method = "vanilla";
92
93 assert_opt(read_scan_files = ca_opt('S', "src", ".FILE&D", &f_src,
94 "source scan (pass with -D)"));
95 assert_opt(ca_opt('D', "dst", ".FILE&S", &f_dst, "destination scan (pass with -S)"));
96 assert_opt(ca_opt('c', "config", ".FILE", &config_file,
97 "selects a configuration file (default: view.conf)"));
98 assert_opt(ca_opt('m', "method", ".METHOD", &method, "selects an ICP method"));
99 assert_opt(basic_mode = ca_long_opt("basic-mode", "", NULL, "uses a ligher gui background"));
100 assert_opt(enable_log = ca_opt('l', "log", "", NULL, "enables debug logging"));
101 assert_opt(ca_opt('h', "help", "<h", NULL, "prints this info"));
102 assert_opt(ca_opt('v', "version", "<v", NULL, "prints version info"));
103
104 if (argc == 1) {
105 ca_print_help();
106 return 1;
107 } else if (ca_parse(NULL) != 0) {
108 return 1;
109 }
110
111 Log.is_enabled = *enable_log;
112 parse_config(config_file);
113 if (*basic_mode) {
115 }
116
117 std::optional<std::unique_ptr<icp::ICP>> icp_opt = icp::ICP::from_method(method);
118
119 if (!icp_opt.has_value()) {
120 std::cerr << "error: unknown ICP method '" << method << "'. expected one of:\n";
121 for (const std::string& registered_method: icp::ICP::registered_methods()) {
122 std::cerr << "* " << registered_method << '\n';
123 }
124 std::exit(1);
125 }
126
127 std::unique_ptr<icp::ICP> icp = std::move(icp_opt.value());
128
129 // std::vector<icp::Vector> a = {icp::Vector(0, 0), icp::Vector(100, 100)};
130 // std::vector<icp::Vector> b = {};
131 // double angle = (double)8 * M_PI / 180.0;
132 // icp::Vector center = icp::get_centroid(a);
133 // icp::Matrix rotation_matrix{
134 // {std::cos(angle), -std::sin(angle)}, {std::sin(angle), std::cos(angle)}};
135 // for (const auto& point: a) {
136 // b.push_back(rotation_matrix * (point - center) + center);
137 // }
138 // LidarView* view = new LidarView(a, b, std::move(icp));
139 // launch_gui(view, "test");
140 // return 0;
141
142 if (*read_scan_files) {
143 LidarScan source = parse_lidar_scan(f_src);
144 LidarScan destination = parse_lidar_scan(f_dst);
145
146 icp::ICP::Config config;
147 config.set("overlap_rate", 0.9);
148 LidarView* view = new LidarView(source.points, destination.points, std::move(icp));
149
150 launch_gui(view, std::string(f_src) + std::string(" and ") + std::string(f_dst));
151 }
152}
Configuration for ICP instances.
Definition icp.h:80
void set(std::string key, T value)
Associates key with an integer, double, or string value.
Definition icp.h:90
static std::optional< std::unique_ptr< ICP > > from_method(std::string name, const Config &params=Config())
Factory constructor for the ICP method name with configuration config.
Definition icp.cpp:76
static const std::vector< std::string > & registered_methods()
Returns a current list of the names of currently registered ICP methods.
Definition icp.cpp:70
int main(int argc, const char **argv)
Definition main.cpp:69
void assert_opt(bool *opt_result)
Definition main.cpp:47
void launch_gui(LidarView *view, std::string visualized="LiDAR scans")
Definition main.cpp:53
void set_config_param(const char *var, const char *data, void *user_data)
Definition main.cpp:20
void parse_config(const char *path)
Definition main.cpp:32
Definition driver.h:7
double y_displace
bool use_light_mode
double x_displace