Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
adas-api/src/demo.cpp
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
302 lines (256 sloc)
10.2 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <algorithm> | |
#include <thread> | |
#include <stdlib.h> | |
#include "ftxui/component/captured_mouse.hpp" // for ftxui | |
#include "ftxui/component/component.hpp" // for Menu, Renderer, Horizontal, Vertical | |
#include "ftxui/component/component_base.hpp" // for ComponentBase | |
#include "ftxui/component/screen_interactive.hpp" // for Component, ScreenInteractive | |
#include "ftxui/dom/elements.hpp" // for text, Element, operator|, window, flex, vbox | |
using namespace ftxui; | |
#include <can_wrap.hpp> | |
using can::operator<<; | |
#include <status_frames.h> | |
ftxui::Component Wrap( const std::string& name, Component component ) | |
{ | |
return Renderer(component, [name, component] { | |
return hbox({ | |
text(name) | size(WIDTH, EQUAL, 10), | |
separator(), | |
component->Render() | xflex, | |
}) | | |
xflex; | |
}); | |
} | |
Component Window(std::string title, Component component) { | |
return Renderer(component, [component, title] { // | |
return window(text(title), component->Render()) | flex; | |
}); | |
} | |
class CanInterface | |
{ | |
public: | |
AxleTorqueFrame frontAxle; | |
AxleTorqueFrame rearAxle { false }; | |
StatusFrame status; | |
SteeringFrame steering; | |
WheelCountsFrame wheelCounts; | |
WheelSpeedsFrame wheelSpeeds; | |
std::array< ProcessFrame* const, 6 > frames { &frontAxle, &rearAxle, &status, &steering, &wheelCounts, &wheelSpeeds }; | |
int canSocket; | |
CanInterface() | |
{ | |
} | |
~CanInterface() | |
{ | |
can::close( canSocket ); | |
} | |
void connect() | |
{ | |
canSocket = can::connect( "vcan0" ); | |
} | |
void process() | |
{ | |
const can_frame frame = can::read( canSocket ); | |
for( auto& f : frames ) | |
{ | |
if( f->frameId == frame.can_id ) | |
{ | |
f->process( frame ); | |
//std::cout << *f << std::endl; | |
} | |
} | |
} | |
}; | |
class Layout | |
{ | |
public: | |
// == options ====== | |
std::vector<std::string> missionStates { "NOT_SELECTED", "SELECTED", "RUNNING", "FINISHED" }; | |
int missionOpt = 0; | |
int frontTorque = 0; | |
int rearTorque = 0; | |
int steering = 0; | |
bool ebrake = false; | |
bool drive = false; | |
std::array<int,4> wheelTicks { 0, 0, 0, 0 }; | |
ftxui::Component carGrid; | |
ftxui::Component controls; | |
ftxui::Component statusInfo; | |
ftxui::Component info; | |
ftxui::Component global; | |
ftxui::Component stateControls; | |
int count = 0; | |
Layout( CanInterface &interface ) | |
{ | |
auto cell = [](const char* t) { return text(t) | border; }; | |
statusInfo = Container::Vertical( | |
{ | |
Window( "Warnings", Renderer( [&] | |
{ | |
return text( interface.status.warning_message() ); | |
} ) ), | |
Window( "Faults", Renderer( [&] | |
{ | |
return text( interface.status.fault_message() ); | |
} ) ), | |
Window( "Status", Renderer( [&] | |
{ | |
auto as_state = [&]( StatusFrame::AsState state ) | |
{ | |
switch( state ) | |
{ | |
case StatusFrame::AsState::AS_OFF: return "OFF"; | |
case StatusFrame::AsState::AS_READY: return "READY"; | |
case StatusFrame::AsState::AS_DRIVING: return "DRIVING"; | |
case StatusFrame::AsState::AS_EMERGENCY: return "EMERGENCY"; | |
case StatusFrame::AsState::AS_FINISHED: return "FINISHED"; | |
} | |
return "ERROR"; | |
}; | |
auto ami_state = [&]( StatusFrame::AmiState state ) | |
{ | |
switch( state ) | |
{ | |
case StatusFrame::AmiState::ACCELERATION: return "ACCELERATION"; | |
case StatusFrame::AmiState::SKIDPAD: return "SKIDPAD"; | |
case StatusFrame::AmiState::AUTOCROSS: return "AUTOCROSS"; | |
case StatusFrame::AmiState::TRACK_DRIVE: return "TRACK_DRIVE"; | |
case StatusFrame::AmiState::STATIC_INSPECTION_A: return "STATIC_INSPECTION_A"; | |
case StatusFrame::AmiState::STATIC_INSPECTION_B: return "STATIC_INSPECTION_B"; | |
case StatusFrame::AmiState::AUTONOMOUS_DEMO: return "AUTONOMOUS_DEMO"; | |
} | |
return "ERROR"; | |
}; | |
return vbox({hbox({text("AS "),text(as_state(interface.status.as_state()))}), | |
hbox({text("AMI "),text(ami_state(interface.status.ami_state()))}), | |
hbox({text("Handshake "),text(interface.status.handshake()?"ON":"OFF")}),}); | |
} ) ), | |
} ); | |
carGrid = Renderer( [&]() | |
{ | |
auto wheel = [&]( int count, int rpm ) | |
{ | |
return vbox( | |
{ | |
hbox({text("count "), text(std::to_string(count))}), | |
hbox({text("rpm "), text(std::to_string(rpm))}), | |
} ) | border; | |
}; | |
auto axle = [&]( float current, float max, float requested ) | |
{ | |
return vbox( | |
{ | |
hbox({text("crrnt "), text(std::to_string(current))}), | |
hbox({text("max "), text(std::to_string(max))}), | |
hbox({text("rqstd "), text(std::to_string(requested))}), | |
} ) | border; | |
}; | |
auto chassis = [&]( bool as, bool ts, bool ebrake ) | |
{ | |
return vbox( | |
{ | |
hbox({text("AS "), text(as?"ON":"OFF")}), | |
hbox({text("TS "), text(ts?"ON":"OFF")}), | |
hbox({text("Ebrake "), text(ebrake?"ON":"OFF")}), | |
} ) | border; | |
}; | |
return gridbox( | |
{ | |
{ | |
wheel( interface.wheelCounts.front_left(), | |
interface.wheelSpeeds.front_left() ), | |
vcenter( hcenter( text("Front") ) ), | |
wheel( interface.wheelCounts.front_right(), | |
interface.wheelSpeeds.front_right() ), | |
}, | |
{ | |
text(""), | |
axle( interface.frontAxle.get_current(), | |
interface.frontAxle.get_max(), | |
interface.frontAxle.get_requested() ), | |
text(""), | |
}, | |
{ | |
text(""), | |
chassis( interface.status.as_switch(), | |
interface.status.ts_switch(), | |
false ), | |
text(""), | |
}, | |
{ | |
text(""), | |
axle( interface.rearAxle.get_current(), | |
interface.rearAxle.get_max(), | |
interface.rearAxle.get_requested() ), | |
text(""), | |
}, | |
{ | |
wheel( interface.wheelCounts.rear_left(), | |
interface.wheelSpeeds.rear_left() ), | |
vcenter( hcenter( text("Rear") ) ), | |
wheel( interface.wheelCounts.rear_right(), | |
interface.wheelSpeeds.rear_right() ), | |
}, | |
} ); | |
} ); | |
controls = Container::Vertical( | |
{ | |
Slider( "Front:", &frontTorque, 0, 100, 1 ), | |
Slider( "Rear :", &rearTorque, 0, 100, 1 ), | |
Slider( "Steering:", &steering, -20, 20, 1 ) | |
} ); | |
stateControls = Window( "Controls", Container::Vertical( | |
{ | |
Window( "Mission status", Menu( &missionStates, &missionOpt ) ), | |
Checkbox( "Ebrake", &this->ebrake ), | |
Checkbox( "Drive", &this->drive ), | |
} ) ); | |
global = Container::Horizontal( | |
{ | |
statusInfo, | |
Container::Vertical( | |
{ | |
carGrid | xflex_grow | yflex_grow, | |
controls | size( WIDTH, GREATER_THAN, 30 ) | xflex, | |
}), | |
stateControls | |
} ); | |
} | |
ftxui::Component& operator()() | |
{ | |
return this->global; | |
} | |
}; | |
int main( int argc, char *argv[] ) | |
{ | |
CanInterface interface; | |
interface.connect(); | |
Layout layout( interface ); | |
auto screen = ScreenInteractive::Fullscreen(); | |
bool canThreadRunning = true; | |
std::thread canThread = std::thread( [&] | |
{ | |
std::this_thread::sleep_for( std::chrono::milliseconds(500) ); | |
while( canThreadRunning ) | |
{ | |
const can_frame frame = can::read( interface.canSocket ); | |
for( auto& f : interface.frames ) | |
{ | |
if( f->frameId == frame.can_id ) | |
{ | |
//std::cout << frame << std::endl; | |
//f->process( frame ); | |
screen.Post( [frame,&f](){ f->process( frame ); } ); | |
} | |
} | |
screen.Post( Event::Custom ); | |
//std::this_thread::sleep_for( std::chrono::milliseconds(5) ); | |
} | |
//std::cout << "Ending" << std::endl; | |
} ); | |
screen.Loop( layout() ); | |
//std::this_thread::sleep_for( std::chrono::seconds(500) ); | |
canThreadRunning = false; | |
canThread.join(); | |
return 0; | |
} |