assert1

Dependencies:   mbed X_NUCLEO_IHM02A1

chemin.cpp

Committer:
JimmyAREM
Date:
2019-03-30
Revision:
3:06cbe2f6c494
Parent:
2:977799d72329

File content as of revision 3:06cbe2f6c494:

#include "mbed.h"
#include "chemin.h"
#include "terrain_precalc.h"
#include "odometrie.h"
#include "tests_moteurs.h"


/*
L'origine du terrain est
    y-----------------|
    |       |  |      |
    |  ¯¯¯¯¯¯¯¯¯¯¯¯¯  |
    |                 |
    0-----------------|> x

    Et l'origine des angles est de x vers y positif.
*/


// Function to Create A New Node
Node* newNode(int x, int y, int distance, int p)
{
    Node* temp = (Node*)malloc(sizeof(Node));
    temp->x = x;
    temp->y = y;
    temp->distance = distance;
    temp->priority = p;
    temp->next = NULL;

    return temp;
}

// Return the value at head
void peek(Node** head, int*x, int*y, int*distance)
{
    *x = (*head)->x;
    *y = (*head)->y;
    *distance = (*head)->distance;
}

// Removes the element with the
// highest priority form the list
void pop(Node** head)
{
    Node* temp = *head;
    (*head) = (*head)->next;
    free(temp);
}



// Function to push according to priority
void push(Node** head, int x, int y, int distance, int p)
{
    Node* start = (*head);

    // Create new Node
    Node* temp = newNode(x, y,distance, p);

    // Special Case: The head of list has lesser
    // priority than new node. So insert new
    // node before head node and change head node.
    if ((*head)->priority > p) {

        // Insert New Node before head
        temp->next = *head;
        (*head) = temp;
    } else {

        // Traverse the list and find a
        // position to insert new node
        while (start->next != NULL &&
                start->next->priority < p) {
            start = start->next;
        }

        // Either at the ends of the list
        // or at required position
        temp->next = start->next;
        start->next = temp;
    }
}

// Function to check is list is empty
int isEmpty(Node** head)
{
    return (*head) == NULL;
}


void calc_distances(int ox, int oy, int gx, int gy)
{
    //Calcule la distance de chaque point du terrain à l'objectif (gx,gy)
    //COmplexite en O(l*L)
    printf("ok\n");

    char visite[l][L] = {{0}}; //sauvegarde les points deja visites pour eviter de passer 2 fois dessus
    int voisins[9][9] = {{0,1}, {-1,0}, {1,0}, {0,-1}, {1,1}, {-1,1}, {1,-1}, {-1,-1} };    //voisin d'un point
    int distance = 0;
    int px = gx;
    int py = gy;
    visite[gx][gy] = 1;
    Node* pq = newNode(gx,gy,distance, 0);
    printf("ok2\n");
    while(!isEmpty(&pq)) { //Tant que l'on n'a pas parcouru tous les points TODO: optimiser pour arreter lorque (px,py) == (ox,oy) pour éviter de tout parcourir, sans que cela infule sur le choix du chemin

        peek(&pq,&px,&py,&distance);    //on recupere les infos du point
        distances[px][py] = distance;
        //printf("position tiree : %d , %d , de distance %d\n" , px,py,distance);


        for(int i=0; i<9; i++) {
            int vx = px+voisins[i][0];
            int vy = py+voisins[i][1];

            if( vx >= 0 && vx < l && vy >= 0 && vy < L && terrain[vx][vy] != 1 && visite[vx][vy] == 0) {
                //printf("positions ajoutee : %d,%d,%d\n" ,  vx, vy,distance );
                visite[vx][vy] = 1;
                push(&pq, vx, vy, distance+1,distance+1);  //on ajoute ses soivins s'ils sont dans le terrain, ne sont pas un mur, et n'ont pas été visités
            }
        }
        pop(&pq); //on peut le pop puisqu'il a été visité

    }
}

Node* trouver_chemin(int ox, int oy, int gx, int gy)
{
    //Trouve le meilleur chemin en se rapprochant de l'objectif
    //Complexité en longueur du chemin (MAX= L*l)
    int voisins[9][9] = {{0,1}, {-1,0}, {1,0}, {0,-1}, {1,1}, {-1,1}, {1,-1}, {-1,-1} };
    int distance = 0;
    Node* pq = newNode(ox,oy,distance, 0);
    int px = ox;
    int py = oy;

    while(!(px==gx && py==gy)) {
        distance++;
        unsigned long long dmin = L*l;
        int xmin = 0;
        int ymin = 0;
        for(int i=0; i<9; i++) {
            int vx = px+voisins[i][0];
            int vy = py+voisins[i][1];

            if( vx >= 0 && vx < l && vy >= 0 && vy < L && terrain[vx][vy] != 1 && distances[vx][vy] < dmin) {
                dmin = distances[vx][vy];
                xmin = vx;
                ymin = vy;
            }
        }
        //printf("position ajoutee chemin : %d , %d , de distance %d\n" , px,py,distance);
        push(&pq, xmin, ymin, distance,distance);
        px = xmin;
        py = ymin;

    }
    return pq;
}


Node* traduction_points_commandes(Node* pq)
{
    /*

    y_____________
    | 9   10   11|
    |            |
    | -1   R    1|
    |            |
    |-11  -10  -9|
    ¯¯¯¯¯¯¯¯¯¯¯¯¯x
         ||
         \/
    ___________
    | 4  3  2 |
    | 5  R  1 |
    | 6  7  8 |
    ¯¯¯¯¯¯¯¯¯¯¯
    */
    int i,px,py,distance,direction = 0;
    peek(&pq,&px,&py,&distance);    //on recupere les infos du point
    pop(&pq);
    Node* cmd = newNode(0,0,0,0);

    int px_new,py_new,direction_new,_ =0;


    while(!isEmpty(&pq)) {
        peek(&pq,&px_new,&py_new,&_);   //on recupere les infos du point
        pop(&pq);
        //printf("%d , %d , %d\n",px,py,px_new - px + 10*(py_new-py));
        switch(px_new - px + 10*(py_new-py)) {
            case 1:
                direction_new=1;
                distance+=100;
                break;
            case -1:
                direction_new=5;
                distance+=100;
                break;
            case 10:
                direction_new=3;
                distance+=100;
                break;
            case -10:
                direction_new=7;
                distance+=100;
                break;
            case 11:
                direction_new=2;
                distance+=141; //racine de 2, la diagonale d'un carré
                break;
            case 9:
                direction_new=4;
                distance+=141;
                break;
            case -9:
                direction_new=8;
                distance+=141;
                break;
            case -11:
                direction_new=6;
                distance+=141;
                break;
        }

        if(direction_new != direction) {
            if(direction ==0) {

                push(&cmd,(int) direction_new, 0, 0, i);

            } else {
                int a = direction-direction_new;
                if(direction == 8 && direction_new == 1) a = -1;
                if(direction == 1 && direction_new == 8) a = 1;
                printf("%d %d, %d,%d , %d \n", a, distance,direction, direction_new,(direction-direction_new));
                push(&cmd,(int) 45*a, distance, 0, i);
            }
            distance = 0;
            direction = direction_new;
            i++;
        }
        px = px_new;
        py = py_new;

    }
    printf("ok");
    i++;
    float a = (1+1)/(7-1);
    float b = 1-a*7;
    push(&cmd, 0, distance, 0,i);


    return cmd;

}

void afficher_terrain()
{
    //Affiche le terrain sur le port serie
    printf("Terrain avec murs: \n");
    for(int j=0; j<=L; j++) printf("_");
    printf("\n");
    for(int i = 0; i < l; i++) {
        printf("|");
        for(int j=0; j<L; j++) {

            if(terrain[i][j] ==0) {
                printf(" ");
            } else {
                printf(".");

            }
        }
        printf("|\n");
    }
    for(int j=0; j<=L; j++) printf("¯");
    printf("\n\n");
}


void afficher_terrain(Node* points)
{
    char terrain_tmp[l][L] = {{0}};
    for(int i = 0; i < l; i++) for(int j=0; j<L; j++) terrain_tmp[i][j] = terrain[i][j];

    int i,px,py,_ = 0;
    while(!isEmpty(&points)) {
        peek(&points,&px,&py,&_);   //on recupere les infos du point
        pop(&points);
        terrain_tmp[px][py] = 2;
    }

    //Affiche le terrain sur le port serie
    printf("Terrain avec murs: \n");
    for(int j=0; j<=L; j++) printf("_");
    printf("\n");
    for(int i = 0; i < l; i++) {
        printf("|");
        for(int j=0; j<L; j++) {

            if(terrain_tmp[i][j] ==0) {
                printf(" ");
            } else if(terrain_tmp[i][j] == 2) {
                printf("X");
            } else {
                printf(".");

            }
        }
        printf("|\n");
    }
    for(int j=0; j<=L; j++) printf("¯");
    printf("\n\n");
}

int conversion_codage_angles(int o)
{

    switch(o) {
        case 1:
            o = 0;
            break;
        case 2:
            o = 45;
            break;
        case 3:
            o = 90;
            break;
        case 4:
            o = 135;
            break;
        case 5:
            o = -180;
            break;
        case 6:
            o = -225;
            break;
        case 7:
            o = 270;
            break;
        case 8:
            o = 315;
            break;
    }
    return o;
}

void aller_a_point(int ox , int oy, int gx , int gy , int vitesse_deplacement){
    
    double angle_absolut = get_angle();

    calc_distances(ox,oy,gx,gy);
    Node* cm = (Node*)malloc(sizeof(Node)); 
    cm = traduction_points_commandes(trouver_chemin(ox,oy,gx,gy));
    
    //afficher_terrain(trouver_chemin(ox,oy,gx,gy));
    
    int o,d,_ = 0;
    pop(&cm);
    peek(&cm,&o,&d,&_);     //on recupere les infos de direction 
    pop(&cm);
    o = conversion_codage_angles(o);
    printf("rotation %d, avancement de %d\n",o,d);
    angle_absolut += o;
    
    //test_rotation_abs(o,100);
    wait(2);
    
    while(!isEmpty(&cm)){ 
        peek(&cm,&o,&d,&_);     //on recupere les infos de direction 
        pop(&cm);
        printf("rotation %d, avancement de %d\n",o,d);
        if(d != 0 && o != 0) {
            test_ligne_droite(10*d, -vitesse_deplacement);
            wait(2);
            angle_absolut += o;
            test_rotation_abs(angle_absolut,50);
            wait(2);
            }
    }
 }