Skip to content

Commit cf8e853

Browse files
committed
Improve UI and project structure
1 parent 8d761d5 commit cf8e853

File tree

8 files changed

+280
-247
lines changed

8 files changed

+280
-247
lines changed

include/Game.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@
1313

1414
namespace path_finding_visualizer {
1515

16-
static const std::vector<std::string> PLANNER_NAMES{"BFS", "DFS", "DIJKSTRA",
17-
"A*", "RRT", "RRT*"};
18-
enum PLANNERS_IDS { BFS, DFS, DIJKSTRA, AStar, RRT, RRT_STAR };
16+
static const std::vector<std::string> GRAPH_BASED_PLANNERS{"BFS", "DFS",
17+
"DIJKSTRA", "A*"};
18+
static const std::vector<std::string> SAMPLING_BASED_PLANNERS{"RRT", "RRT*"};
19+
enum GRAPH_BASED_PLANNERS_IDS { BFS, DFS, DIJKSTRA, AStar };
20+
enum SAMPLING_BASED_PLANNERS_IDS { RRT, RRT_STAR };
1921

2022
class Game {
2123
public:
@@ -35,7 +37,8 @@ class Game {
3537
void render();
3638
void initGuiTheme();
3739
void renderGui();
38-
void setPlanner(const int id);
40+
void setGraphBasedPlanner(const int id);
41+
void setSamplingBasedPlanner(const int id);
3942

4043
private:
4144
sf::RenderWindow* window_;

include/States/Algorithms/SamplingBased/RRT/RRT.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,9 @@ class RRT : public SamplingBased {
2525
virtual void renderPlannerData() override;
2626
virtual void renderParametersGui() override;
2727

28-
// override algorithm function
29-
virtual void solveConcurrently(
30-
std::shared_ptr<Vertex> start_point, std::shared_ptr<Vertex> goal_point,
31-
std::shared_ptr<MessageQueue<bool>> message_queue) override;
28+
// override main update function
29+
virtual void updatePlanner(bool &solved, Vertex &start,
30+
Vertex &goal) override;
3231

3332
/**
3433
* @brief Randomly sample a vertex

include/States/Algorithms/SamplingBased/RRT_STAR/RRT_STAR.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,8 @@ class RRT_STAR : public RRT {
2424
virtual void initParameters() override;
2525

2626
// override algorithm function
27-
virtual void solveConcurrently(
28-
std::shared_ptr<Vertex> start_point, std::shared_ptr<Vertex> goal_point,
29-
std::shared_ptr<MessageQueue<bool>> message_queue) override;
27+
virtual void updatePlanner(bool& solved, Vertex& start,
28+
Vertex& goal) override;
3029

3130
/**
3231
* @brief Find all the nearest neighbours inside the radius of particular

include/States/Algorithms/SamplingBased/SamplingBased.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,16 @@ class SamplingBased : public State {
7070
// planner related initialization
7171
// this function runs when user presses RUN buttons
7272
virtual void initPlanner() = 0;
73-
7473
virtual void initParameters() = 0;
7574

75+
// pure virtual function need to be implemented by (single-query)
76+
// sampling-based planners
77+
virtual void updatePlanner(bool &solved, Vertex &start, Vertex &goal) = 0;
78+
7679
// main algorithm function (runs in separate thread)
77-
virtual void solveConcurrently(
78-
std::shared_ptr<Vertex> start_point, std::shared_ptr<Vertex> goal_point,
79-
std::shared_ptr<MessageQueue<bool>> message_queue) = 0;
80+
void solveConcurrently(std::shared_ptr<Vertex> start_point,
81+
std::shared_ptr<Vertex> goal_point,
82+
std::shared_ptr<MessageQueue<bool>> message_queue);
8083

8184
protected:
8285
// key timers
@@ -107,6 +110,9 @@ class SamplingBased : public State {
107110
*/
108111
int max_iterations_;
109112

113+
std::mutex iter_no_mutex_;
114+
unsigned int curr_iter_no_{0u};
115+
110116
// MessageQueue Object
111117
std::shared_ptr<MessageQueue<bool>> message_queue_;
112118

src/Game.cpp

Lines changed: 69 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ namespace path_finding_visualizer {
1818

1919
// Constructor
2020
Game::Game(sf::RenderWindow* window) : window_{window} {
21-
curr_planner_ = PLANNER_NAMES[0];
21+
curr_planner_ = GRAPH_BASED_PLANNERS[0];
2222
// manually add BFS for now
2323
states_.push(std::make_unique<bfs_state_type>(window_, states_));
2424

@@ -121,31 +121,40 @@ void Game::initGuiTheme() {
121121

122122
colors[ImGuiCol_SliderGrab] = colors[ImGuiCol_Text];
123123
colors[ImGuiCol_SliderGrabActive] = colors[ImGuiCol_Text];
124+
125+
colors[ImGuiCol_PlotHistogram] = ImVec4(0.3f, 0.305f, 0.31f, 1.0f);
124126
}
125127

126-
void Game::setPlanner(const int id) {
128+
void Game::setGraphBasedPlanner(const int id) {
127129
switch (id) {
128-
case PLANNERS_IDS::BFS:
130+
case GRAPH_BASED_PLANNERS_IDS::BFS:
129131
// BFS
130132
states_.push(std::make_unique<bfs_state_type>(window_, states_));
131133
break;
132-
case PLANNERS_IDS::DFS:
134+
case GRAPH_BASED_PLANNERS_IDS::DFS:
133135
// DFS
134136
states_.push(std::make_unique<dfs_state_type>(window_, states_));
135137
break;
136-
case PLANNERS_IDS::DIJKSTRA:
138+
case GRAPH_BASED_PLANNERS_IDS::DIJKSTRA:
137139
// Dijkstra
138140
states_.push(std::make_unique<dijkstra_state_type>(window_, states_));
139141
break;
140-
case PLANNERS_IDS::AStar:
142+
case GRAPH_BASED_PLANNERS_IDS::AStar:
141143
// A-Star
142144
states_.push(std::make_unique<astar_state_type>(window_, states_));
143145
break;
144-
case PLANNERS_IDS::RRT:
146+
default:
147+
break;
148+
}
149+
}
150+
151+
void Game::setSamplingBasedPlanner(const int id) {
152+
switch (id) {
153+
case SAMPLING_BASED_PLANNERS_IDS::RRT:
145154
// RRT
146155
states_.push(std::make_unique<rrt_state_type>(window_, states_));
147156
break;
148-
case PLANNERS_IDS::RRT_STAR:
157+
case SAMPLING_BASED_PLANNERS_IDS::RRT_STAR:
149158
// RRTStar
150159
states_.push(std::make_unique<rrtstar_state_type>(window_, states_));
151160
break;
@@ -155,25 +164,62 @@ void Game::setPlanner(const int id) {
155164
}
156165

157166
void Game::renderGui() {
158-
if (ImGui::BeginCombo("Select Planner", curr_planner_.c_str())) {
159-
for (int n = 0; n < PLANNER_NAMES.size(); n++) {
160-
bool is_selected = (curr_planner_ == PLANNER_NAMES[n]);
161-
if (ImGui::Selectable(PLANNER_NAMES[n].c_str(), is_selected)) {
162-
if (PLANNER_NAMES[n] != curr_planner_) {
163-
// change the planner
164-
setPlanner(n);
167+
if (ImGui::Button("Choose Planner..")) ImGui::OpenPopup("planners_popup");
168+
ImGui::SameLine();
169+
ImGui::TextUnformatted(curr_planner_.c_str());
170+
if (ImGui::BeginPopup("planners_popup")) {
171+
if (ImGui::BeginMenu("Graph-based Planners")) {
172+
for (int n = 0; n < GRAPH_BASED_PLANNERS.size(); n++) {
173+
bool selected = (GRAPH_BASED_PLANNERS[n] == curr_planner_);
174+
if (ImGui::MenuItem(GRAPH_BASED_PLANNERS[n].c_str(), nullptr, selected,
175+
!selected)) {
176+
if (!selected) {
177+
// change the planner
178+
setGraphBasedPlanner(n);
179+
}
180+
curr_planner_ = GRAPH_BASED_PLANNERS[n];
165181
}
166-
curr_planner_ = PLANNER_NAMES[n];
167182
}
168-
169-
if (is_selected)
170-
ImGui::SetItemDefaultFocus(); // Set the initial focus when opening the
171-
// combo (scrolling + for keyboard
172-
// navigation support in the upcoming
173-
// navigation branch)
183+
ImGui::EndMenu();
184+
}
185+
if (ImGui::BeginMenu("Sampling-based Planners")) {
186+
for (int n = 0; n < SAMPLING_BASED_PLANNERS.size(); n++) {
187+
bool selected = (SAMPLING_BASED_PLANNERS[n] == curr_planner_);
188+
if (ImGui::MenuItem(SAMPLING_BASED_PLANNERS[n].c_str(), nullptr,
189+
selected, !selected)) {
190+
if (!selected) {
191+
// change the planner
192+
setSamplingBasedPlanner(n);
193+
}
194+
curr_planner_ = SAMPLING_BASED_PLANNERS[n];
195+
}
196+
}
197+
ImGui::EndMenu();
174198
}
175-
ImGui::EndCombo();
199+
200+
ImGui::EndPopup();
176201
}
202+
203+
// if (ImGui::BeginCombo("Select Planner", curr_planner_.c_str())) {
204+
// for (int n = 0; n < PLANNER_NAMES.size(); n++) {
205+
// bool is_selected = (curr_planner_ == PLANNER_NAMES[n]);
206+
// if (ImGui::Selectable(PLANNER_NAMES[n].c_str(), is_selected)) {
207+
// if (PLANNER_NAMES[n] != curr_planner_) {
208+
// // change the planner
209+
// setPlanner(n);
210+
// }
211+
// curr_planner_ = PLANNER_NAMES[n];
212+
// }
213+
214+
// if (is_selected)
215+
// ImGui::SetItemDefaultFocus(); // Set the initial focus when opening
216+
// the
217+
// // combo (scrolling + for keyboard
218+
// // navigation support in the upcoming
219+
// // navigation branch)
220+
// }
221+
// ImGui::EndCombo();
222+
// }
177223
ImGui::Spacing();
178224
}
179225

src/States/Algorithms/SamplingBased/RRT/RRT.cpp

Lines changed: 40 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -108,94 +108,51 @@ void RRT::renderParametersGui() {
108108
}
109109
}
110110

111-
// TODO: Since RRT*-like planners share the same iteration concept,
112-
// solveConcurrently() function can be only defined one time
113-
void RRT::solveConcurrently(std::shared_ptr<Vertex> start_point,
114-
std::shared_ptr<Vertex> goal_point,
115-
std::shared_ptr<MessageQueue<bool>> message_queue) {
116-
// copy assignment
117-
// thread-safe due to shared_ptrs
118-
std::shared_ptr<Vertex> start_vertex = start_point;
119-
std::shared_ptr<Vertex> goal_vertex = goal_point;
120-
std::shared_ptr<MessageQueue<bool>> s_message_queue = message_queue;
121-
122-
bool solved = false;
123-
124-
double cycle_duration = 1; // duration of a single simulation cycle in ms
125-
// init stop watch
126-
auto last_update = std::chrono::system_clock::now();
127-
128-
unsigned int iteration_number = 0u;
129-
130-
while (true) {
131-
// compute time difference to stop watch
132-
long time_since_last_update =
133-
std::chrono::duration_cast<std::chrono::milliseconds>(
134-
std::chrono::system_clock::now() - last_update)
135-
.count();
136-
137-
if (time_since_last_update >= cycle_duration) {
138-
////////////////////////////
139-
// run the main algorithm //
140-
////////////////////////////
141-
if (iteration_number < max_iterations_) {
142-
std::shared_ptr<Vertex> x_rand = std::make_shared<Vertex>();
143-
std::shared_ptr<Vertex> x_nearest = std::make_shared<Vertex>();
144-
std::shared_ptr<Vertex> x_new = std::make_shared<Vertex>();
145-
146-
sample(x_rand);
147-
nearest(x_rand, x_nearest);
148-
149-
// find the distance between x_rand and x_nearest
150-
double d = distance(x_rand, x_nearest);
151-
152-
// if this distance d > max_distance_, we need to find nearest state in
153-
// the direction of x_rand
154-
if (d > range_) {
155-
interpolate(x_nearest, x_rand, range_ / d, x_new);
156-
} else {
157-
x_new->x = x_rand->x;
158-
x_new->y = x_rand->y;
159-
}
160-
161-
if (!isCollision(x_nearest, x_new)) {
162-
x_new->parent = x_nearest;
163-
164-
std::unique_lock<std::mutex> lck(mutex_);
165-
vertices_.emplace_back(x_new);
166-
edges_.emplace_back(x_nearest, x_new);
167-
lck.unlock();
168-
169-
if (inGoalRegion(x_new)) {
170-
goal_vertex->parent = std::move(x_new);
171-
solved = true;
172-
}
173-
}
174-
175-
iteration_number++;
176-
} else {
177-
std::cout << "Iterations number reach max limit. Planning stopped."
178-
<< '\n';
179-
solved = true;
180-
}
181-
////////////////////////////
182-
183-
// reset stop watch for next cycle
184-
last_update = std::chrono::system_clock::now();
111+
void RRT::updatePlanner(bool &solved, Vertex &start, Vertex &goal) {
112+
std::unique_lock<std::mutex> iter_no_lck(iter_no_mutex_);
113+
bool running = (curr_iter_no_ < max_iterations_);
114+
iter_no_lck.unlock();
115+
116+
if (running) {
117+
std::shared_ptr<Vertex> x_rand = std::make_shared<Vertex>();
118+
std::shared_ptr<Vertex> x_nearest = std::make_shared<Vertex>();
119+
std::shared_ptr<Vertex> x_new = std::make_shared<Vertex>();
120+
121+
sample(x_rand);
122+
nearest(x_rand, x_nearest);
123+
124+
// find the distance between x_rand and x_nearest
125+
double d = distance(x_rand, x_nearest);
126+
127+
// if this distance d > max_distance_, we need to find nearest state in
128+
// the direction of x_rand
129+
if (d > range_) {
130+
interpolate(x_nearest, x_rand, range_ / d, x_new);
131+
} else {
132+
x_new->x = x_rand->x;
133+
x_new->y = x_rand->y;
185134
}
186135

187-
// sends an update method to the message queue using move semantics
188-
auto ftr = std::async(std::launch::async, &MessageQueue<bool>::send,
189-
s_message_queue, std::move(solved));
190-
ftr.wait();
136+
if (!isCollision(x_nearest, x_new)) {
137+
x_new->parent = x_nearest;
191138

192-
if (solved) return;
139+
std::unique_lock<std::mutex> lck(mutex_);
140+
vertices_.emplace_back(x_new);
141+
edges_.emplace_back(x_nearest, x_new);
142+
lck.unlock();
193143

194-
std::lock_guard<std::mutex> lock(mutex_);
195-
if (is_stopped_) return;
144+
if (inGoalRegion(x_new)) {
145+
goal.parent = std::move(x_new);
146+
solved = true;
147+
}
148+
}
196149

197-
// sleep at every iteration to reduce CPU usage
198-
std::this_thread::sleep_for(std::chrono::milliseconds(1));
150+
iter_no_lck.lock();
151+
curr_iter_no_++;
152+
iter_no_lck.unlock();
153+
} else {
154+
std::cout << "Iterations number reach max limit. Planning stopped." << '\n';
155+
solved = true;
199156
}
200157
}
201158

0 commit comments

Comments
 (0)