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