Programme de commande [Langage C]
Répondre à la discussion
Affichage des résultats 1 à 7 sur 7

Programme de commande [Langage C]



  1. #1
    invitefef498b4

    Programme de commande [Langage C]


    ------

    Bonjour à tous,
    je réalise avec un ami un programme de commande de robot à distance avec une interface PC.

    Pour cela, je me suis basé sur le cours de la programmation en C de matéo sur le sdz ainsi que le cours sur les sockets de Zephyr.
    Dans l'attente de la réception de ma carte wi-fi qui ira sur le robot, je voudrais savoir si mon code marche, au moins sur le principe. Je m'explique :

    On a une fenêtre en SDL avec un "mode d'emploi", la commande s'effectue au moyen des touches sur le clavier. (c'est la partie de mon ami). Je me suis occupé de la partie socket. Avec l'utilisation de thread, je lance ma partie de programme (qui sert a envoyer les variables) en continue, l'utilisateur n'aura plus qu'a taper sur le clavier pour commander le robot.
    En théorie, cela devrait marcher mais je ne sais pas s'il se lancera correctement.

    Autre problème : Le programme devrait se quitter en cliquant sur un bouton quitter, mais il se trouve que si on clique (n'importe ou) sur la fenêtre, le programme quitte. Nous avons essayer de changer le code en changeant les évènements pour que ça quitte mais apparament, le compilateur ne veut pas compiler (erreur : duplicate value) => On utilise deux fois SDL_BUTTON_LEFT.

    Dans l'attente d'une réponse rassurante, merci d'avance !

    Code source (PS : la structure ne sert à rien)

    Partie SDL :


    Code:
    /*
    Programme Commande
    Par Busy Maxime, réalisée dans le cadre du PPE (Projet Pluritechnique encadré)
    au lycée Saint François d'Assise
    */
    
    
    #include <stdlib.h>           
    #include <stdio.h>            
    #include <SDL/SDL.h>           
    #include "structures.h"         
    #include <winsock2.h>          
    #include <pthread.h>           
    
    
    
    void* envoie_de_donnees(void* data);        
    
    
    int main() // fonction main
    {
    
        pthread_t thread;  
    
        pthread_create(&thread, NULL, envoie_de_donnees, NULL);
    
    
    SDL_Surface *ecran = NULL;      
    SDL_Surface *rectangle = NULL;  // premier rectangle, pour informations livréées par les capteurs, en haut a gauche de la fenetre
    SDL_Surface *rectangle_second = NULL; // second rectangle, idem que le premier mais juste en dessous, meme role
    SDL_Surface *rectangle_controleboutonsouris = NULL; // troisieme rectangle en bas, tres large, pour commande du drone grace a la souris en cliquant sur les boutons
    SDL_Surface *rectangle_video = NULL;     // quatrieme rectangle, rectangle video
    SDL_Surface *rectangle_quitter = NULL;      // rectangle permettant de quitter le programme
    
    
    
    int stop_wifi = 0;              // cette variable permetra, si elle passe a 1, de couper la liaison wifi
    int start_reprise_wifi = 1;     // cette variable permetra, si laliaison wifi est coupée et si elle passe a 1, de retablir la liaison wifi
    int continuer = 1 ;             // variable permettant de "mettre en pause la fenetre", et d'arreter le programme si elle passe a 0
    VariablesPobBot PobBot ;        // on fait appelle a la structure variables PobBot du header
    
    
    SDL_Event event ;                        //on met en place les evenements
    SDL_Rect position ;                             // mise en place du repere
    
    SDL_Init (SDL_INIT_VIDEO);                      // declaration d'ouverture de la fenetre
    
    
    SDL_SetVideoMode(1250, 780, 32, SDL_HWSURFACE );                // reglage de la fenetre a ouvrir
    ecran = SDL_SetVideoMode (1250, 780, 32, SDL_HWSURFACE );       // on fait correspondre l'ecran a la fenetre a ouvrir
    SDL_WM_SetCaption ("commande du pob bot", NULL);                // permet de definir le titre de la fenetre
    SDL_FillRect (ecran, NULL, SDL_MapRGB (ecran-> format, 160, 157, 156));     // couleur de la surface, ici, l'ecran
    
    
    
    rectangle = SDL_CreateRGBSurface (SDL_HWSURFACE, 310, 60, 32, 0, 0, 0, 0);  // on cree une surface, on la fait correspondre a rectangle
    position.x = 900;                           // on definit l'abcisse de la surface
    position.y = 150;                           // puis on definit son ordonée
    SDL_FillRect (rectangle, NULL, SDL_MapRGB (rectangle->format, 226, 226, 226));      // couleur de la surface, ici, rectangle
    SDL_BlitSurface (rectangle, NULL, ecran, &position);                   // on "blitte" la surface, cela permet en quelque sorte de la fixer sur l'ecran
    
    
    
    
    rectangle_second = SDL_CreateRGBSurface (SDL_HWSURFACE, 310, 60, 32, 0, 0, 0, 0);  //on repete la meme operation en changeant certains parametres pour le second rectangle
    position.x = 900;
    position.y = 300;
    SDL_FillRect(rectangle_second, NULL, SDL_MapRGB(rectangle_second->format, 226, 226, 226));
    SDL_BlitSurface (rectangle_second, NULL, ecran, &position);
    
    
    
    
    
    rectangle_controleboutonsouris = SDL_LoadBMP("clavier.bmp");           // on fait correspondre l'image clavier.bmp a la variable rectangle_controleboutonsouris
    position.x = 130;                                                       // on donne l'abcisse de l'image
    position.y = 500;                                                       // on donne l'ordonnée de l'image
    SDL_BlitSurface (rectangle_controleboutonsouris, NULL, ecran, &position);       // on "blitte", on fixe la surface sur l'ecran
    
    
    
    rectangle_quitter = SDL_LoadBMP("rectagle_green.bmp");
    position.x =950;
    position.y =-50;
    SDL_SetColorKey (rectangle_quitter, SDL_SRCCOLORKEY, SDL_MapRGB(rectangle_quitter-> format,255,255,255));
    SDL_BlitSurface (rectangle_quitter, NULL, ecran, &position);
    
    
    
    
    rectangle_video = SDL_CreateRGBSurface (SDL_HWSURFACE, 750, 400, 32, 0,0,0,0);   // rectangle temporaire, a remplacer par la video vue 1ere personne du drone
    position.x = 130 ;
    position.y = 70 ;
    SDL_FillRect (rectangle_video, NULL, SDL_MapRGB(rectangle_video->format,0,0,0));
    SDL_BlitSurface (rectangle_video, NULL, ecran, &position);
    
     SDL_Flip (ecran);  // cette fonction sert a "rafraichir", actualiser une surface, ici l'ecran
    
    
    while (continuer)               // boucle qui se repetera tant que la variable booléenne "continuer" sera egale a 1, et donc vraie. si continuer =0, le programme s'arrete
    {
        SDL_WaitEvent(&event);     //fonction permettant de reperer les evenements
        switch (event.type)        // la fonction test le type d'evenement
        {
            case SDL_QUIT :         // si cet evenement est de type "quitter", alors...
            continuer = 0 ;         // ...on met continuer à 0 et le programme s'arrete
            break;
            case SDL_KEYDOWN :              // si il est de type touche enfoncée...
            switch (event.key.keysym.sym)   // ...la fonction regarde quelles touches sont enfoncées
            {
    
                case SDLK_ESCAPE :          // si on appui sur escape...
                continuer = 0;              // on met continuer à 0, le programme s'arrete
                break;
    
                case SDLK_BACKSPACE :               // si on appui sur retour arriere,...
                start_reprise_wifi = 0;      // on coupe la liaison wifi
                stop_wifi = 1;
                break;
    
                case SDLK_RETURN :
                stop_wifi = 0;               // si on appui sur enter,...
                start_reprise_wifi = 1;      // on retablit la liaison wifi
                break;
    
                case SDLK_UP :              // si on presse la fleche haut (clavier) ...
                PobBot.mouvement_pob_bot = 1;          // la variable booléenne "avance" de type VariablesPobBot vaut 1, le drone avance
                break;
    
                case SDLK_DOWN :            // de meme, si on presse la fleche  bas,...
                PobBot.mouvement_pob_bot = 2;          // le drone recule
                break;
    
                case SDLK_RIGHT :           // si on presse la fleche droite,...
                PobBot.mouvement_pob_bot = 3;   // le drone tourne à droite
                break;
    
                case SDLK_LEFT :            // si on presse la fleche gauche,...
                PobBot.mouvement_pob_bot = 4;   // le drone tourne à guauche
                break;
    
                case SDLK_a :               // si on presse a,...
                PobBot.mouvement_pob_bot = 5;        // la pince s'eleve
                break;
    
                case SDLK_q :               // si on presse q,...
                PobBot.mouvement_pob_bot = 6;      // la pince s'abaisse
                break;
    
                case SDLK_LCTRL :           // si on presse le bouton controle (ctrl) LE PLUS A GAUCHE du clavier,...
                PobBot.mouvement_pob_bot = 7;  // la pince est fermée
                break;
    
                case SDLK_LALT :            // si on presse le bouton alt LE PLUS A GAUCHE du clavier,...
                PobBot.mouvement_pob_bot = 8; // la pince est ouverte
                break;
    
            }
        break;
    
        case SDL_KEYUP :                    // si l'evenement est de type touche relachée :
        switch (event.key.keysym.sym)
        {
            case SDLK_UP :                  // si on relache la fleche haut,...
            PobBot.mouvement_pob_bot = 0;              // le drone arrete d'avancer
            break;
    
            case SDLK_DOWN :                // si on relache la fleche bas,...
            PobBot.mouvement_pob_bot = 0;              // le drone arrete de reculer
            break;
    
            case SDLK_RIGHT :               // si on relache la fleche droite,...
            PobBot.mouvement_pob_bot = 0;       // le drone arrete de tourner a droite
            break;
    
            case SDLK_LEFT :                // si on relache la fleche gauche,...
            PobBot.mouvement_pob_bot = 0;       // le drone arrete de tourner a gauche
            break;
    
            case SDLK_a :                   //si on relache la touche a,...
            PobBot.mouvement_pob_bot = 0;            // la pince arrete de s'elever
            break;
    
            case SDLK_q :                   // si on relache la touche q,...
            PobBot.mouvement_pob_bot = 0;          // la pince arrete de s'abaisser
            break;
        }
       break;
    
    
    case SDL_MOUSEBUTTONUP  :
    if (950 < event.button.x < 1200 &&  -50 < event.button.y < 100)
    continuer = 0;
    else
    continuer = 1;
    
    
    break;
      }
      }                                 // fin de la boucle while(continuer)
    
    SDL_FreeSurface (rectangle);            // on libere la surface allouée pour "rectangle"
    SDL_FreeSurface (rectangle_second);     // on libere la surface allouée pour "rectangle_second"
    SDL_FreeSurface (rectangle_controleboutonsouris);   // on libere la surface allouée pour "rectangle_controleboutonsouris"
    SDL_FreeSurface (rectangle_quitter);
    SDL_FreeSurface (rectangle_video);
    SDL_Quit ();         // on libere la sdl de la memoire
    
            pthread_join(thread, NULL); //Fin du thread
    
    
        return EXIT_SUCCESS;    // tout s'est correctement déroulé, on revoie un EXIT_SUCCESS
    }



    Partie socket :


    Code:
    /*
    Programme Envoie de données
    Par Yu David, réalisée dans le cadre du PPE (Projet Pluritechnique encadré)
    au lycée Saint François d'Assise
    */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>             // Inclusion de la librairie String.h, nécessaire a l'utilisation des chaines de charactères
    #include <pthread.h>            // Inclusion de la librairie prthread.h, nécessaire pour utiliser les threads
    
    #define PORT 8000
    
    #if defined (WIN32)             // Si le système d'exploitation (OS) est Windows
        #include <winsock2.h>
        typedef int socklen_t;
    #elif defined (linux)           // Si le système d'exploitation (OS) est Linux
        #include <sys/types.h>
        #include <sys/socket.h>
        #include <netinet/in.h>
        #include <arpa/inet.h>
        #include <unistd.h>
        #define INVALID_SOCKET -1
        #define SOCKET_ERROR -1
        #define closesocket(s) close(s)
        typedef int SOCKET;
        typedef struct sockaddr_in SOCKADDR_IN;
        typedef struct sockaddr SOCKADDR;
    #endif
    
    
    void* envoie_de_donnees()         // Fonction envoie_de_donnes qui sera exécuter dés le début du programme "Commande"
    {
        #if defined (WIN32)
        WSADATA WSAData;            // Initialisation de la bibliothèque Winsock
        int erreur = WSAStartup(MAKEWORD(2,2), &WSAData);       // Transformation de deux entiers d'un octet en un seul entier de 2 octet
        #else
            int erreur = 0;
        #endif
    
        /* Code Socket Début */
    
        SOCKET sock;                // déclaration d'une socket : sock
        SOCKADDR_IN sin;            // paramétrage d'une socket : sock
        SOCKET csock;               // déclaration d'une socket : csock
        SOCKADDR_IN csin;           // paramétrage d'une socket : csock
    
        char  PobBot.mouvement_pob_bot [100];   // Initialisation du tableau de valeur a 100 cases
    
        socklen_t recsize = sizeof (csin);
        int sock_err;                           // Initialisation et déclaration de la variable sock_err
    
    
    if(!erreur)
        {
    
            sock = socket(AF_INET, SOCK_STREAM, 0);         // Création d'une socket
    
    
            if(sock != INVALID_SOCKET)          // Si la socket marche correctement
            {
                printf("La socket %d est maintenant ouverte en mode TCP/IP\n", sock);
    
    
                /* Configuration */
                sin.sin_addr.s_addr = htonl(INADDR_ANY);  // Adresse IP automatique
                sin.sin_family = AF_INET;                 
                sin.sin_port = htons(PORT);              
                sock_err = bind(sock, (SOCKADDR*)&sin, recsize);    
    
    
                if(sock_err != SOCKET_ERROR)       
                {
    
                    sock_err = listen(sock, 5);           
                    printf("Listage du port %d...\n", PORT);
    
    
                    if(sock_err != SOCKET_ERROR)          
                    {
                    
                        printf("Patientez pendant que le client se connecte sur le port %d...\n\n", PORT);
                        csock = accept(sock, (SOCKADDR*)&csin, &recsize); // fonction accept
                        printf("Un client se connecte avec la socket %d de %s:%d\n\n", csock, inet_ntoa(csin.sin_addr), htons(csin.sin_port));
                        sock_err = send (csock,  PobBot.mouvement_pob_bot, 32, 0);      "PobBot.mouvement_pob_bot au POB
    
                        if(sock_err != SOCKET_ERROR)        
                            printf("Chaine envoyee : %d\n\n",  PobBot.mouvement_pob_bot);
                        else
                            printf("Erreur de transmition\n");
    
                            shutdown(csock, 2);
                    }
                    else
                        perror("listen");
                }
                else
                    perror("bind");
    
              
    
                printf("Fermeture de la socket client\n");
                closesocket(csock);
    
                printf("Fermeture de la socket serveur\n");
                closesocket(sock);
    
                printf("Fermeture du serveur terminee\n\n");
            }
            else
                perror("socket");
    
    
      <code type="c">  
    
        #if defined (WIN32)
        WSACleanup();           
        }
    
    }</code>

    Si vous souhaitez, je peux vous envoyer le zip avec les images pour que vous voyez a peu près la tête du programme.


    -----
    Dernière modification par JPL ; 30/03/2011 à 15h50. Motif: Ajout de la balise Code

  2. #2
    lou_ibmix_xi

    Re : Programme de commande [Language C]

    C'est inutile de poster un code aussi long, surtout sans les balises codes....
    1ère remarque, le programme quitte lorsque tu cliques n'importe où dans la fenêtre, je pencherai plutôt pour un planton.
    2ème remarque, on avance par couche: je commencerai par faire une bibliothèque de gestion d'envoie des commandes, sans interface graphique, une fois que c'est validé, j'ajoute la partie graphique.
    Enfin, pour savoir si ton programme fonctionne comme prévu, tu fais un programme simulant le robot: tu pourrais par exemple afficher toutes les commandes reçues...
    Bon courage

  3. #3
    invitefef498b4

    Re : Programme de commande [Language C]

    Tout d'abord, merci de la réponse rapide.
    Il me semblait que j'avais mis des balises, visiblement sa n'a pas marché.
    Pour ce qui est du code, nous avons travailler en parallèle, il est vrai qu'il aurait sans doute tété préférable de commencer par une interface en console puis par rajouter le graphique, mais nous n'avons plus tellement le temps de recommencer.
    Je vais faire un programme client pour tester le programme, merci

  4. #4
    JPL
    Responsable des forums

    Re : Programme de commande [Langage C]

    Balises ajoutées.
    Rien ne sert de penser, il faut réfléchir avant - Pierre Dac

  5. A voir en vidéo sur Futura
  6. #5
    softelectro

    Re : Programme de commande [Langage C]

    salut

    Concernant le problème de gestion souris je pense que le problème via de ce morceau de code

    Code:
    case SDL_MOUSEBUTTONUP  :
    if (950 < event.button.x < 1200 &&  -50 < event.button.y < 100)
    je me trompe peut être mais le test de la double inégalité me parait imprévisible.
    je ferai plutôt un truc du genre, A optimiser et tester!

    Code:
    case SDL_MOUSEBUTTONUP  :
    x_mouse = event.button.x
    y_mouse = event.button.y
    if (950 < x_mouse && x_mouse < 1200 &&  -50 < y_mouse && y_mouse < 100)
    @+

  7. #6
    bzh_nicolas

    Re : Programme de commande [Langage C]

    C'est même certain que ton problème de souris vient de là, ta condition est toujours vrai (ce qui explique que l'appli quitte peu importe l'endroit ou tu cliques) :
    Le résultat d'une comparaison en C est 0 ou 1 donc en réalité tu fais :
    Code:
    950 < event.button.x
    vaut 0 ou 1
    ensuite ça donne soit :
    Code:
     0 < 1200
    ou :
    Code:
     1 < 1200
    Donc toujours vrai.
    P.S. d'ailleurs je ne savais même pas que ce genre de "double comparaison" était autorisée dans la syntaxe du C...
    Dernière modification par bzh_nicolas ; 01/04/2011 à 06h55.

  8. #7
    whoami

    Re : Programme de commande [Langage C]

    Bonjour,
    Citation Envoyé par bzh_nicolas Voir le message
    P.S. d'ailleurs je ne savais même pas que ce genre de "double comparaison" était autorisée dans la syntaxe du C...
    C'est autorisé, mais tout ce qui est autorisé n'est pas forcément très bon à utiliser, surtout pour la lisibilité du code.

    Un code "propre" aurait montré plus rapidement d'où vient le problème.

Discussions similaires

  1. Sous programme en langage C
    Par invite817c9d71 dans le forum Logiciel - Software - Open Source
    Réponses: 8
    Dernier message: 06/06/2010, 10h25
  2. programme langage C
    Par invite3ca1c29c dans le forum Logiciel - Software - Open Source
    Réponses: 4
    Dernier message: 23/11/2008, 12h19
  3. programme de correlation en langage assembleur
    Par invite54d71191 dans le forum Électronique
    Réponses: 9
    Dernier message: 12/05/2008, 21h17
  4. programme I2C en langage C
    Par invite7670cc44 dans le forum Électronique
    Réponses: 0
    Dernier message: 07/04/2008, 19h47
  5. Questions sur le langage de commande UNIX
    Par inviteb4fcae87 dans le forum Logiciel - Software - Open Source
    Réponses: 19
    Dernier message: 18/11/2007, 17h53