Real Time Computing
Computing the positions of an object in real time presents many challenges, since there are many sources of delays that needs to be accounted for: receiving data, making calculation, etc. For this project we needed to use 3 different methods of calculating an integral. One would provide an over-estimation, an other an under-estimation, and the 3rd one somewhere in the middle. On top of those, I've created a 4th method that would intentionally be wrong.
Since the 3rd method provides the most accurate result, all the other methods corrects themselves with its value, if and only if all 3 accurate methods are within a 0.005m margin. If we are over that margin we use the solution computed by the over-estimation method.
The reason for the correction is to save time and to avoid the gap between the over-estimation and under-estimation to widen over time. We save time because we shorten the integral that needs to be calculated by using the Sum Rule: the limit of a sum equals the sum of the limits.
NB: To make the project more challenging and fun for myself I created a Server – Client relationship. Please contact me if you would like a copy of the full code.
Code
/*Chiasson-St-Coeur Simon
* serveur.cpp
*/
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <netdb.h>
#include <unistd.h>
#include <stdlib.h>
#include <iostream>
#include "integrale.h"
#define PORT_NUM 1670
#define MAX_LISTEN 5
using namespace std;
//Variables Globales
char out_buf[100];
char in_buf[100];
unsigned int server_s = 0;
pthread_t threads[10];
struct sockaddr_in server_addr;
unsigned int client_s;
struct sockaddr_in client_addr;
struct in_addr client_ip_addr;
unsigned int addr_len;
int *ptr[10];
//Signature des fonctions
void *fonc(void *);
class Prog
//La classe abstraite que les 4 programmes vont suivre.
{
private:
float table_Val[50];
short curr;
public:
Prog() {curr = 0;};
~Prog(){};
void set_Resultat(float valeur)
//L'integrale d'une somme est la somme des integrales, nous utilisons les anciens
//resultats pour calculer le resultat courant.
{
if(curr != 0)
table_Val[curr++] = table_Val[curr-1] + valeur;
else
table_Val[curr++] = valeur;
}
void corr_Resultat(float valeur)
//Si une correction doit avoir lieu, cette fonction est apelle
{
if(curr != 0)
table_Val[curr-1] = valeur;
else
table_Val[curr] = valeur;
}
int get_curr()
{
return curr;
}
void inc_curseur()
{
curr++;
}
float get_Val()
//get_Val() par default, puisque le curseur est incremente lorsqu'on ajoute un resultat, get_Val()
//donne valeur de la case precedente.
{
return table_Val[curr-1];
}
float get_Val(int pos)
{
return table_Val[pos];
}
};//Prog
class Prog1: public Prog
//Le 1er programme fait une sous-estimation en utilisant les sommes de Reimann
{
public:
Prog1() {};
~Prog1(){};
float sous_estimation(int debut, int fin, Graphe &graphe)
{
float resultat = 0;
for(int i = debut; i < fin; i++)
resultat = resultat + (graphe.get_Point(i, 1) * 0.1);
set_Resultat(resultat);
return get_Val();
}
};//Prog1
class Prog2 : public Prog
//Le 2ieme programme fait une sur-estimation en utilisant les sommes de Reimann
{
public:
Prog2() {};
~Prog2(){};
float sur_estimation(int debut,int fin, Graphe &graphe)
{
float resultat = 0;
for(int i = debut + 1; i <= fin; i++)
resultat = resultat + (graphe.get_Point(i, 1) * 0.1);
set_Resultat(resultat);
return get_Val();
}
};//Prog2
class Prog3 : public Prog
//Le 3ieme programme fait une estimation en utilisant la methode de trapeze
{
public:
Prog3() {};
~Prog3(){};
float trapeze(int min, int max, Graphe &graphe)
{
float resultat = graphe.get_Point(min, 1) + graphe.get_Point(max, 1);
float delta = (((max-min)*0.1)/(max-min))/2;
for(int i = min + 1; i < max; i++)
resultat = resultat + 2*(graphe.get_Point(i, 1));
set_Resultat(delta*resultat);
return get_Val();
}
};//Prog3
class ProgErr : public Prog
//Programme avec une erreur, on ajoute 0,03m au resultat.
{
public:
ProgErr(){};
~ProgErr(){};
float trapezeErr(int min, int max, Graphe &graphe)
{
float resultat = graphe.get_Point(min, 1) + graphe.get_Point(max, 1);
float delta = (((max-min)*0.1)/(max-min))/2;
for(int i = min + 1; i < max; i++)
resultat = resultat + 2*(graphe.get_Point(i, 1));
set_Resultat(delta*resultat+0.03);
return get_Val();
}
void affiche_vals()
{ cout << "Valeurs enregistre de ProgErr:\n";
for(int i = 0; i < get_curr(); i++)
cout << get_Val(i) << endl;
}
};
int main()
{
pthread_setconcurrency(4);
server_s = socket(AF_INET, SOCK_STREAM, 0);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT_NUM);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(server_s, (struct sockaddr *)&server_addr, sizeof(server_addr));
listen(server_s, MAX_LISTEN);
while (1) {
addr_len = sizeof(client_addr);
client_s = accept(server_s, (struct sockaddr *)&client_addr, &addr_len);
pthread_create(&threads[client_s-4], NULL, fonc ,&client_s);
}
pthread_join(threads[client_s-4],(void **)&(ptr[client_s-4]));
close(server_s);
return 0;
}//main()
void *fonc(void *arg)
{
int socketClient = * (int *) arg;
float valeur;
int i = 0;
Graphe integrale;
Prog1 prog1;
Prog2 prog2;
Prog3 prog3;
ProgErr prog3_err;
srand(time(NULL));
//On envoie au serveur abcde pour confirmer que la connection est bien etablie
//et que nous sommes prets a recevoir les donnees
sleep(1);
strcpy(out_buf, "abcde");
cout << out_buf <<endl;
send(socketClient, out_buf, (strlen(out_buf)+1), 0);
printf("Sent\n");
recv(socketClient, in_buf, sizeof(in_buf), 0);
cout << in_buf << endl;
while(in_buf[0] != 'f')
{
valeur = float(atof(in_buf));
integrale.place_Point(i++, 1, valeur);
//Envoi au client qu'on a recu et enregistre la valeur, alors on est pret pour recevoir la prochaine
strcpy(out_buf, "go");
send(socketClient, out_buf, (strlen(out_buf)+1), 0);
recv(socketClient, in_buf, sizeof(in_buf), 0);
}//while
integrale.afficher_Graphe();
for(int j = 10; j < 150; j += 10)
{
prog1.sous_estimation(j-10, j, integrale);
prog2.sur_estimation(j-10, j, integrale);
prog3.trapeze(j-10, j, integrale);
prog3_err.trapezeErr(j-10, j, integrale);
cout << "Iteration " << j/10 << endl << "Valeur de la sous-estimation: " << prog1.get_Val() <<
"\nValeur de la sur-estimation: " << prog2.get_Val() <<
"\nValeur de la methode trapeze: " << prog3.get_Val() << endl;
prog3_err.affiche_vals();
cout << endl;
//Corrections des valeurs s'il y a lieu, la marge est de 0.5cm.
//Si toutes les resultats sont dans cette marge, alors prog1 et prog2 corriges leurs
//valeurs avec celle obtenue par prog3, c-a-d, selon la methode trapeze
if(abs(prog1.get_Val() - prog3.get_Val()) > 0.005){
prog1.corr_Resultat(prog2.get_Val());
prog3.corr_Resultat(prog2.get_Val());
}
else{
prog1.corr_Resultat(prog3.get_Val());
prog2.corr_Resultat(prog3.get_Val());
}
if(abs(prog1.get_Val() - prog3_err.get_Val()) > 0.005){
prog1.corr_Resultat(prog2.get_Val());
prog3_err.corr_Resultat(prog2.get_Val());
}
//Sleep pour simuler un deplacement par seconde.
sleep(1);
}//for
return NULL;
}//fonc