#include #include #include #include #include #include #include #include #include "engine.hpp" #include "measure.hpp" #include "rfid_reader.hpp" #include "ultrasound_sensor.hpp" #include "emergency_stop.h" using namespace std; typedef chrono::high_resolution_clock clocktype; const int tickrate = 100; const chrono::milliseconds tick_delay = 1000ms / tickrate; const uint32_t exit_tag = 0xAE0B1E2B; const int no_tags = 3; const uint32_t distance_until_turn = 180; chrono::milliseconds backoff_time = 100ms; chrono::milliseconds turn_right_follow_time = 150ms; chrono::milliseconds turn_right_backoff_time = 500ms; bool stop = false; enum class mmode { STOP, LABYRINTH_FIND_WALL, LABYRINTH_BACKOFF, LABYRINTH_TURN_RIGHT, LABYRINTH_TURN_AWAY, LABYRINTH_FOLLOW, SEARCH_STRAIGHT, SEARCH_TURN_RIGHT, SEARCH_TURN_LEFT, SEARCH_TAG_STOP, HAPPY }; void signal_handler(int sig) { stop = true; } int main() { signal(SIGINT, signal_handler); signal(SIGTERM, signal_handler); engine right( gpio(13, gpio::pin_direction::OUTPUT, gpio::pin_type::LOW_ON), gpio(20, gpio::pin_direction::OUTPUT, gpio::pin_type::LOW_ON) ); engine left( gpio(19, gpio::pin_direction::OUTPUT, gpio::pin_type::LOW_ON), gpio(26, gpio::pin_direction::OUTPUT, gpio::pin_type::LOW_ON) ); gpio bwleftleft(18, gpio::pin_direction::INPUT, gpio::pin_type::HIGH_ON); gpio bwleftright(4, gpio::pin_direction::INPUT, gpio::pin_type::HIGH_ON); gpio bwrightleft(3, gpio::pin_direction::INPUT, gpio::pin_type::HIGH_ON); gpio bwrightright(2, gpio::pin_direction::INPUT, gpio::pin_type::HIGH_ON); emergency_stop stop_button(25); ultrasound_sensor ultrasoundright(23, 24); ultrasound_sensor ultrasoundleft(12, 6); rfid_reader rfid; // TODO This random is unseeded minstd_rand random; clocktype::time_point mmode_end = clocktype::now(); mmode mode = mmode::STOP; mmode target_mode = mmode::LABYRINTH_FIND_WALL; clocktype::time_point mode_reset_time; int last_tag = 0x00000000; vector found_tags; found_tags.reserve(no_tags); measure measurement("main"); clocktype::time_point next_tick = clocktype::now(); while (!stop) { measurement.start(); clocktype::time_point tick_start = clocktype::now(); switch (mode) { case mmode::LABYRINTH_FOLLOW: case mmode::LABYRINTH_BACKOFF: case mmode::LABYRINTH_TURN_RIGHT: case mmode::LABYRINTH_TURN_AWAY: case mmode::LABYRINTH_FIND_WALL: { if (tick_start >= mode_reset_time) { switch (mode) { case mmode::LABYRINTH_BACKOFF: target_mode = mmode::LABYRINTH_TURN_AWAY; mode_reset_time = tick_start + turn_right_backoff_time; break; case mmode::LABYRINTH_TURN_AWAY: target_mode = mmode::LABYRINTH_FIND_WALL; break; case mmode::LABYRINTH_TURN_RIGHT: target_mode = mmode::LABYRINTH_FOLLOW; break; } } if (bwrightleft.get_value() || bwrightright.get_value()) { target_mode = mmode::LABYRINTH_BACKOFF; mode_reset_time = tick_start + backoff_time; } else if (bwleftleft.get_value() || bwleftright.get_value()) { if (mode != mmode::LABYRINTH_BACKOFF) { target_mode = mmode::LABYRINTH_TURN_RIGHT; mode_reset_time = tick_start + turn_right_follow_time; } } int last_id = rfid.last_id(); if (last_id == exit_tag) { target_mode = mmode::SEARCH_STRAIGHT; last_tag = last_id; } } break; case mmode::SEARCH_STRAIGHT: { auto usoundright = ultrasoundright.get_value(); auto usoundleft = ultrasoundleft.get_value(); if (min(usoundright, usoundleft) < distance_until_turn) { if (std::abs((long long int) usoundright - usoundleft) < 50) { int angle = random() % 180 + 90; if (angle <= 180) { target_mode = mmode::SEARCH_TURN_RIGHT; } else { target_mode = mmode::SEARCH_TURN_LEFT; angle = 360 - angle; } mode_reset_time = tick_start + 3ms * angle; } else { int angle = random() % 90 + 90; mode_reset_time = tick_start + 3ms * angle; if (usoundright < usoundleft) target_mode = mmode::SEARCH_TURN_LEFT; else target_mode = mmode::SEARCH_TURN_RIGHT; } } int last_id = rfid.last_id(); if (last_id != last_tag && last_id != exit_tag) { last_tag = last_id; if (find(found_tags.begin(), found_tags.end(), last_tag) == found_tags.end()) { found_tags.push_back(last_tag); target_mode = mmode::SEARCH_TAG_STOP; mode_reset_time = tick_start + 200ms; if (found_tags.size() == no_tags) { target_mode = mmode::HAPPY; mode_reset_time = tick_start + 2s; } } } } break; case mmode::SEARCH_TURN_LEFT: case mmode::SEARCH_TURN_RIGHT: case mmode::SEARCH_TAG_STOP: if (tick_start >= mode_reset_time) { target_mode = mmode::SEARCH_STRAIGHT; } break; case mmode::HAPPY: if (tick_start >= mode_reset_time) { target_mode = mmode::STOP; stop = true; } break; } if (stop_button.get_state()) { target_mode = mmode::STOP; stop = true; } if (target_mode != mode) { mode = target_mode; switch (mode) { case mmode::STOP: left.set_speed(0); right.set_speed(0); break; case mmode::LABYRINTH_FIND_WALL: left.set_speed(60); right.set_speed(60); break; case mmode::LABYRINTH_BACKOFF: left.set_speed(-100); right.set_speed(-100); break; case mmode::LABYRINTH_TURN_AWAY: case mmode::LABYRINTH_TURN_RIGHT: left.set_speed(100); right.set_speed(-60); break; case mmode::LABYRINTH_FOLLOW: left.set_speed(0); right.set_speed(100); break; case mmode::SEARCH_STRAIGHT: left.set_speed(100); right.set_speed(100); break; case mmode::HAPPY: case mmode::SEARCH_TURN_LEFT: left.set_speed(-100); right.set_speed(100); break; case mmode::SEARCH_TURN_RIGHT: left.set_speed(100); right.set_speed(-100); break; case mmode::SEARCH_TAG_STOP: left.set_speed(-100); right.set_speed(-100); break; } } measurement.stop(); if (!stop) { next_tick += tick_delay; this_thread::sleep_until(next_tick); } } return 0; }