all
This commit is contained in:
commit
f9cd6248ec
56
CMakeLists.txt
Normal file
56
CMakeLists.txt
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.30)
|
||||||
|
project(c C)
|
||||||
|
|
||||||
|
set(CMAKE_C_STANDARD 17)
|
||||||
|
set(INCLUDE_DIRECTORIES ./)
|
||||||
|
include_directories()
|
||||||
|
|
||||||
|
add_executable(stack_test stack/stack.c stack/stack.h stack/stack_test.c
|
||||||
|
cell/cell.c
|
||||||
|
cell/cell.h)
|
||||||
|
|
||||||
|
add_executable(maze-nolib
|
||||||
|
leelib/leelib.c
|
||||||
|
leelib/leelib.h
|
||||||
|
stack/stack.c
|
||||||
|
stack/stack.h
|
||||||
|
lee-algorithm/lee-algorithm.c
|
||||||
|
lee-algorithm/lee-algorithm.h
|
||||||
|
cell/cell.c
|
||||||
|
cell/cell.h
|
||||||
|
robot/robot.c
|
||||||
|
robot/robot.h
|
||||||
|
robot/simple-simulator.c
|
||||||
|
main.c
|
||||||
|
robot/simulator-moves.c
|
||||||
|
robot/challenges/challenge2.c
|
||||||
|
robot/challenges/challenge3.c
|
||||||
|
robot/challenges/challenges.h
|
||||||
|
robot/challenges/challenge4.c)
|
||||||
|
|
||||||
|
add_executable(maze-libsp
|
||||||
|
leelib/leelib.c
|
||||||
|
leelib/leelib.h
|
||||||
|
stack/stack.c
|
||||||
|
stack/stack.h
|
||||||
|
lee-algorithm/lee-algorithm.c
|
||||||
|
lee-algorithm/lee-algorithm.h
|
||||||
|
cell/cell.c
|
||||||
|
cell/cell.h
|
||||||
|
robot/robot.c
|
||||||
|
robot/robot.h
|
||||||
|
communication/communication.c
|
||||||
|
communication/communication.h
|
||||||
|
communication/utils.c
|
||||||
|
communication/utils.h
|
||||||
|
main.c
|
||||||
|
robot/controller-moves.c
|
||||||
|
robot/remote.c
|
||||||
|
robot/challenges/challenges.h
|
||||||
|
robot/challenges/challenge2.c
|
||||||
|
robot/challenges/challenge3.c
|
||||||
|
robot/challenges/challenge4.c)
|
||||||
|
|
||||||
|
target_link_libraries(maze-libsp serialport m)
|
||||||
|
target_link_libraries(maze-nolib m)
|
||||||
|
target_link_libraries(stack_test m)
|
||||||
3
Testing/Temporary/LastTest.log
Normal file
3
Testing/Temporary/LastTest.log
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
Start testing: Jun 05 17:03 CEST
|
||||||
|
----------------------------------------------------------
|
||||||
|
End testing: Jun 05 17:03 CEST
|
||||||
15
cell/cell.c
Normal file
15
cell/cell.c
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
//
|
||||||
|
// Created by nano on 5/1/25.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "cell.h"
|
||||||
|
|
||||||
|
int cell_equals(cell a, cell b) {
|
||||||
|
return (a.x == b.x && a.y == b.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cell_add(cell *c, cell a, cell b) {
|
||||||
|
c->x = a.x + b.x;
|
||||||
|
c->y = a.y + b.y;
|
||||||
|
}
|
||||||
|
|
||||||
19
cell/cell.h
Normal file
19
cell/cell.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
//
|
||||||
|
// Created by nano on 5/1/25.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef CELL_H
|
||||||
|
#define CELL_H
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct cell {
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
} cell;
|
||||||
|
|
||||||
|
int cell_equals(cell a,cell b);
|
||||||
|
void cell_add(cell *c, cell a, cell b);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif //CELL_H
|
||||||
210
communication/communication.c
Normal file
210
communication/communication.c
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
//
|
||||||
|
// Created by nano on 4/26/25.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "communication.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct sp_port *port;
|
||||||
|
struct sp_event_set *event_data_ready;
|
||||||
|
struct sp_event_set *event_ready_for_tx;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the serial communication for the usb -> uart board
|
||||||
|
*/
|
||||||
|
void comm_init_communication() {
|
||||||
|
struct sp_port **port_list;
|
||||||
|
comm_get_port_list(&port_list);
|
||||||
|
int portnr = 0;
|
||||||
|
comm_list_serial_ports(port_list);
|
||||||
|
printf("Chose a port: ");
|
||||||
|
scanf("%d", &portnr);
|
||||||
|
sp_copy_port(port_list[portnr], &port);
|
||||||
|
sp_free_port_list(port_list);
|
||||||
|
comm_open_port();
|
||||||
|
}
|
||||||
|
|
||||||
|
void comm_get_port_list(struct sp_port ***port_list) {
|
||||||
|
enum sp_return result = sp_list_ports(port_list);
|
||||||
|
if (result != SP_OK) {
|
||||||
|
printf("Error listing serial ports\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void comm_list_serial_ports(struct sp_port **port_list) {
|
||||||
|
printf("Port list:\n");
|
||||||
|
for (int i = 0; port_list[i] != NULL; i++) {
|
||||||
|
char *port_name = sp_get_port_name(port_list[i]);
|
||||||
|
printf("Port %d: %s\n", i, port_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Opens communication to the selected serial port and sets the correct parameters for the zigbee carrier board.
|
||||||
|
* Also add event to see when data arrives.
|
||||||
|
*/
|
||||||
|
void comm_open_port() {
|
||||||
|
|
||||||
|
check(sp_open(port, SP_MODE_READ_WRITE));
|
||||||
|
check(sp_set_baudrate(port, 9600));
|
||||||
|
check(sp_set_bits(port, 8));
|
||||||
|
check(sp_set_parity(port, SP_PARITY_NONE));
|
||||||
|
check(sp_set_stopbits(port, 1));
|
||||||
|
|
||||||
|
check(sp_new_event_set(&event_data_ready));
|
||||||
|
check(sp_new_event_set(&event_ready_for_tx));
|
||||||
|
|
||||||
|
sp_add_port_events(event_data_ready, port, SP_EVENT_RX_READY);
|
||||||
|
sp_add_port_events(event_ready_for_tx, port, SP_EVENT_TX_READY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ends the serial communication for the usb -> uart board
|
||||||
|
*/
|
||||||
|
void comm_end_communication() {
|
||||||
|
check(sp_close(port));
|
||||||
|
sp_free_port(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait till there is data available.
|
||||||
|
* @param timeout how much time in ms to wait for the data
|
||||||
|
* @returns SP_OK if data is ready.
|
||||||
|
* @returns SP_ERR_FAIL if data was not available before timeout ended.
|
||||||
|
*/
|
||||||
|
int comm_await_data_ready(int timeout) {
|
||||||
|
// Await data from the robot
|
||||||
|
return sp_wait(event_data_ready, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait till you can transmit again .
|
||||||
|
* @param timeout how much time in ms to wait for the data
|
||||||
|
* @returns SP_OK if data is ready.
|
||||||
|
* @returns SP_ERR_FAIL if uart module wasnt ready for transmit before timeout ended.
|
||||||
|
*/
|
||||||
|
int comm_await_ready_for_tx(int timeout) {
|
||||||
|
return sp_wait(event_ready_for_tx, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a number of bytes from the buffer, store them in data without blocking the process.
|
||||||
|
* @param data array where to store the data
|
||||||
|
* @param amount_of_bytes
|
||||||
|
* @return ALL_BYTES if the number of expected bytes was read
|
||||||
|
* @return NOT_ENOUGH_BYTES if read less than expected
|
||||||
|
* @return ERROR if read fails
|
||||||
|
*/
|
||||||
|
comm_result comm_nonblocking_read(byte *data, int amount_of_bytes) {
|
||||||
|
//read available data
|
||||||
|
int recv_bytes = sp_nonblocking_read(port, data, amount_of_bytes);
|
||||||
|
if (recv_bytes == amount_of_bytes) {
|
||||||
|
return ALL_BYTES;
|
||||||
|
}
|
||||||
|
if (recv_bytes >= 0) {
|
||||||
|
return NOT_ENOUGH_BYTES;
|
||||||
|
}
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a number of bytes from the buffer, store them in data, with a number of ms to wait in case that amount of data is not available..
|
||||||
|
* @param data array where to store the data
|
||||||
|
* @param amount_of_bytes
|
||||||
|
* @param timeout how much time in ms to wait for all data to be available.
|
||||||
|
* @return ALL_BYTES if the number of expected bytes was read
|
||||||
|
* @return NOT_ENOUGH_BYTES if read less than expected
|
||||||
|
* @return ERROR if read fails
|
||||||
|
*/
|
||||||
|
comm_result comm_blocking_read(byte *data, int amount_of_bytes, int timeout) {
|
||||||
|
//read available data
|
||||||
|
int recv_bytes = sp_blocking_read(port, data, amount_of_bytes, timeout);
|
||||||
|
printf("RECV: %d\n",*data);
|
||||||
|
if (recv_bytes == amount_of_bytes) {
|
||||||
|
return ALL_BYTES;
|
||||||
|
}
|
||||||
|
if (recv_bytes >= 0) {
|
||||||
|
return NOT_ENOUGH_BYTES;
|
||||||
|
}
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a number of bytes to the buffer, from data, with a number of ms to wait in case that amount of data is not available..
|
||||||
|
* @param data array where to store the data
|
||||||
|
* @param amount_of_bytes
|
||||||
|
* @param timeout how much time in ms to wait for all data to be available.
|
||||||
|
* @return ALL_BYTES if the number of expected bytes was read
|
||||||
|
* @return NOT_ENOUGH_BYTES if read less than expected
|
||||||
|
* @return ERROR if read fails
|
||||||
|
*/
|
||||||
|
comm_result comm_blocking_write(byte *data, int amount_of_bytes, int timeout) {
|
||||||
|
// we are writing 8 bit bytes to the fpga anyways and pc -> fpga only needs to tell what do to next, can be fit in 8 bits
|
||||||
|
int sent_bytes = sp_blocking_write(port, data, amount_of_bytes, timeout);
|
||||||
|
printf("SEND: %d \n",*data);
|
||||||
|
|
||||||
|
if (sent_bytes == amount_of_bytes) {
|
||||||
|
return ALL_BYTES;
|
||||||
|
}
|
||||||
|
if (sent_bytes >= 0) {
|
||||||
|
return NOT_ENOUGH_BYTES;
|
||||||
|
}
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a number of bytes to the buffer, from data.
|
||||||
|
* @param data array where to store the data
|
||||||
|
* @param amount_of_bytes
|
||||||
|
* @return ALL_BYTES if the number of expected bytes was read
|
||||||
|
* @return NOT_ENOUGH_BYTES if read less than expected
|
||||||
|
* @return ERROR if read fails
|
||||||
|
*/
|
||||||
|
comm_result comm_nonblocking_write(byte *data, int amount_of_bytes) {
|
||||||
|
// we are writing 8 bit bytes to the fpga anyways and pc -> fpga only needs to tell what do to next, can be fit in 8 bits
|
||||||
|
int sent_bytes = sp_nonblocking_write(port, data, amount_of_bytes);
|
||||||
|
if (sent_bytes == amount_of_bytes) {
|
||||||
|
return ALL_BYTES;
|
||||||
|
}
|
||||||
|
if (sent_bytes >= 0) {
|
||||||
|
return NOT_ENOUGH_BYTES;
|
||||||
|
}
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check if bytes are left to be sent
|
||||||
|
int comm_output_waiting() {
|
||||||
|
return sp_output_waiting(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Helper function for error handling. Taken from libserialport examples */
|
||||||
|
int check(enum sp_return result) {
|
||||||
|
/* For this example we'll just exit on any error by calling abort(). */
|
||||||
|
char *error_message;
|
||||||
|
switch (result) {
|
||||||
|
case SP_ERR_ARG:
|
||||||
|
printf("Error: Invalid argument.\n");
|
||||||
|
abort();
|
||||||
|
case SP_ERR_FAIL:
|
||||||
|
error_message = sp_last_error_message();
|
||||||
|
printf("Error: Failed: %s\n", error_message);
|
||||||
|
sp_free_error_message(error_message);
|
||||||
|
abort();
|
||||||
|
case SP_ERR_SUPP:
|
||||||
|
printf("Error: Not supported.\n");
|
||||||
|
abort();
|
||||||
|
case SP_ERR_MEM:
|
||||||
|
printf("Error: Couldn't allocate memory.\n");
|
||||||
|
abort();
|
||||||
|
case SP_OK:
|
||||||
|
default:
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
89
communication/communication.h
Normal file
89
communication/communication.h
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
//
|
||||||
|
// Created by nano on 4/26/25.
|
||||||
|
//
|
||||||
|
#ifndef COMMS_H
|
||||||
|
#define COMMS_H
|
||||||
|
#include <libserialport.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
typedef u_int8_t byte;
|
||||||
|
|
||||||
|
typedef enum { ALL_BYTES, NOT_ENOUGH_BYTES, ERROR } comm_result;
|
||||||
|
int comm_output_waiting() ;
|
||||||
|
/**
|
||||||
|
* Initializes the serial communication for the usb -> uart board
|
||||||
|
*/
|
||||||
|
void comm_init_communication();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates port list from present serial ports.
|
||||||
|
* @param port_list pointer to port list to set.
|
||||||
|
*/
|
||||||
|
void comm_get_port_list(struct sp_port ***port_list);
|
||||||
|
|
||||||
|
void comm_list_serial_ports(struct sp_port **port_list);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens communication to the selected serial port and sets the correct parameters for the zigbee carrier board.
|
||||||
|
*/
|
||||||
|
void comm_open_port();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ends the serial communication for the usb -> uart board
|
||||||
|
*/
|
||||||
|
void comm_end_communication();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Await fresh data from the serial port
|
||||||
|
* @param timeout timeout for waiting for a byte to be ready to read
|
||||||
|
* @return if there is data available (1 or 0)
|
||||||
|
*/
|
||||||
|
int comm_await_data_ready(int timeout);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the serial port is ready to be written to.
|
||||||
|
* @param timeout timeout for waiting for a byte to be ready to read
|
||||||
|
* @return if data can be written (1 or 0)
|
||||||
|
*/
|
||||||
|
int comm_await_ready_for_tx(int timeout);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*Do a nonblocking read from the serial port
|
||||||
|
*@param data pointer to data to read
|
||||||
|
*@param amount_of_bytes amount of bytes to read from uart buffer
|
||||||
|
*@return if whole buffer was filled, part of the buffer was filled or error
|
||||||
|
*/
|
||||||
|
comm_result comm_nonblocking_read(byte *data, int amount_of_bytes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*Do a blocking read from the serial port
|
||||||
|
*@param data pointer to data to read
|
||||||
|
*@param amount_of_bytes amount of bytes to read from uart buffer
|
||||||
|
*@param timeout how long to wait for data to be filled
|
||||||
|
*@return if whole buffer was filled, part of the buffer was filled or error
|
||||||
|
*/
|
||||||
|
comm_result comm_blocking_read(byte *data, int amount_of_bytes, int timeout);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*Do a nonblocking write from the serial port
|
||||||
|
*@param data pointer to data to write
|
||||||
|
*@param amount_of_bytes amount of bytes to write to uart
|
||||||
|
*@return if whole buffer was written, part of the buffer was written or error
|
||||||
|
*/
|
||||||
|
comm_result comm_nonblocking_write(byte *data, int amount_of_bytes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*Do a nonblocking write from the serial port
|
||||||
|
*@param data pointer to data to write
|
||||||
|
*@param amount_of_bytes amount of bytes to write to uart
|
||||||
|
*@param timeout how long to wait for data to be filled
|
||||||
|
*@return if whole buffer was written, part of the buffer was written or error
|
||||||
|
*/
|
||||||
|
comm_result comm_blocking_write(byte *data, int amount_of_bytes, int timeout);
|
||||||
|
|
||||||
|
/** Helper function for error handling.
|
||||||
|
* Taken from libserialport examples. */
|
||||||
|
int check(enum sp_return result);
|
||||||
|
|
||||||
|
|
||||||
|
#endif //COMMS_H
|
||||||
122
communication/utils.c
Normal file
122
communication/utils.c
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
//
|
||||||
|
// Created by nano on 4/26/25.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "communication.h"
|
||||||
|
|
||||||
|
#define ACK 16
|
||||||
|
#define NOTHING_RECV 0
|
||||||
|
|
||||||
|
/**Helper functions to convert from bits to bytes*/
|
||||||
|
void byte_to_bit_array(byte bit_array[], byte data) {
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
bit_array[i] = (data >> i) & 1; //shift through all bits and check if they're 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**2's complement notation*/
|
||||||
|
void bit_array_to_byte(const byte bit_array[], byte *data) {
|
||||||
|
*data = 0;
|
||||||
|
byte currentpow = 1;
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
*data += bit_array[i] * currentpow;
|
||||||
|
currentpow *= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void comm_write_until_successful(byte d, int timeout) {
|
||||||
|
//while (comm_await_comm_awaready_for_tx(50)!=SP_OK) {} //wait indefinitely till you can send data
|
||||||
|
REWRITE:
|
||||||
|
comm_blocking_write(&d,1,timeout);
|
||||||
|
|
||||||
|
byte data;
|
||||||
|
int counter =0;
|
||||||
|
REREAD:
|
||||||
|
while (comm_blocking_read(&data,1,timeout) != ALL_BYTES) {counter ++; if (counter == 10) goto REWRITE;} //idk if this does anything but the code works so im not touching it
|
||||||
|
|
||||||
|
//data ? printf("RECV: %d \n",data) : 0;
|
||||||
|
counter++;
|
||||||
|
printf("Times Read %d",counter);
|
||||||
|
if (data == ACK) {
|
||||||
|
printf("ACK\n");
|
||||||
|
}
|
||||||
|
else if (counter !=10)
|
||||||
|
goto REREAD;
|
||||||
|
else
|
||||||
|
goto REWRITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CROSSING 0x20
|
||||||
|
|
||||||
|
/**
|
||||||
|
* await data from the robot
|
||||||
|
* @param data data gotten from robot
|
||||||
|
* @return 1 if correct, -1 if retry required
|
||||||
|
*/
|
||||||
|
int comm_await_crossing(int timeout){
|
||||||
|
byte data;
|
||||||
|
int run =1;
|
||||||
|
printf("AWAITING CROSSING\n");
|
||||||
|
while (run){
|
||||||
|
comm_blocking_read(&data, 1,timeout);
|
||||||
|
printf("Read while expecting crossing: %d\n",data);
|
||||||
|
if (data==CROSSING) {
|
||||||
|
//printf("CROSSING\n");
|
||||||
|
run=0;
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SENSOR_NOTHING_AHEAD 5
|
||||||
|
#define SENSOR_1_CROSSING_AHEAD 1
|
||||||
|
#define SENSOR_2_CROSSING_AHEAD 2
|
||||||
|
#define SENSOR_3_CROSSING_AHEAD 3
|
||||||
|
#define SENSOR_4_CROSSING_AHEAD 4
|
||||||
|
|
||||||
|
int comm_get_distance_sensor(int *len, int timeout) {
|
||||||
|
byte *data = malloc(sizeof(byte));
|
||||||
|
while (comm_blocking_read(data,1,timeout) == ALL_BYTES) {
|
||||||
|
printf("Got while expecting distance sensor: %d \n", *data);
|
||||||
|
switch (*data) {
|
||||||
|
case SENSOR_NOTHING_AHEAD:
|
||||||
|
*len=0;
|
||||||
|
free(data);
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
case SENSOR_1_CROSSING_AHEAD:
|
||||||
|
*len=1;
|
||||||
|
free(data);
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
case SENSOR_2_CROSSING_AHEAD:
|
||||||
|
*len=3;
|
||||||
|
free(data);
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
case SENSOR_3_CROSSING_AHEAD:
|
||||||
|
*len=5;
|
||||||
|
free(data);
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
case SENSOR_4_CROSSING_AHEAD:
|
||||||
|
*len=7;
|
||||||
|
free(data);
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("wat\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
20
communication/utils.h
Normal file
20
communication/utils.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
//
|
||||||
|
// Created by nano on 4/26/25.
|
||||||
|
//
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef COMM_UTILS_H
|
||||||
|
#define COMM_UTILS_H
|
||||||
|
typedef u_int8_t byte;
|
||||||
|
|
||||||
|
void byte_to_bit_array(byte *bit_array, byte data);
|
||||||
|
|
||||||
|
void bit_array_to_byte(const byte bit_array[], byte *data);
|
||||||
|
|
||||||
|
void comm_write_until_successful(byte d, int timeout);
|
||||||
|
|
||||||
|
int comm_await_crossing(int timeout);
|
||||||
|
|
||||||
|
int comm_get_distance_sensor(int *len, int timeout) ;
|
||||||
|
#endif //COMM_UTILS_H
|
||||||
148
lee-algorithm/lee-algorithm.c
Normal file
148
lee-algorithm/lee-algorithm.c
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "lee-algorithm.h"
|
||||||
|
|
||||||
|
#include "../stack/stack.h"
|
||||||
|
#include "../cell/cell.h"
|
||||||
|
#include "../communication/utils.h"
|
||||||
|
#include "../robot/robot.h"
|
||||||
|
|
||||||
|
|
||||||
|
// Maze en standaard Lee-functies
|
||||||
|
|
||||||
|
int unexpanded_matrix[MAZE_SIZE][MAZE_SIZE] = {
|
||||||
|
{ -1, -1, -1, 0, -1, 0, -1, 0, -1, -1, -1},
|
||||||
|
{ -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},
|
||||||
|
{ -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1},
|
||||||
|
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||||
|
{ -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1},
|
||||||
|
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||||
|
{ -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1},
|
||||||
|
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||||
|
{ -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1},
|
||||||
|
{ -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},
|
||||||
|
{ -1, -1, -1, 0, -1, 0, -1, 0, -1, -1, -1,}
|
||||||
|
};
|
||||||
|
|
||||||
|
const cell neighbours[4] = {{-1, 0}, {0, 1}, {1,}, {0, -1}}; // NORTH EAST SOUTH WEST
|
||||||
|
const cell crossing_neighbours[4] = {{-2, 0}, {0, 2}, {2,0}, {0, -2}};
|
||||||
|
|
||||||
|
void lee_run(robot r, cell targetCell, stack *moves) {
|
||||||
|
int assignmentMatrix[MAZE_SIZE][MAZE_SIZE];
|
||||||
|
memcpy(assignmentMatrix, unexpanded_matrix, sizeof(assignmentMatrix));
|
||||||
|
lee_expand(assignmentMatrix, r.pos, targetCell);
|
||||||
|
lee_trace(assignmentMatrix, r, targetCell, moves);
|
||||||
|
stack_invert(moves);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lee_expand(int assignmentMatrix[MAZE_SIZE][MAZE_SIZE], cell startCell, cell targetCell) {
|
||||||
|
int v = 1;
|
||||||
|
assignmentMatrix[targetCell.x][targetCell.y] = v;
|
||||||
|
while (assignmentMatrix[startCell.x][startCell.y] == 0) {
|
||||||
|
for (int i = 0; i < MAZE_SIZE; i++) {
|
||||||
|
for (int j = 0; j < MAZE_SIZE; j++) {
|
||||||
|
if (assignmentMatrix[i][j] == v) {
|
||||||
|
for (int k = 0; k < 4; k++) {
|
||||||
|
cell neighbour;
|
||||||
|
cell_add(&neighbour, (cell){i, j}, neighbours[k]);
|
||||||
|
if (isInBound(neighbour) && assignmentMatrix[neighbour.x][neighbour.y] == 0) {
|
||||||
|
assignmentMatrix[neighbour.x][neighbour.y] = v + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void lee_trace(int assignmentMatrix[MAZE_SIZE][MAZE_SIZE], robot r, cell targetCell, stack *stack) {
|
||||||
|
robot tempBot = r;
|
||||||
|
printf("\n");
|
||||||
|
while (!cell_equals(tempBot.pos, targetCell)) {
|
||||||
|
// check forward first,as its most efficient move
|
||||||
|
cell neighbourCell;
|
||||||
|
cell_add(&neighbourCell, tempBot.pos, neighbours[tempBot.dir]);
|
||||||
|
if (isInBound(neighbourCell) &&
|
||||||
|
assignmentMatrix[neighbourCell.x][neighbourCell.y] > 0 &&
|
||||||
|
assignmentMatrix[neighbourCell.x][neighbourCell.y] < assignmentMatrix[tempBot.pos.x][tempBot.pos.y]) {
|
||||||
|
tempBot.pos = neighbourCell;
|
||||||
|
//if (isValidCrossing(tempBot.pos) ) {
|
||||||
|
stack_push(stack, neighbours[tempBot.dir]);
|
||||||
|
//}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// check rest of directions
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
cell_add(&neighbourCell, tempBot.pos, neighbours[(tempBot.dir + i) % 4]);
|
||||||
|
//ugly calculation as to check all 3 other directions other than the main one
|
||||||
|
if (isInBound(neighbourCell) &&
|
||||||
|
assignmentMatrix[neighbourCell.x][neighbourCell.y] > 0 &&
|
||||||
|
assignmentMatrix[neighbourCell.x][neighbourCell.y] < assignmentMatrix[tempBot.pos.x][tempBot.pos.y]) {
|
||||||
|
tempBot.pos = neighbourCell;
|
||||||
|
spin(&r, tempBot.dir);
|
||||||
|
//if (isValidCrossing(tempBot.pos)) {
|
||||||
|
stack_push(stack, neighbours[(tempBot.dir + i) % 4]);
|
||||||
|
//}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int validatePath(robot r, stack s) {
|
||||||
|
robot temp = r;
|
||||||
|
for (int i = 0; i < s.length; i++) {
|
||||||
|
cell_add(&temp.pos, temp.pos,s.data[i]);
|
||||||
|
if (unexpanded_matrix[temp.pos.x][temp.pos.y] < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int firstMove;
|
||||||
|
void followPath(robot *r, stack *path,int visited[MAZE_SIZE][MAZE_SIZE]) {
|
||||||
|
while (path->length > 0) {
|
||||||
|
cell currentCell = stack_pop(path);
|
||||||
|
int result = move(r,currentCell);
|
||||||
|
comm_await_crossing(2000);
|
||||||
|
comm_discard_sensor_data(1000);
|
||||||
|
visited[r->pos.x][r->pos.y] = 5;
|
||||||
|
if (result == 0) {
|
||||||
|
move(r,currentCell);
|
||||||
|
comm_await_crossing(2000);
|
||||||
|
comm_discard_sensor_data(1000);
|
||||||
|
visited[r->pos.x][r->pos.y] = 5;
|
||||||
|
}
|
||||||
|
printMatrix_with_current_pos(visited,*r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int isInBound(const cell c) {
|
||||||
|
if (c.x >= 0 && c.x < MAZE_SIZE &&
|
||||||
|
c.y >= 0 && c.y < MAZE_SIZE) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int isStation(const cell c) {
|
||||||
|
if (c.x == 0 || c.x == MAZE_SIZE - 1 ||
|
||||||
|
c.y == 0 || c.y == MAZE_SIZE - 1){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
int isValidCrossing(const cell c) {
|
||||||
|
if (c.x > 0 && c.x < MAZE_SIZE - 1 &&
|
||||||
|
c.y > 0 && c.y < MAZE_SIZE - 1 &&
|
||||||
|
c.x % 2 == 1 && c.y % 2 == 1 &&
|
||||||
|
unexpanded_matrix[c.x][c.y]==0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
25
lee-algorithm/lee-algorithm.h
Normal file
25
lee-algorithm/lee-algorithm.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
//
|
||||||
|
// Created by nano on 4/30/25.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef LEE_ALGORITHM_H
|
||||||
|
#define LEE_ALGORITHM_H
|
||||||
|
|
||||||
|
#include "../stack/stack.h"
|
||||||
|
#include "../robot/robot.h"
|
||||||
|
|
||||||
|
#define MAZE_SIZE 11
|
||||||
|
|
||||||
|
void followPath(robot *r, stack *path,int visited[MAZE_SIZE][MAZE_SIZE]);
|
||||||
|
|
||||||
|
void lee_run(robot r, cell targetCell, stack *moves);
|
||||||
|
|
||||||
|
void lee_expand(int assignmentMatrix[MAZE_SIZE][MAZE_SIZE], cell startCell,cell targetCell) ;
|
||||||
|
void lee_trace(int assignmentMatrix[MAZE_SIZE][MAZE_SIZE], robot r, cell targetCell, stack *stack);
|
||||||
|
|
||||||
|
int validatePath(robot r, stack s);
|
||||||
|
|
||||||
|
int isInBound(cell c);
|
||||||
|
int isStation(cell c);
|
||||||
|
int isValidCrossing(cell c);
|
||||||
|
#endif //LEE_ALGORITHM_H
|
||||||
73
leelib/leelib.c
Normal file
73
leelib/leelib.c
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "../lee-algorithm/lee-algorithm.h"
|
||||||
|
|
||||||
|
void readEdge (int *i, int *j)
|
||||||
|
/* Scans input to read a blocked edge.
|
||||||
|
Returns the indices i and j in m[13][13] of an edge.
|
||||||
|
Call this function with pointers to the variables
|
||||||
|
that should receive the values, e.g.
|
||||||
|
readEdge (&x, &y);
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
int cx, cy;
|
||||||
|
char d;
|
||||||
|
scanf ("%d %d %c", &cy, &cx, &d);
|
||||||
|
if (d == 's') {
|
||||||
|
*i = 2 + cy * 2 + 1;
|
||||||
|
*j = 2 + cx * 2;
|
||||||
|
}
|
||||||
|
else if (d == 'e') {
|
||||||
|
*i = 2 + cy * 2;
|
||||||
|
*j = 2 + cx * 2 + 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fprintf (stderr, "error on direction: %c\n", d);
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void readStation (int *i, int *j)
|
||||||
|
/* Scans input to read a station.
|
||||||
|
Returns the indices i and j in m[13][13] of a station.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
int s;
|
||||||
|
scanf ("%d", &s);
|
||||||
|
switch (s) {
|
||||||
|
case 1: *i = 10, *j = 3; break;
|
||||||
|
case 2: *i = 10, *j = 5; break;
|
||||||
|
case 3: *i = 10, *j = 7; break;
|
||||||
|
case 4: *i = 7, *j = 10; break;
|
||||||
|
case 5: *i = 5, *j = 10; break;
|
||||||
|
case 6: *i = 3, *j = 10; break;
|
||||||
|
case 7: *i = 0, *j = 7; break;
|
||||||
|
case 8: *i = 0, *j = 5; break;
|
||||||
|
case 9: *i = 0, *j = 3; break;
|
||||||
|
case 10: *i = 3, *j = 0; break;
|
||||||
|
case 11: *i = 5, *j = 0; break;
|
||||||
|
case 12: *i = 7, *j = 0; break;
|
||||||
|
default: fprintf (stderr, "Illegal station\n"); exit (-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void printCrossingName (int i, int j)
|
||||||
|
/* Print the name of the crossing with indices i and j in m[13][13]/ */
|
||||||
|
{
|
||||||
|
if ((i-2)%2 == 0 && (j-2)%2 == 0)
|
||||||
|
printf ("c%d%d ", (i-2)/2, (j-2)/2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void printMatrix (int m[][MAZE_SIZE])
|
||||||
|
/* Print the elements of the matrix m[13][13]. */
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
for (i = 0; i < MAZE_SIZE; i++) {
|
||||||
|
for (j = 0; j < MAZE_SIZE; j++) {
|
||||||
|
printf ("%2d ", m[i][j]);
|
||||||
|
}
|
||||||
|
printf ("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
19
leelib/leelib.h
Normal file
19
leelib/leelib.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
void readEdge (int *i, int *j);
|
||||||
|
/* Scans input to read a blocked edge.
|
||||||
|
Returns the indices i and j in m[13][13] of an edge.
|
||||||
|
Call this function with pointers to the variables
|
||||||
|
that should receive the values, e.g.
|
||||||
|
readEdge (&x, &y);
|
||||||
|
*/
|
||||||
|
|
||||||
|
void readStation (int *i, int *j);
|
||||||
|
/* Scans input to read a station.
|
||||||
|
Returns the indices i and j in m[13][13] of a station.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void printCrossingName (int i, int j);
|
||||||
|
/* Print the name of the crossing with indices i and j in m[13][13]/ */
|
||||||
|
|
||||||
|
void printMatrix (int m[][11]);
|
||||||
|
/* Print the elements of the matrix m[13][13]. */
|
||||||
|
|
||||||
46
main.c
Normal file
46
main.c
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#include <ctype.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "cell/cell.h"
|
||||||
|
#include "communication/communication.h"
|
||||||
|
#include "leelib/leelib.h"
|
||||||
|
#include "robot/robot.h"
|
||||||
|
#include "robot/challenges/challenges.h"
|
||||||
|
|
||||||
|
extern int unexpanded_matrix[MAZE_SIZE][MAZE_SIZE];
|
||||||
|
extern int visited[MAZE_SIZE][MAZE_SIZE];
|
||||||
|
|
||||||
|
extern const cell neighbours[4];
|
||||||
|
|
||||||
|
|
||||||
|
void addBlock(robot r, cell move, direction dir, cell targetCell, stack *s);
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
/* read the starting and end station.*/
|
||||||
|
if (argc < 2) {
|
||||||
|
printf("NOT ENOUGH ARGUMENTS \n");
|
||||||
|
printf("USAGE: ./maze <CHALLENGE NR or 0 for simple remote> \n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
switch (strtol(argv[1],NULL, 10)) {
|
||||||
|
case 0:
|
||||||
|
simple_control();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
challenge_2();
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
challenge_3((cell){10,3});
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
challenge_4((cell){10,3});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("DOESNT WORK YET \n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
127
maze-editor.html
Normal file
127
maze-editor.html
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<title>Maze Editor</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
margin: 20px;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
color: #444;
|
||||||
|
}
|
||||||
|
.maze-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
td {
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
input[type="checkbox"] {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.cell-0 {
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
.cell-1 {
|
||||||
|
background-color: #ddd;
|
||||||
|
}
|
||||||
|
.button {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
#output {
|
||||||
|
font-family: monospace;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
input[disabled] {
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Maze Editor</h1>
|
||||||
|
<div id="maze-container" class="maze-container"></div>
|
||||||
|
<button class="button" onclick="printArray()">Show Array</button>
|
||||||
|
<div id="output"></div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const MAZE_SIZE = 11;
|
||||||
|
// Original matrix with -1's
|
||||||
|
const originalMatrix = [
|
||||||
|
[ -1, -1, -1, 0, -1, 0, -1, 0, -1, -1, -1 ],
|
||||||
|
[ -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1 ],
|
||||||
|
[ -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1 ],
|
||||||
|
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
|
||||||
|
[ -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1 ],
|
||||||
|
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
|
||||||
|
[ -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1 ],
|
||||||
|
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
|
||||||
|
[ -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1 ],
|
||||||
|
[ -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1 ],
|
||||||
|
[ -1, -1, -1, 0, -1, 0, -1, 0, -1, -1, -1 ]
|
||||||
|
];
|
||||||
|
|
||||||
|
// Work copy for editing
|
||||||
|
let mazeData = JSON.parse(JSON.stringify(originalMatrix));
|
||||||
|
|
||||||
|
function initMaze() {
|
||||||
|
const container = document.getElementById("maze-container");
|
||||||
|
container.innerHTML = "";
|
||||||
|
const table = document.createElement("table");
|
||||||
|
for (let i = 0; i < MAZE_SIZE; i++) {
|
||||||
|
const tr = document.createElement("tr");
|
||||||
|
for (let j = 0; j < MAZE_SIZE; j++) {
|
||||||
|
const td = document.createElement("td");
|
||||||
|
const checkbox = document.createElement("input");
|
||||||
|
checkbox.type = "checkbox";
|
||||||
|
checkbox.checked = mazeData[i][j] === -1;
|
||||||
|
// Disable if original value is -1 OR not at even indices
|
||||||
|
checkbox.disabled =
|
||||||
|
originalMatrix[i][j] === -1 ||
|
||||||
|
!(i % 2 === 0 || j % 2 === 0) ||
|
||||||
|
checkbox.addEventListener("change", function () {
|
||||||
|
mazeData[i][j] = this.checked ? -1 : 0;
|
||||||
|
updateCellClass(td, this.checked);
|
||||||
|
});
|
||||||
|
td.appendChild(checkbox);
|
||||||
|
updateCellClass(td, mazeData[i][j] === -1);
|
||||||
|
tr.appendChild(td);
|
||||||
|
}
|
||||||
|
table.appendChild(tr);
|
||||||
|
}
|
||||||
|
container.appendChild(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateCellClass(td, isWall) {
|
||||||
|
td.className = isWall ? "cell-1" : "cell-0";
|
||||||
|
}
|
||||||
|
|
||||||
|
function printArray() {
|
||||||
|
let output = "int unexpanded_matrix[MAZE_SIZE][MAZE_SIZE] = {\n";
|
||||||
|
for (let i = 0; i < MAZE_SIZE; i++) {
|
||||||
|
output += "\t{";
|
||||||
|
for (let j = 0; j < MAZE_SIZE; j++) {
|
||||||
|
output += mazeData[i][j];
|
||||||
|
if (j < MAZE_SIZE - 1) output += ", ";
|
||||||
|
}
|
||||||
|
output += "}";
|
||||||
|
if (i < MAZE_SIZE - 1) output += ",";
|
||||||
|
output += "\n";
|
||||||
|
}
|
||||||
|
output += "};";
|
||||||
|
document.getElementById("output").textContent = output;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.onload = initMaze;
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
101
robot/challenges/challenge2.c
Normal file
101
robot/challenges/challenge2.c
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "../../communication/communication.h"
|
||||||
|
#include "../../leelib/leelib.h"
|
||||||
|
#include "../../lee-algorithm/lee-algorithm.h"
|
||||||
|
#include "../challenges/challenges.h"
|
||||||
|
|
||||||
|
extern int unexpanded_matrix[MAZE_SIZE][MAZE_SIZE];
|
||||||
|
extern const cell neighbours[4]; // SOUTH, EAST, WEST, NORTH
|
||||||
|
|
||||||
|
|
||||||
|
int compute_path_length(cell from, cell to);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void challenge_2() {
|
||||||
|
comm_init_communication();
|
||||||
|
|
||||||
|
cell start;
|
||||||
|
printf("Starting station: ");
|
||||||
|
readStation(&start.x, &start.y);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
robot r;
|
||||||
|
r.pos = start;
|
||||||
|
r.dir = getStartDirection(start);
|
||||||
|
//cell_add(&r.pos,r.pos,neighbours[r.dir]);
|
||||||
|
cell stations[3];
|
||||||
|
for(int i=0;i<3;i++){
|
||||||
|
printf("Station to visit %d: ",i+1);
|
||||||
|
readStation(&(stations[i].x),&(stations[i].y));
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
int bestOrder[3];
|
||||||
|
int minTotal = INT_MAX;
|
||||||
|
|
||||||
|
// test alle 6
|
||||||
|
for (int a = 0; a < 3; a++) {
|
||||||
|
for (int b = 0; b < 3; b++) {
|
||||||
|
if (b == a) continue;
|
||||||
|
for (int c = 0; c < 3; c++) {
|
||||||
|
if (c == a || c == b) continue;
|
||||||
|
int total = 0;
|
||||||
|
total += compute_path_length(start, stations[a]);
|
||||||
|
total += compute_path_length(stations[a], stations[b]);
|
||||||
|
total += compute_path_length(stations[b], stations[c]);
|
||||||
|
if (total < minTotal) {
|
||||||
|
minTotal = total;
|
||||||
|
bestOrder[0] = a;
|
||||||
|
bestOrder[1] = b;
|
||||||
|
bestOrder[2] = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int visited[MAZE_SIZE][MAZE_SIZE]={0};
|
||||||
|
memcpy(visited, unexpanded_matrix, sizeof(unexpanded_matrix));
|
||||||
|
|
||||||
|
// volg beste volgorde
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
cell target = stations[bestOrder[i]];
|
||||||
|
printf("\n[Station %d] Naar (%d, %d):\n", i+1, target.x, target.y);
|
||||||
|
stack path;
|
||||||
|
stack_init(&path);
|
||||||
|
lee_run(r, target, &path);
|
||||||
|
followPath(&r, &path,visited);
|
||||||
|
visited[r.pos.x][r.pos.y] = 5;
|
||||||
|
stack_free(&path);
|
||||||
|
}
|
||||||
|
printMatrix_with_current_pos(visited,r);
|
||||||
|
printAllMoves();
|
||||||
|
comm_end_communication();
|
||||||
|
}
|
||||||
|
|
||||||
|
int compute_path_length(const cell from, const cell to) { //modified expand phase to get maximum length
|
||||||
|
if (to.x == 999 && to.y == 999) return 999;
|
||||||
|
int tempMatrix[MAZE_SIZE][MAZE_SIZE];
|
||||||
|
memcpy(tempMatrix, unexpanded_matrix, sizeof(tempMatrix));
|
||||||
|
int steps = 1;
|
||||||
|
tempMatrix[to.x][to.y] = steps;
|
||||||
|
while (tempMatrix[from.x][from.y] == 0) {
|
||||||
|
for (int i = 0; i < MAZE_SIZE; i++) {
|
||||||
|
for (int j = 0; j < MAZE_SIZE; j++) {
|
||||||
|
if (tempMatrix[i][j] == steps) {
|
||||||
|
for (int k = 0; k < 4; k++) {
|
||||||
|
cell n;
|
||||||
|
cell_add(&n,(cell){i,j}, neighbours[k]);
|
||||||
|
if (isInBound(n) && tempMatrix[n.x][n.y] == 0) {
|
||||||
|
tempMatrix[n.x][n.y] = steps + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
steps++;
|
||||||
|
if (steps > 1000) break;
|
||||||
|
}
|
||||||
|
return tempMatrix[from.x][from.y] ? tempMatrix[from.x][from.y] : INT_MAX;
|
||||||
|
}
|
||||||
169
robot/challenges/challenge3.c
Normal file
169
robot/challenges/challenge3.c
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include "../../cell/cell.h"
|
||||||
|
#include <limits.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "../robot.h"
|
||||||
|
#include "../../communication/communication.h"
|
||||||
|
#include "../../communication/utils.h"
|
||||||
|
#include "../../lee-algorithm/lee-algorithm.h"
|
||||||
|
#include "../../leelib/leelib.h"
|
||||||
|
#include "../challenges/challenges.h"
|
||||||
|
|
||||||
|
#define MAZE_SIZE 11
|
||||||
|
|
||||||
|
extern int unexpanded_matrix[MAZE_SIZE][MAZE_SIZE];
|
||||||
|
extern const cell neighbours[4]; // volgorde: SOUTH, EAST, WEST, NORTH
|
||||||
|
|
||||||
|
|
||||||
|
int compute_path_length(cell from, cell to);
|
||||||
|
void find_best_order_of_3(cell start,cell stations[3],int bestOrder[3]);
|
||||||
|
void find_best_order_of_2(cell start,cell stations[2],int bestOrder[2]);
|
||||||
|
|
||||||
|
|
||||||
|
void challenge_3(cell start) {
|
||||||
|
comm_init_communication();
|
||||||
|
int visited[MAZE_SIZE][MAZE_SIZE]={0};
|
||||||
|
memcpy(visited, unexpanded_matrix, sizeof(unexpanded_matrix));
|
||||||
|
|
||||||
|
robot r;
|
||||||
|
r.pos = start;
|
||||||
|
r.dir = getStartDirection(start);
|
||||||
|
|
||||||
|
stack path;
|
||||||
|
stack_init(&path);
|
||||||
|
|
||||||
|
int visitedStations=0,run=1,bestOrder[3];
|
||||||
|
|
||||||
|
cell all_stations[3];
|
||||||
|
cell last_stations[2];
|
||||||
|
|
||||||
|
for(int i=0;i<3;i++){
|
||||||
|
printf("Station to visit %d: ",i+1);
|
||||||
|
readStation(&(all_stations[i].x),&(all_stations[i].y));
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
find_best_order_of_3(start,all_stations,bestOrder);
|
||||||
|
|
||||||
|
cell target = all_stations[bestOrder[0]];
|
||||||
|
lee_run(r, target, &path);
|
||||||
|
|
||||||
|
while (run){
|
||||||
|
printf("\n[Station %d] Naar (%d, %d):\n", visitedStations +1 ,target.x, target.y);
|
||||||
|
switch (visitedStations) {
|
||||||
|
case 0:
|
||||||
|
if (!followPath_with_blockages(&r, &path,visited)) {
|
||||||
|
find_best_order_of_3(r.pos,all_stations,bestOrder);
|
||||||
|
target = all_stations[bestOrder[0]];
|
||||||
|
stack_reinit(&path);
|
||||||
|
lee_run(r, target, &path);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//robot is in the station, manually spin
|
||||||
|
unexpanded_matrix[r.pos.x][r.pos.y]=0; //bugfix, somehow something was causing for a blockage to show up at station.
|
||||||
|
turnRight(&r);
|
||||||
|
r.dir=(r.dir+1)%4;
|
||||||
|
comm_await_crossing(2000);
|
||||||
|
comm_discard_sensor_data(1000);
|
||||||
|
visitedStations++;
|
||||||
|
last_stations[0] = all_stations[bestOrder[1]];
|
||||||
|
last_stations[1] = all_stations[bestOrder[2]];
|
||||||
|
find_best_order_of_2(r.pos,last_stations,bestOrder);
|
||||||
|
stack_reinit(&path);
|
||||||
|
target = last_stations[bestOrder[0]];
|
||||||
|
lee_run(r, target, &path);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if (!followPath_with_blockages(&r, &path,visited)) {
|
||||||
|
find_best_order_of_2(r.pos,last_stations,bestOrder);
|
||||||
|
target = last_stations[bestOrder[0]];
|
||||||
|
stack_reinit(&path);
|
||||||
|
lee_run(r, target, &path);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//robot is in the station, manually spin
|
||||||
|
unexpanded_matrix[r.pos.x][r.pos.y]=0; //bugfix, somehow something was causing for a blockage to show up at station.
|
||||||
|
turnRight(&r);
|
||||||
|
r.dir=(r.dir+1)%4;
|
||||||
|
comm_await_crossing(2000);
|
||||||
|
comm_discard_sensor_data(1000);
|
||||||
|
visitedStations++;
|
||||||
|
stack_reinit(&path);
|
||||||
|
target = last_stations[bestOrder[1]];
|
||||||
|
lee_run(r, target, &path);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (!followPath_with_blockages(&r,&path,visited)) {
|
||||||
|
stack_reinit(&path);
|
||||||
|
lee_run(r, target, &path);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//robot is in the station, manually spin
|
||||||
|
unexpanded_matrix[r.pos.x][r.pos.y]=0; //bugfix, somehow something was causing for a blockage to show up at station.
|
||||||
|
turnRight(&r);
|
||||||
|
r.dir=(r.dir+1)%4;
|
||||||
|
comm_await_crossing(2000);
|
||||||
|
comm_discard_sensor_data(1000);
|
||||||
|
visitedStations++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
run=0;
|
||||||
|
break;
|
||||||
|
default: ;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
stack_free(&path);
|
||||||
|
printMatrix_with_current_pos(visited,r);
|
||||||
|
printAllMoves();
|
||||||
|
comm_end_communication();
|
||||||
|
}
|
||||||
|
|
||||||
|
void find_best_order_of_3(cell start,cell stations[3],int bestOrder[3]) {
|
||||||
|
int minTotal = INT_MAX;
|
||||||
|
|
||||||
|
// test alle 6
|
||||||
|
for (int a = 0; a < 3; a++) {
|
||||||
|
for (int b = 0; b < 3; b++) {
|
||||||
|
if (b == a) continue;
|
||||||
|
for (int c = 0; c < 3; c++) {
|
||||||
|
if (c == a || c == b) continue;
|
||||||
|
int total = 0;
|
||||||
|
total += compute_path_length(start, stations[a]);
|
||||||
|
total += compute_path_length(stations[a], stations[b]);
|
||||||
|
total += compute_path_length(stations[b], stations[c]);
|
||||||
|
if (total < minTotal) {
|
||||||
|
minTotal = total;
|
||||||
|
bestOrder[0] = a;
|
||||||
|
bestOrder[1] = b;
|
||||||
|
bestOrder[2] = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void find_best_order_of_2(cell start,cell stations[2],int bestOrder[2]) {
|
||||||
|
|
||||||
|
int total1 = 0;
|
||||||
|
total1 += compute_path_length(start, stations[0]);
|
||||||
|
total1 += compute_path_length(stations[0], stations[1]);
|
||||||
|
|
||||||
|
int total2 = 0;
|
||||||
|
total2 += compute_path_length(start, stations[1]);
|
||||||
|
total2 += compute_path_length(stations[1], stations[0]);
|
||||||
|
|
||||||
|
if (total1 < total2) {
|
||||||
|
bestOrder[0] = 0;
|
||||||
|
bestOrder[1] = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bestOrder[0] = 1;
|
||||||
|
bestOrder[1] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
168
robot/challenges/challenge4.c
Normal file
168
robot/challenges/challenge4.c
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
#include <limits.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "../../stack/stack.h"
|
||||||
|
#include "../../cell/cell.h"
|
||||||
|
#include "../../communication/communication.h"
|
||||||
|
#include "../../lee-algorithm/lee-algorithm.h"
|
||||||
|
#include "../../leelib/leelib.h"
|
||||||
|
#include "../challenges/challenges.h"
|
||||||
|
|
||||||
|
#define MAZE_SIZE 11
|
||||||
|
|
||||||
|
extern int unexpanded_matrix[MAZE_SIZE][MAZE_SIZE];
|
||||||
|
extern cell neighbours[4];
|
||||||
|
extern cell crossing_neighbours[4];
|
||||||
|
int findNearestCrossing(robot r,int visited [MAZE_SIZE][ MAZE_SIZE],cell *result,int *crossing_counter);
|
||||||
|
int compute_path_length(cell from, const cell to) ;
|
||||||
|
|
||||||
|
|
||||||
|
void challenge_4(cell start) {
|
||||||
|
comm_init_communication();
|
||||||
|
cell finalStation,finalCrossing;
|
||||||
|
printf("Final destination? ");
|
||||||
|
readStation(&finalStation.x, &finalStation.y);
|
||||||
|
direction finalDirection = getStartDirection(finalStation); // direction away from the ending start
|
||||||
|
|
||||||
|
robot r;
|
||||||
|
r.pos = start;
|
||||||
|
r.dir = getStartDirection(start);
|
||||||
|
cell_add(&finalCrossing,finalStation,neighbours[getStartDirection(finalStation)]);
|
||||||
|
int visited[MAZE_SIZE][MAZE_SIZE] = {0};
|
||||||
|
memcpy(visited, unexpanded_matrix, sizeof(unexpanded_matrix));
|
||||||
|
|
||||||
|
|
||||||
|
cell result;
|
||||||
|
stack moves;
|
||||||
|
int crossing_counter=0,obstacle_counter=0;
|
||||||
|
stack_init(&moves);
|
||||||
|
|
||||||
|
stack first_move;
|
||||||
|
stack_init(&first_move);
|
||||||
|
stack_push(&first_move,neighbours[r.dir]);
|
||||||
|
followPath_with_blockages(&r,&first_move,visited);
|
||||||
|
|
||||||
|
while (findNearestCrossing(r,visited,&result,&crossing_counter)) {
|
||||||
|
lee_run(r,result,&moves);
|
||||||
|
if (!followPath_with_blockages(&r,&moves,visited)) { // ensure all is visited, no check for nr of obstacles because sometimes it creates bugs
|
||||||
|
obstacle_counter++;
|
||||||
|
if (validatePath(r,moves)) {
|
||||||
|
printf("following path \n");
|
||||||
|
followPath(&r,&moves,visited);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
crossing_counter--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { // if we know where all 12 blocks are, we go
|
||||||
|
followPath(&r,&moves,visited);
|
||||||
|
}
|
||||||
|
stack_reinit(&moves);
|
||||||
|
printf("Crossings:%d \n",crossing_counter);
|
||||||
|
//if (crossing_counter==25) {
|
||||||
|
// break;
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
lee_run(r,finalCrossing,&moves); // Go to crossing in front of the final destination
|
||||||
|
followPath(&r,&moves,visited);
|
||||||
|
stack_free(&moves);
|
||||||
|
spin(&r,finalDirection);
|
||||||
|
printMatrix_with_current_pos(visited,r);
|
||||||
|
parkBackwards(&r);
|
||||||
|
printMatrix_with_current_pos(visited,r);
|
||||||
|
printf("done");
|
||||||
|
printAllMoves();
|
||||||
|
comm_end_communication();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to find the nearest/best crossing to go to
|
||||||
|
* Steps:
|
||||||
|
* - Unvisited and without blocks
|
||||||
|
* - Unvisited but with a block
|
||||||
|
* - Visited
|
||||||
|
* In all cases forwards gets priority
|
||||||
|
* @param r robot
|
||||||
|
* @param visited array of all visited cells
|
||||||
|
* @param result crossing that was chosen as the best next possible move
|
||||||
|
* @param crossing_counter count amount of crossings
|
||||||
|
* @return 1 if found an unvisited crossing, 0 if all crossings visited.
|
||||||
|
*/
|
||||||
|
int findNearestCrossing(robot r,int visited [MAZE_SIZE][MAZE_SIZE],cell *result,int *crossing_counter) {
|
||||||
|
cell tempcell;
|
||||||
|
robot temp_robot;
|
||||||
|
temp_robot.pos = r.pos;
|
||||||
|
temp_robot.dir = r.dir;
|
||||||
|
|
||||||
|
if(!isValidCrossing(temp_robot.pos)){ // if robot is in a intersection, move it to crossing
|
||||||
|
cell_add(&temp_robot.pos,temp_robot.pos,neighbours[r.dir]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for nearby unvisited crossings and without blockages
|
||||||
|
for (int i=0;i<4;i++) {
|
||||||
|
cell_add(&tempcell,temp_robot.pos,neighbours[(r.dir+i)%4]);
|
||||||
|
if (isInBound(tempcell) && unexpanded_matrix[tempcell.x][tempcell.y]!=-1) {
|
||||||
|
cell_add(&tempcell,temp_robot.pos,crossing_neighbours[(r.dir+i)%4]);
|
||||||
|
if (isValidCrossing(tempcell) && visited[tempcell.x][tempcell.y] == 0) {
|
||||||
|
*result= tempcell;
|
||||||
|
*crossing_counter+=1;
|
||||||
|
printf("nearby_unvisited \n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//find closest neighbour of neighbours
|
||||||
|
int min_distance = INT_MAX;
|
||||||
|
cell min_cell = (cell){0,0};
|
||||||
|
|
||||||
|
for (int i=0;i<4;i++) {
|
||||||
|
cell neighbour_crossing;
|
||||||
|
cell_add(&neighbour_crossing,temp_robot.pos,crossing_neighbours[i]);
|
||||||
|
for (int j=0;j<4;j++) {
|
||||||
|
cell_add(&tempcell,neighbour_crossing,neighbours[j]);
|
||||||
|
if (isInBound(tempcell) && unexpanded_matrix[tempcell.x][tempcell.y]!=-1) {
|
||||||
|
cell_add(&tempcell,tempcell,neighbours[j]);
|
||||||
|
if (isValidCrossing(tempcell) && visited[tempcell.x][tempcell.y] == 0) {
|
||||||
|
int tmp = compute_path_length(r.pos,tempcell);
|
||||||
|
if (tmp <= min_distance) {
|
||||||
|
min_distance=tmp;
|
||||||
|
min_cell = tempcell;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!cell_equals(min_cell, (cell){0,0})) {
|
||||||
|
*result=min_cell;
|
||||||
|
*crossing_counter+=1;
|
||||||
|
printf("neighb_of_neighb \n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
min_distance = INT_MAX;
|
||||||
|
min_cell = (cell){0,0};
|
||||||
|
//find the closest unvisited crossing that isnt a neighbour of a neighbour.
|
||||||
|
for (int i=0;i<MAZE_SIZE;i++) {
|
||||||
|
for (int j=0;j<MAZE_SIZE;j++) {
|
||||||
|
tempcell = (cell) {i,j};
|
||||||
|
if (isValidCrossing(tempcell) && visited[i][j] == 0) {
|
||||||
|
int tmp = compute_path_length(r.pos,tempcell);
|
||||||
|
if (tmp <= min_distance) {
|
||||||
|
min_distance=tmp;
|
||||||
|
min_cell = tempcell;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!cell_equals(min_cell, (cell){0,0})) {
|
||||||
|
*result=min_cell;
|
||||||
|
*crossing_counter+=1;
|
||||||
|
printf("random_iterate \n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
11
robot/challenges/challenges.h
Normal file
11
robot/challenges/challenges.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#ifndef CHALLENGES_H
|
||||||
|
#define CHALLENGES_H
|
||||||
|
#include "../../cell/cell.h"
|
||||||
|
|
||||||
|
|
||||||
|
void challenge_2();
|
||||||
|
void challenge_3(cell start);
|
||||||
|
void challenge_4(cell start);
|
||||||
|
void challenge_4_old(cell start) ;
|
||||||
|
#endif
|
||||||
|
|
||||||
174
robot/controller-moves.c
Normal file
174
robot/controller-moves.c
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
//
|
||||||
|
// Created by nano on 5/14/25.
|
||||||
|
//
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "robot.h"
|
||||||
|
#include "../communication/communication.h"
|
||||||
|
#include "../communication/utils.h"
|
||||||
|
#include "../lee-algorithm/lee-algorithm.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define FORWARD 4
|
||||||
|
#define BACKWARD 5//TBD
|
||||||
|
#define TURN_LEFT 1
|
||||||
|
#define TURN_RIGHT 2
|
||||||
|
#define TURN_AROUND 3
|
||||||
|
|
||||||
|
#define PARK 6
|
||||||
|
|
||||||
|
#define CROSSING 32
|
||||||
|
|
||||||
|
int firstMove = 1;
|
||||||
|
/*
|
||||||
|
* FIRST MOVE:
|
||||||
|
* SEND: FWD
|
||||||
|
* RECV: ACK, SENSOR_DATA, CROSSING
|
||||||
|
* SEND: next move
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern cell neighbours[4];
|
||||||
|
extern cell crossing_neighbours[4];
|
||||||
|
/* For any move:
|
||||||
|
* C SEND: LEFT / RIGHT / FWD
|
||||||
|
* C RECV: ACK , CROSSING, <SENSOR DATA>
|
||||||
|
* C SEND: NEXT INSTRUCTION
|
||||||
|
*/
|
||||||
|
void turnLeft(robot *r) {
|
||||||
|
comm_write_until_successful(TURN_LEFT, 1000);
|
||||||
|
r->dir = (r->dir + 3) % 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
void turnRight(robot *r) {
|
||||||
|
comm_write_until_successful(TURN_RIGHT, 1000);
|
||||||
|
r->dir = (r->dir + 1) % 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
void turnAround(robot *r) {
|
||||||
|
/*
|
||||||
|
comm_write_until_successful(TURN_AROUND,1000);
|
||||||
|
r->dir = (r->dir + 2) % 4;*/
|
||||||
|
//THIJS:
|
||||||
|
turnRight(r);
|
||||||
|
comm_await_crossing(2000);
|
||||||
|
comm_discard_sensor_data(1000);
|
||||||
|
turnRight(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
void forward(robot *r) {
|
||||||
|
comm_write_until_successful(FORWARD, 1000);
|
||||||
|
cell_add(&r->pos, r->pos, neighbours[r->dir]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void backward(robot *r) {
|
||||||
|
comm_write_until_successful(BACKWARD,1000);
|
||||||
|
cell_add(&r->pos, r->pos, crossing_neighbours[(r->dir + 2) % 4]);
|
||||||
|
//printf("Doesnt exist rn");
|
||||||
|
//exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void parkBackwards(robot *r) {
|
||||||
|
comm_write_until_successful(PARK,1000);
|
||||||
|
cell_add(&r->pos,r->pos,neighbours[(r->dir + 2) % 4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//BJORN CODE
|
||||||
|
/*
|
||||||
|
int first_move = 1;
|
||||||
|
int followPath_with_blockages(robot *r, stack *path, int visited[MAZE_SIZE][MAZE_SIZE]) {
|
||||||
|
|
||||||
|
while (path->length > 0 ) {
|
||||||
|
int len=0;
|
||||||
|
cell current_move = stack_pop(path);
|
||||||
|
int result = move(r, current_move);
|
||||||
|
visited[r->pos.x][r->pos.y] = 5;
|
||||||
|
printMatrix_with_current_pos(visited, *r);
|
||||||
|
|
||||||
|
switch (result) {
|
||||||
|
case 0: //SPIN --> we expect sensor data
|
||||||
|
comm_get_distance_sensor(&len, 1000);
|
||||||
|
if (len != 0) {
|
||||||
|
len=(len-1)*2+1;
|
||||||
|
register_sensor_blockages(r, len, visited);
|
||||||
|
comm_await_crossing(2000);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
comm_await_crossing(2000);
|
||||||
|
break;
|
||||||
|
case 1: // FWD --> we do not expect sensor data, except fist move
|
||||||
|
comm_await_crossing(2000);
|
||||||
|
if (first_move) {
|
||||||
|
comm_get_distance_sensor(&len, 1000);
|
||||||
|
if (len != 0) {
|
||||||
|
len=(len-1)*2+1;
|
||||||
|
register_sensor_blockages(r, len, visited);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default : ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
|
||||||
|
int followPath_with_blockages(robot *r, stack *path, int visited[MAZE_SIZE][MAZE_SIZE]) {
|
||||||
|
while (path->length > 0) {
|
||||||
|
int len = 0;
|
||||||
|
cell current_move = stack_pop(path);
|
||||||
|
int result = move(r, current_move);
|
||||||
|
visited[r->pos.x][r->pos.y] = 5;
|
||||||
|
switch (isValidCrossing(r->pos)) {
|
||||||
|
case 1:
|
||||||
|
comm_await_crossing(2000);
|
||||||
|
comm_get_distance_sensor(&len, 1000);
|
||||||
|
if (len != 0) {
|
||||||
|
//len=(len-1)*2+1;
|
||||||
|
register_sensor_blockages(r, len, visited);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
comm_await_crossing(2000);
|
||||||
|
comm_discard_sensor_data(1000);
|
||||||
|
break;
|
||||||
|
default: ;
|
||||||
|
}
|
||||||
|
printMatrix_with_current_pos(visited, *r);
|
||||||
|
if (result==0) { //spin
|
||||||
|
move(r, current_move); // advance forward
|
||||||
|
comm_await_crossing(2000);
|
||||||
|
comm_get_distance_sensor(&len, 1000);
|
||||||
|
if (len != 0) {
|
||||||
|
//len=(len-1)*2+1;
|
||||||
|
register_sensor_blockages(r, len, visited);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
printf("Continuing after spin cause no block \n");
|
||||||
|
printMatrix_with_current_pos(visited, *r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void printAllMoves() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void comm_discard_sensor_data(int timeout) {
|
||||||
|
printf("DISCARDING DATA\n");
|
||||||
|
byte *b = malloc(sizeof(byte));
|
||||||
|
int run = 1;
|
||||||
|
//while (run) {
|
||||||
|
comm_blocking_read(b, 1, timeout);
|
||||||
|
// for (int i = 1; i <= 5; i++) {
|
||||||
|
// if (*b == (byte) i) {
|
||||||
|
// run = 0;
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
printf("%d\n", *b);
|
||||||
|
free(b);
|
||||||
|
}
|
||||||
57
robot/remote.c
Normal file
57
robot/remote.c
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
//
|
||||||
|
// Created by nano on 5/14/25.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "robot.h"
|
||||||
|
#include "../communication/communication.h"
|
||||||
|
#include "../communication/utils.h"
|
||||||
|
#include "../leelib/leelib.h"
|
||||||
|
|
||||||
|
void simple_control() {
|
||||||
|
robot r;
|
||||||
|
printf("Where are we starting? ");
|
||||||
|
readStation(&r.pos.x,&r.pos.y);
|
||||||
|
r.dir=getStartDirection(r.pos);
|
||||||
|
|
||||||
|
comm_init_communication();
|
||||||
|
char in;
|
||||||
|
int run = 1;
|
||||||
|
while (run) {
|
||||||
|
printf("Move? ");
|
||||||
|
scanf("%c", &in);
|
||||||
|
switch (tolower(in)) {
|
||||||
|
case 'f':
|
||||||
|
printf("going forward\n");
|
||||||
|
forward(&r);
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
printf("going backward\n");
|
||||||
|
backward(&r);
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
printf("going left\n");
|
||||||
|
turnLeft(&r);
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
printf("turning right\n");
|
||||||
|
turnRight(&r);
|
||||||
|
break;
|
||||||
|
case 'a':
|
||||||
|
printf("turning around\n");
|
||||||
|
turnAround(&r);
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
printf("exiting\n");
|
||||||
|
run = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//byte b;
|
||||||
|
//comm_await_crossing(&b,50);
|
||||||
|
}
|
||||||
|
comm_end_communication();
|
||||||
|
}
|
||||||
134
robot/robot.c
Normal file
134
robot/robot.c
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
//
|
||||||
|
// Created by nano on 5/9/25.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "robot.h"
|
||||||
|
|
||||||
|
#include "../lee-algorithm/lee-algorithm.h"
|
||||||
|
|
||||||
|
extern int unexpanded_matrix[MAZE_SIZE][MAZE_SIZE];
|
||||||
|
extern const cell neighbours[4];
|
||||||
|
char *arrow[4] = {"↑", "→", "↓", "←"};
|
||||||
|
|
||||||
|
// Richting in tekst
|
||||||
|
const char *directionToString(direction dir) {
|
||||||
|
switch (dir) {
|
||||||
|
case NORTH: return "NORTH";
|
||||||
|
case EAST: return "EAST";
|
||||||
|
case SOUTH: return "SOUTH";
|
||||||
|
case WEST: return "WEST";
|
||||||
|
default: return "UNKNOWN";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bepaal gewenste richting van current naar next
|
||||||
|
|
||||||
|
int determineDirection(cell from, cell to) {
|
||||||
|
if (to.x == from.x - 1) return NORTH;
|
||||||
|
if (to.x == from.x + 1) return SOUTH;
|
||||||
|
if (to.y == from.y - 1) return WEST;
|
||||||
|
if (to.y == from.y + 1) return EAST;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int determineDirectionFromMove(cell move) {
|
||||||
|
if (move.x == -1) return NORTH;
|
||||||
|
if (move.x == 1) return SOUTH;
|
||||||
|
if (move.y == -1) return WEST;
|
||||||
|
if (move.y == 1) return EAST;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getStartDirection(cell startCell) {
|
||||||
|
if (startCell.x == 0) return SOUTH;
|
||||||
|
if (startCell.x == MAZE_SIZE - 1) return NORTH;
|
||||||
|
if (startCell.y == 0) return EAST;
|
||||||
|
if (startCell.y == MAZE_SIZE - 1) return WEST;
|
||||||
|
|
||||||
|
//fprintf(stderr, "Warning: startCell is not on the maze edge!\n");
|
||||||
|
return NORTH; // fallback
|
||||||
|
}
|
||||||
|
|
||||||
|
void spin(robot *robot, direction desiredDirection) {
|
||||||
|
switch (robot->dir - desiredDirection) {
|
||||||
|
case -2:
|
||||||
|
case 2:
|
||||||
|
turnAround(robot);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
case -3:
|
||||||
|
turnLeft(robot);
|
||||||
|
break;
|
||||||
|
case -1:
|
||||||
|
case 3:
|
||||||
|
turnRight(robot);
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* move the robot
|
||||||
|
* @param r robot
|
||||||
|
* @param move which move to make
|
||||||
|
* @return 1 if forward
|
||||||
|
* @return 0 if spin
|
||||||
|
*/
|
||||||
|
int move(robot *r, cell move) {
|
||||||
|
if (r->dir != (direction) determineDirectionFromMove(move)) {
|
||||||
|
spin(r, determineDirectionFromMove(move));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
forward(r);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Sensorinput: geeft 1–4 aan, blok in die richting, gemeten vanaf huidige robotpositie
|
||||||
|
void register_sensor_blockages(robot* r, int sensorInput,int visited[MAZE_SIZE][MAZE_SIZE]) {
|
||||||
|
|
||||||
|
if (!isValidCrossing(r->pos)) {
|
||||||
|
printf("Waarschuwing: robot staat niet op een kruispunt (%d,%d)", r->pos.x, r->pos.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
cell step = r->pos;
|
||||||
|
switch (r->dir) {
|
||||||
|
case NORTH: step.x -= sensorInput; break;
|
||||||
|
case EAST: step.y += sensorInput; break;
|
||||||
|
case SOUTH: step.x += sensorInput; break;
|
||||||
|
case WEST: step.y -= sensorInput; break;
|
||||||
|
}
|
||||||
|
if (step.x >= 1 && step.x < MAZE_SIZE-1 &&
|
||||||
|
step.y >= 1 && step.y < MAZE_SIZE-1 &&
|
||||||
|
((step.x%2==1 && step.y%2==0)|| (step.x%2==0 && step.y%2==1))) {
|
||||||
|
unexpanded_matrix[step.x][step.y] = -1;
|
||||||
|
visited[step.x][step.y] = -1;
|
||||||
|
printf("Blokkade geregistreerd op (%d, %d)", step.x, step.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void printMatrix_with_current_pos(int m[][MAZE_SIZE], robot r) {
|
||||||
|
//system("clear");
|
||||||
|
printf("\n");
|
||||||
|
for (int i = 0; i < MAZE_SIZE; i++) {
|
||||||
|
for (int j = 0; j < MAZE_SIZE; j++) {
|
||||||
|
if (r.pos.x == i && r.pos.y == j) {
|
||||||
|
printf("\033[31;47;1;4m %s \033[0m", arrow[r.dir]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (m[i][j] == 5) {
|
||||||
|
printf("\033[34;47;1m%3s\033[0m", "░░░");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
printf("\033[%dm%3s\33[0m",m[i][j]<0?40:107, "░░░");
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
58
robot/robot.h
Normal file
58
robot/robot.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
//
|
||||||
|
// Created by nano on 5/9/25.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ROBOT_H
|
||||||
|
#define ROBOT_H
|
||||||
|
#include "../cell/cell.h"
|
||||||
|
#include "../stack/stack.h"
|
||||||
|
|
||||||
|
#define MAZE_SIZE 11
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
NORTH = 0,
|
||||||
|
EAST = 1,
|
||||||
|
SOUTH = 2,
|
||||||
|
WEST = 3
|
||||||
|
} direction;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
cell pos;
|
||||||
|
direction dir;
|
||||||
|
} robot;
|
||||||
|
|
||||||
|
void turnLeft(robot *r);
|
||||||
|
|
||||||
|
void turnRight(robot *r);
|
||||||
|
|
||||||
|
void turnAround(robot *r);
|
||||||
|
|
||||||
|
void forward(robot *r);
|
||||||
|
|
||||||
|
void backward(robot *r);
|
||||||
|
|
||||||
|
const char *directionToString(direction dir);
|
||||||
|
|
||||||
|
int determineDirection(cell from, cell to);
|
||||||
|
|
||||||
|
int determineDirectionFromMove(cell move);
|
||||||
|
|
||||||
|
int getStartDirection(cell startCell);
|
||||||
|
|
||||||
|
void spin(robot *robot, direction desiredDirection);
|
||||||
|
|
||||||
|
int move(robot *r, cell move);
|
||||||
|
|
||||||
|
void printMatrix_with_current_pos(int m[][MAZE_SIZE], robot r);
|
||||||
|
|
||||||
|
void register_sensor_blockages(robot* r, int sensorInput, int visited[MAZE_SIZE][MAZE_SIZE]);
|
||||||
|
|
||||||
|
int followPath_with_blockages(robot *r, stack *path,int visited[MAZE_SIZE][MAZE_SIZE]);
|
||||||
|
|
||||||
|
void simple_control();
|
||||||
|
|
||||||
|
void printAllMoves();
|
||||||
|
void parkBackwards(robot *r);
|
||||||
|
void comm_discard_sensor_data(int timeout);
|
||||||
|
#endif //ROBOT_H
|
||||||
66
robot/simple-simulator.c
Normal file
66
robot/simple-simulator.c
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define SIMULATION
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include "../leelib/leelib.h"
|
||||||
|
#include "../lee-algorithm/lee-algorithm.h"
|
||||||
|
#include "../cell/cell.h"
|
||||||
|
|
||||||
|
extern int unexpanded_matrix[MAZE_SIZE][MAZE_SIZE];
|
||||||
|
extern const cell neighbours[4];
|
||||||
|
|
||||||
|
|
||||||
|
void addBlock(robot r, direction dir, cell targetCell, stack *s);
|
||||||
|
|
||||||
|
void simple_control() { //TODO: OUTDATED, rewrite if needed.
|
||||||
|
/* read the starting and end station.*/
|
||||||
|
cell startCell, targetCell;
|
||||||
|
printf("STARTING AND ENDING STATION: ");
|
||||||
|
readStation(&startCell.x, &startCell.y);
|
||||||
|
readStation(&targetCell.x, &targetCell.y);
|
||||||
|
|
||||||
|
robot r;
|
||||||
|
r.dir = getStartDirection(startCell);
|
||||||
|
r.pos = startCell;
|
||||||
|
stack s;
|
||||||
|
stack_init(&s);
|
||||||
|
lee_run(r, targetCell, &s);
|
||||||
|
|
||||||
|
while (s.length > 0) {
|
||||||
|
move(&r, stack_pop(&s));
|
||||||
|
printMatrix_with_current_pos(unexpanded_matrix, r);
|
||||||
|
|
||||||
|
printf("BLOCKAGE: ");
|
||||||
|
char input;
|
||||||
|
scanf("%c", &input);
|
||||||
|
switch (tolower(input)) {
|
||||||
|
case 'n':
|
||||||
|
addBlock(r, NORTH, targetCell, &s);
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
addBlock(r, SOUTH, targetCell, &s);
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
addBlock(r, EAST, targetCell, &s);
|
||||||
|
break;
|
||||||
|
case 'w':
|
||||||
|
addBlock(r, WEST, targetCell, &s);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stack_free(&s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addBlock(robot r, direction dir, cell targetCell, stack *s) {
|
||||||
|
cell block;
|
||||||
|
cell_add(&block, r.pos, neighbours[dir]);
|
||||||
|
unexpanded_matrix[block.x][block.y] = -2; // putting -2 makes it not work???
|
||||||
|
if (!validatePath(r, *s)) {
|
||||||
|
stack_reinit(s);
|
||||||
|
lee_run(r, targetCell, s);
|
||||||
|
}
|
||||||
|
}
|
||||||
110
robot/simulator-moves.c
Normal file
110
robot/simulator-moves.c
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
//
|
||||||
|
// Created by nano on 5/14/25.
|
||||||
|
//
|
||||||
|
// Functies om de richting aan te passen
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "robot.h"
|
||||||
|
#include "../lee-algorithm/lee-algorithm.h"
|
||||||
|
|
||||||
|
//Dummy moves for the simulator / when a machine with libserialport is unavailable.
|
||||||
|
|
||||||
|
extern cell neighbours[4];
|
||||||
|
//extern cell crossing_neighbours[4];
|
||||||
|
|
||||||
|
char *moves[100];
|
||||||
|
int indx;
|
||||||
|
|
||||||
|
void turnLeft(robot *r) {
|
||||||
|
r->dir = (r->dir + 3) % 4;
|
||||||
|
moves[indx] = "\33[1;102mL\33[0m";
|
||||||
|
indx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void turnRight(robot *r) {
|
||||||
|
r->dir = (r->dir + 1) % 4;
|
||||||
|
moves[indx] = "\33[1;101mR\33[0m";
|
||||||
|
indx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void turnAround(robot *r) {
|
||||||
|
r->dir = (r->dir + 2) % 4;
|
||||||
|
moves[indx] = "\33[1;103mS\33[0m";
|
||||||
|
indx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void forward(robot *r) {
|
||||||
|
cell_add(&r->pos, r->pos, neighbours[r->dir]);
|
||||||
|
moves[indx] = "\33[1;105mF\33[0m";
|
||||||
|
indx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void backward(robot *r) {
|
||||||
|
cell_add(&r->pos, r->pos, neighbours[(r->dir + 2) % 4]);
|
||||||
|
moves[indx] = "\33[1;44mB\33[0m";
|
||||||
|
indx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int followPath_with_blockages(robot *r, stack *path,int visited[MAZE_SIZE][MAZE_SIZE]) {
|
||||||
|
while (path->length > 0) {
|
||||||
|
cell current_move = stack_pop(path);
|
||||||
|
int result = move(r,current_move);
|
||||||
|
visited[r->pos.x][r->pos.y] = 5;
|
||||||
|
printMatrix_with_current_pos(visited,*r);
|
||||||
|
if (isValidCrossing(r->pos)) {
|
||||||
|
printf("ADD BLOCKAGE? (Y/N) ");
|
||||||
|
char input[10];
|
||||||
|
scanf("%s", input);
|
||||||
|
printf("\n");
|
||||||
|
if (tolower(input[0]) == 'y' ){
|
||||||
|
printf("HOW FAR? (1-4) ");
|
||||||
|
int len;
|
||||||
|
scanf("%d",&len);
|
||||||
|
printf("\n");
|
||||||
|
len=(len-1)*2+1;
|
||||||
|
register_sensor_blockages(r,len,visited);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (result == 0) {
|
||||||
|
move(r,current_move);
|
||||||
|
visited[r->pos.x][r->pos.y] = 5;
|
||||||
|
printMatrix_with_current_pos(visited,*r);
|
||||||
|
if (isValidCrossing(r->pos)) {
|
||||||
|
printf("ADD BLOCKAGE? (Y/N) ");
|
||||||
|
char input[10];
|
||||||
|
scanf("%s", input);
|
||||||
|
printf("\n");
|
||||||
|
if (tolower(input[0]) == 'y' ){
|
||||||
|
printf("HOW FAR? (1-4) ");
|
||||||
|
int len;
|
||||||
|
scanf("%d",&len);
|
||||||
|
printf("\n");
|
||||||
|
len=(len-1)*2+1;
|
||||||
|
register_sensor_blockages(r,len,visited);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void printAllMoves() {
|
||||||
|
printf("\n");
|
||||||
|
for (int i = 0; i < indx; i++) {
|
||||||
|
printf("%s",moves[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void parkBackwards(robot *r) {
|
||||||
|
backward(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
void comm_discard_sensor_data(int timeout){}
|
||||||
|
void comm_await_crossing(){}
|
||||||
|
void comm_init_communication(){}
|
||||||
|
void comm_end_communication(){}
|
||||||
83
stack/stack.c
Normal file
83
stack/stack.c
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
//
|
||||||
|
// Created by nano on 4/30/25.
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "stack.h"
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
void stack_init(stack *stack) {
|
||||||
|
stack -> length = 0;
|
||||||
|
stack -> size = 1;
|
||||||
|
stack -> data = calloc(stack->size,sizeof(cell));
|
||||||
|
}
|
||||||
|
|
||||||
|
void stack_free(stack *stack) {
|
||||||
|
free(stack -> data);
|
||||||
|
stack->size = 0;
|
||||||
|
stack->length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void stack_reinit(stack *stack) {
|
||||||
|
stack_free(stack);
|
||||||
|
stack_init(stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
void stack_expand(stack *stack) {
|
||||||
|
stack -> size = stack -> size *2;
|
||||||
|
cell *new_data = calloc(stack -> size ,sizeof(cell));
|
||||||
|
memcpy(new_data, stack -> data, stack -> size/2 * sizeof(cell));
|
||||||
|
free(stack -> data);
|
||||||
|
stack -> data = new_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void stack_push(stack *stack, cell c) {
|
||||||
|
if (stack -> length + 1 == stack -> size) {
|
||||||
|
stack_expand(stack);
|
||||||
|
}
|
||||||
|
stack -> data[stack -> length++] = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
void stack_shrink(stack *stack) {
|
||||||
|
stack -> size = stack -> size / 2;
|
||||||
|
cell *new_data = calloc(stack -> size , sizeof(cell));
|
||||||
|
memcpy(new_data, stack -> data, stack -> size * sizeof(cell));
|
||||||
|
free(stack -> data);
|
||||||
|
stack -> data = new_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
cell stack_pop(stack *stack) {
|
||||||
|
if (stack -> length > 0) {
|
||||||
|
const cell c = stack -> data[stack -> length - 1];
|
||||||
|
if ((stack->length - 1) == (stack->size / 2) && stack -> size/2 !=0) {
|
||||||
|
stack_shrink(stack);
|
||||||
|
}
|
||||||
|
stack -> length--;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
return (cell) {INT_MAX,INT_MAX};
|
||||||
|
}
|
||||||
|
|
||||||
|
void stack_invert(stack *stack) {
|
||||||
|
cell *inv_data = calloc(stack -> size , sizeof(cell));
|
||||||
|
for (int i=0;i<stack->length;i++)
|
||||||
|
inv_data[stack->length -1 - i] = stack->data[i];
|
||||||
|
free(stack -> data);
|
||||||
|
stack -> data = inv_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void stack_append(const stack *from, stack *to) {
|
||||||
|
const int size = (int) pow(2, ceil(log2(to->length + from->length)));
|
||||||
|
// power of 2 which has enough space to hold all the contents of both stacks.
|
||||||
|
cell *new_data = calloc(size,sizeof(cell));
|
||||||
|
memcpy(new_data, to->data, to->length * sizeof(cell));
|
||||||
|
memcpy(new_data+to->length, from -> data, from -> length * sizeof(cell));
|
||||||
|
free(to->data);
|
||||||
|
to->data = new_data;
|
||||||
|
to->length = to->length + from -> length;
|
||||||
|
to->size = size;
|
||||||
|
}
|
||||||
26
stack/stack.h
Normal file
26
stack/stack.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
//
|
||||||
|
// Created by nano on 4/30/25.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef STACK_H
|
||||||
|
#define STACK_H
|
||||||
|
|
||||||
|
#include "../cell/cell.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct stack {
|
||||||
|
cell *data;
|
||||||
|
int length;
|
||||||
|
int size;
|
||||||
|
} stack;
|
||||||
|
|
||||||
|
void stack_init(stack *stack) ;
|
||||||
|
void stack_free(stack *stack) ;
|
||||||
|
void stack_reinit(stack *stack);
|
||||||
|
|
||||||
|
void stack_push(stack *stack, cell c) ;
|
||||||
|
cell stack_pop(stack *stack) ;
|
||||||
|
void stack_invert(stack *stack);
|
||||||
|
void stack_append(const stack *from, stack *to);
|
||||||
|
|
||||||
|
#endif //STACK_H
|
||||||
56
stack/stack_test.c
Normal file
56
stack/stack_test.c
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
//
|
||||||
|
// Created by nano on 4/30/25.
|
||||||
|
//
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "stack.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Quick file to test all functions of the implemented stack.
|
||||||
|
*/
|
||||||
|
int main(void){
|
||||||
|
int ret =1;
|
||||||
|
stack stk;
|
||||||
|
stack_init(&stk);
|
||||||
|
|
||||||
|
BEGIN:
|
||||||
|
for (int i=0;i<=100;i++) {
|
||||||
|
cell c;
|
||||||
|
c.x = i;
|
||||||
|
c.y = 100-i;
|
||||||
|
stack_push(&stk, c);
|
||||||
|
printf("pushed: %d,%d\n",c.x,c.y);
|
||||||
|
}
|
||||||
|
stack_invert(&stk);
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
printf("2nd run \n");
|
||||||
|
ret=0;
|
||||||
|
stack_reinit(&stk);
|
||||||
|
goto BEGIN;
|
||||||
|
}
|
||||||
|
stack_free(&stk);
|
||||||
|
|
||||||
|
printf("Append Test \n");
|
||||||
|
stack s1,s2;
|
||||||
|
stack_init(&s1);
|
||||||
|
stack_init(&s2);
|
||||||
|
for (int i=0;i<100;i++) {
|
||||||
|
stack_push(&s1,(cell){i,i});
|
||||||
|
stack_push(&s2,(cell){i,i});
|
||||||
|
}
|
||||||
|
for (int i=0;i<80;i++) {
|
||||||
|
stack_pop(&s1);
|
||||||
|
}
|
||||||
|
printf("s1 size: %d, s1 len: %d \ns2 size: %d, s2 len: %d \n",s1.size,s1.length,s2.size,s2.length);
|
||||||
|
stack_append(&s1,&s2);
|
||||||
|
printf("s2 size: %d, s2 len: %d \n",s2.size,s2.length);
|
||||||
|
while (s2.length) {
|
||||||
|
cell c = stack_pop(&s2);
|
||||||
|
printf("popped: %d,%d\n", c.x,c.y);
|
||||||
|
}
|
||||||
|
stack_free(&s1);
|
||||||
|
stack_free(&s2);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
20
todo.md
Normal file
20
todo.md
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# TODO
|
||||||
|
|
||||||
|
- [x] implement direction
|
||||||
|
- [x] make lee alg prefer straight line moves over turns (involves direction i would say)
|
||||||
|
- [x] make the code output a set of instructions for the robot.
|
||||||
|
- [x] replace the stuff in main.c with an "emulator" that will behave like the robot, so we can test without being
|
||||||
|
forced to have the robot connected at all times.
|
||||||
|
- [x] think of strategies for the different challenges
|
||||||
|
- [x] implement and optimize said strategies
|
||||||
|
- [x] test all challenges
|
||||||
|
|
||||||
|
### Instructions for the robot are gonna be like:
|
||||||
|
|
||||||
|
- Forward x
|
||||||
|
- Spin left x
|
||||||
|
- spin right x
|
||||||
|
- 180 deg turn x
|
||||||
|
- backward x
|
||||||
|
- (any other moves we can implement on the robot to make it faster)
|
||||||
|
- spin might have to be a routine because of the placement of the sensor ?
|
||||||
Loading…
x
Reference in New Issue
Block a user