Skip to content

Commit

Permalink
Using FTXUI to start and stop lidar scanner
Browse files Browse the repository at this point in the history
  • Loading branch information
Chi-EEE committed Jan 8, 2024
1 parent 94c71f6 commit b1b8d63
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 24 deletions.
124 changes: 117 additions & 7 deletions app/raspberry_pi/src/car/display/CarConsole.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#include <ftxui/dom/elements.hpp>
#include <ftxui/component/loop.hpp> // ftxui::Loop

#include <nod/nod.hpp>

#include "../system/CarSystem.h"

using namespace car::system;
Expand Down Expand Up @@ -92,6 +94,7 @@ namespace car::display {
}
debounce = false;
};

auto main_button = Button(&main_button_text, main_button_lambda, animated_button_style);

auto exit = screen.ExitLoopClosure();
Expand All @@ -100,17 +103,124 @@ namespace car::display {
auto modal_component = ExitModalComponent(hide_exit_modal, exit);
main_component |= Modal(modal_component, &exit_modal_shown);

Loop loop(&screen, main_component);
auto renderer_line_block = Renderer([&] {
auto c = Canvas(100, 100);
for (auto& point : this->car_system->get_scan_data()) {
const double angle = point.angle;
const double distance = point.distance;
const double angleInRadians = angle * (3.14159265f / 180.0f);
const int x = distance * std::cos(angleInRadians);
const int y = distance * std::sin(angleInRadians);
c.DrawBlockLine(50, 50, x, y, Color::Blue);
}
return canvas(std::move(c));
}
);


nod::signal<void(bool)> lidar_signal;

bool loading = false;
std::string lidar_status = "Lidar Status: Disconnected";
bool lidar_enabled = false;
auto lidar_checkbox_option = CheckboxOption::Simple();
lidar_checkbox_option.on_change = [&]
{
if (loading) {
lidar_enabled = !lidar_enabled;
return;
}
loading = true;
if (lidar_enabled) {
lidar_status = "Lidar Status: Connecting...";
}
else {
lidar_status = "Lidar Status: Disconnecting...";
}
lidar_signal(lidar_enabled);
};
auto lidar_checkbox = Checkbox(&lidar_status, &lidar_enabled, lidar_checkbox_option);

int image_index = 0;
auto lidar_spinner = Renderer([&] {return spinner(18, image_index); });
auto settings_container = Container::Vertical({
lidar_checkbox,
Maybe(lidar_spinner, &loading),
}
);

int selected_tab = 0;
std::vector<std::string> tab_titles = {
"Main",
"Scan Map",
"Settings",
};

auto tab_selection = Toggle(&tab_titles, &selected_tab);

auto tab_content = Container::Tab(
{
main_component,
renderer_line_block,
settings_container,
}
, &selected_tab
);

auto main_container = Container::Vertical(
{
tab_selection,
tab_content,
}
);

auto main_renderer = Renderer(main_container, [&]
{
return vbox({
text("Car Application") | bold | hcenter,
tab_selection->Render(),
tab_content->Render() | flex,
}
);
}
);

this->car_system->initialize();

// The main loop:
while (!loop.HasQuitted()) {
this->car_system->update();
loop.RunOnce();
}
lidar_signal.connect([&](bool connected)
{
if (connected) {
this->car_system->start_lidar_device();
lidar_status = "Lidar Status: Connected";
loading = false;
}
else {
this->car_system->stop_lidar_device();
lidar_status = "Lidar Status: Disconnected";
loading = false;
}
}
);

std::atomic<bool> refresh_ui_continue = true;
std::thread refresh_ui([&]
{
while (refresh_ui_continue) {
using namespace std::chrono_literals;
std::this_thread::sleep_for(0.05s);
// The |shift| variable belong to the main thread. `screen.Post(task)`
// will execute the update on the thread where |screen| lives (e.g. the
// main thread). Using `screen.Post(task)` is threadsafe.
screen.Post([&] { image_index++; });
// After updating the state, request a new frame to be drawn. This is done
// by simulating a new "custom" event to be handled.
screen.Post(Event::Custom);
}
}
);

screen.Loop(main_renderer);

// Called after the loop ended.
this->car_system->stop();
};

Expand Down
24 changes: 17 additions & 7 deletions app/raspberry_pi/src/car/system/CarSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace car::system
{
CarSystem::CarSystem(
const std::string &websocket_url,
const std::string& websocket_url,
std::unique_ptr<LidarDevice> lidar_device,
std::unique_ptr<MessagingSystem> messaging_system,
std::unique_ptr<MovementSystem> movement_system) : lidar_device(std::move(lidar_device)), messaging_system(std::move(messaging_system)), movement_system(std::move(movement_system))
Expand All @@ -21,10 +21,10 @@ namespace car::system
this->lidar_device->initialize();

this->messaging_system->move_command_signal.connect([this](const MoveCommand move_command)
{ this->move(move_command); });
{ this->move(move_command); });

this->messaging_system->turn_command_signal.connect([this](const TurnCommand turn_command)
{ this->turn(turn_command); });
{ this->turn(turn_command); });
}

void CarSystem::start()
Expand Down Expand Up @@ -54,8 +54,8 @@ namespace car::system
}
json output_json;
output_json["data"] = json::array();
std::vector<Measure> scan = this->lidar_device->scan();
for (const Measure &measure : scan)
this->scan_data = this->lidar_device->scan();
for (const Measure& measure : this->scan_data)
{
output_json["data"].push_back(
{
Expand All @@ -66,13 +66,23 @@ namespace car::system
this->messaging_system->sendMessage(output_json.dump());
}

void CarSystem::move(const MoveCommand &move_command)
void CarSystem::move(const MoveCommand& move_command)
{
this->movement_system->move(move_command);
}

void CarSystem::turn(const TurnCommand &turn_command)
void CarSystem::turn(const TurnCommand& turn_command)
{
this->movement_system->turn(turn_command);
}

void CarSystem::start_lidar_device()
{
this->lidar_device->start();
}

void CarSystem::stop_lidar_device()
{
this->lidar_device->stop();
}
}
7 changes: 7 additions & 0 deletions app/raspberry_pi/src/car/system/CarSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,18 @@ namespace car::system {
void move(const MoveCommand& move_command);
void turn(const TurnCommand& turn_command);

void start_lidar_device();
void stop_lidar_device();

const std::vector<Measure>& get_scan_data() const { return this->scan_data; }

private:
std::unique_ptr<LidarDevice> lidar_device;
std::unique_ptr<MessagingSystem> messaging_system;
std::unique_ptr<MovementSystem> movement_system;

std::vector<Measure> scan_data;

bool running = false;
};
}
Expand Down
4 changes: 1 addition & 3 deletions app/raspberry_pi/src/car/system/lidar/LidarDevice.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ namespace car::system::lidar {
virtual void start() const = 0;
virtual std::vector<Measure> scan() const = 0;
virtual void stop() const = 0;

private:

virtual void disconnect() const = 0;
};
}

Expand Down
1 change: 1 addition & 0 deletions app/raspberry_pi/src/car/system/lidar/LidarDummy.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ namespace car::system::lidar {

void stop() const override {};

void disconnect() const override {};
private:

};
Expand Down
4 changes: 4 additions & 0 deletions app/raspberry_pi/src/car/system/lidar/LidarScanner.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ namespace car::system::lidar
{
this->lidar->stop();
this->lidar->stop_motor();
}

void disconnect() const override
{
this->lidar->disconnect();
}

Expand Down
15 changes: 8 additions & 7 deletions app/raspberry_pi/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,14 @@ int main()
std::string websocket_url = getWebSocketUrl();
spdlog::info("Got websocket url: {}", websocket_url);

std::unique_ptr<LidarDummy> scanner = std::make_unique<LidarDummy>();
// auto maybe_scanner = LidarScanner::create(GET_CONFIG_VALUE(lidar_port));
// if (!maybe_scanner.has_value())
// {
// spdlog::error("Unable to connect to the Lidar Scanner");
// }
// std::unique_ptr<LidarScanner> &scanner = maybe_scanner.value();
//std::unique_ptr<LidarDummy> scanner = std::make_unique<LidarDummy>();

auto maybe_scanner = LidarScanner::create(GET_CONFIG_VALUE(lidar_port));
if (!maybe_scanner.has_value())
{
spdlog::error("Unable to connect to the Lidar Scanner");
}
std::unique_ptr<LidarScanner> &scanner = maybe_scanner.value();

std::unique_ptr<MessagingSystem> messaging_system = std::make_unique<MessagingSystem>(websocket_url);

Expand Down

0 comments on commit b1b8d63

Please sign in to comment.