Partenaires

CNRS
RESIF
DT
UNAVCO Facility

Rechercher

sur ce site

sur web cnrs


Accueil > Documentation technique > télécommunications > temps reel sur IP

temps reel sur IP

par Olivier Charade - 7 juillet 2008 - modifié le 22 octobre 2008

La transmission des corrections d’une station de base vers un récepteur mobile se fait traditionnellement sur une liaison série. Les récepteurs actuels permettent de le faire sur une liaison réseau. Cela simplifie beaucoup de questions matérielles (en particulier parce qu’un seul câble réseau peut servir àplusieurs communications simultanément) mais nécessite plus de connaissance des protocoles et outils réseau. Cet article propose une façon de faire passer les corrections sur IP sans utiliser les outils ntrip.

Il y a une différence essentielle entre la solution par liaison série et celle par liaison IP :

La liaison série a toujours été « point àpoint » alors que le protocole Ethernet considère que tout le monde parle sur le même support. Alors que la station de base peut diffuser ses corrections en continu sur un port série sans se soucier de savoir si quelqu’un écoute, il n’est pas question de polluer un réseau local avec des messages « diffusés àtous » (broadcast) pour satisfaire un hypothétique récepteur mobile qui écouterait sur ce réseau. Cela signifie qu’il faut venir se connecter sur la station de base pour qu’elle émette ses corrections vers son client.

Le fait de devoir se connecter au récepteur mobile pour lui envoyer les corrections semble plus naturel. Mais il apparaît alors clairement que, pour relier base et mobile, il faut une « tierce machine » qui lance la connexion vers les deux autres et les met ensuite en relation. L’objet de cet article est de donner des éléments pour arriver àcela sans trop de difficultés.

Si la connexion vers un récepteur Trimble NetRS ou NetR5 se fait facilement, celle vers un récepteur Topcon GB1000 est plus délicate car elle nécessite un login.

Le terme technique qui va revenir sans arrêt (et que je ne me vois traduire en Français) est « socket ». C’est un tuyau de communication bi-directionnel qui n’a besoin, pour être défini, que des adresses IP des machines àrelier et du numéro du port sur lequel il est connecté.

configuration de la station de base Trimble [1].

La première étape consiste àindiquer àla station quel type de message elle doit diffuser et sur quel port. Comme nous dialoguons avec un récepteur mobile de marque Topcon, nous ne pouvons utiliser le message RT17 propre àTrimble. Nous allons d’abord travailler avec le message standard CMR.

NetR5 I/O Configuration

Ici, notre NetR5, d’adresse IP 200.0.1.7 fournira le message CMR àqui se connectera sur son port 5017 en TCP.

Pour tester le comportement de cette station, nous pouvons utiliser l’outil netcat. C’est un très bon outil pédagogique pour comprendre le fonctionnement des sockets. Dans sa forme la plus simple, il va créer une socket entre la machine indiquée et le terminal d’où on l’a lancé.

netcat CMR

Il est beaucoup plus simple de comprendre ce qui se passe en le faisant qu’en regardant la copie d’écran ci-dessus car on voit alors les messages de correction s’afficher au fur et àmesure.

On notera la présence de retours àla ligne dont nous reparlerons plus loin. A remarquer également le « prompt » bizarre après l’interruption de netcat, dà» au passage, dans le message CMR, de codes interprétés comme des caractères spéciaux par le terminal qui a changé sa configuration en conséquence. Le plus simple reste de fermer ce terminal et d’en ouvrir un autre pour continuer...

configuration du récepteur mobile GB1000

Nous conseillons vivement l’utilisation de pccdu.exe pour commencer. Avec l’habitude la mise en configuration pourra se faire sous GRIL.

Il faut commencer par configurer un des logins réseau (ici « d ») du récepteur pour accepter les corrections en entrée :

GB1000 configuration du port tcp d en CMR

Avec un « sniffer » (dans le cas où le dialogue pccdu.exe - récepteur se fait par IP) on voit passer :
set,/par/dev/tcp/d/imode,cmr

On en profite pour vérifier les paramètres de la connexion telnet (c’est également faisable àpartir du clavier du GB1000). On se souvient que le port telnet par défaut du GB1000 est le 8002 (au lieu de 23 sur un système Unix standard) et qu’il accepte quatre connexions simultanées pour les utilisateurs « a », « b » « c » et « d ».

On utilise l’onglet « rover » pour indiquer au GB1000 qu’il est un mobile. Ici je lui ai dit de faire du RTK avec des ambiguïtés flottantes. Il calculera sa position en différentiel quand il le pourra. Il faut que la source des corrections soit « any », car seules les liaisons séries sont prévues dans la liste déroulante.

On voit passer, entre autres, sur le « sniffer » :

set,/par/pos/mode/cur,pf
set,/par/pos/mode/cd,on
set,/par/pos/pd/port,any

En revanche, si nous utilisons netcat, comme avec le NetR5, pour observer ce qui se passe sur le port en question, nous voyons tout de suite un problème si nous nous contentons de relier la socket base àla socket mobile :

Le GB1000 se comporte comme avec un telnet et il faut rentrer le login et le mot de passe àla main. J’ai essayé de « tromper » le GB1000 en chaînant une deuxième socket àla première pour effectuer la procédure de login, puis de tuer cette seconde socket pour pouvoir raccorder alors la socket base àla socket mobile. Mais tuer la seconde socket entraîne une fermeture de la session telnet et un nouveau chaînage de socket amène une nouvelle demande d’identification...

Cela montre qu’on ne peut pas échapper àl’écriture d’un petit programme.

Relier les sockets

Tout d’abord, l’utilitaire netcat, en dépit de ses possibilités, n’est pas suffisant pour répondre ànotre besoin. Nous allons devoir nous tourner vers un autre utililtaire, plus rarement disponible de base sur les distributions Linux, mais généralement prévu dans les paquetages additionnels : socat

A partir de deux fenetres differentes nous lançons

socat tcp-listen:14000,fork tcp:200.0.1.7:5017

d’un côté (le port 14000 de la machine locale fournira les corrections issues du port 5017 du NetR5 en 200.0.1.7),

et

socat tcp-listen:14001,fork tcp:200.0.1.14:8002

de l’autre (une connexion sur le port 14001 de la machine locale mettra en relation avec le GB1000 en 200.0.1.14).

Comment relier les deux avec une procédure d’autentification ?

Je propose un petit programme perl qui ne nécessite pas de connaître le perl pour être compris, contrairement àdes programmes C que j’ai vus, qui fonctionnent très bien, mais qui manipulent les sockets àtrès bas niveau et font donc appel àdes fonctions ésotériques (« primitives » est le terme exact dans le monde Unix) pour le néophyte. La puissance de perl réside dans ses modules (annoncés en début de programme par l’instruction use) qui créent un habillage sympathique autour des méchantes fonctions C. Ici nous aurons besoin d’un module présent d’office dans toutes les distributions que j’ai rencontrées, IO::Socket.

Pour ne pas perdre le lecteur dans des ouvertures/lectures/fermetures de fichiers de configuration, j’ai intégré les couples login/mot de passe dans le programme lui-même.

Je n’ai pas pu m’empêcher de laisser le module Readonly comme incitation aux bonnes pratiques d’écriture d’un programme perl, mais il n’ajoute rien ànotre démonstration technique.

Les seules instructions ésotériques sont les deux déclarations de socket avec affichage du code d’erreur et arrêt du programme en cas de problème, et l’« autoflush » qui évite la rétention d’information dans le tube de communication (« bufferization »).

#!/usr/bin/perl -w
# base2rover.pl        O.Charade       2008    May 29
#
#
use strict;
use Readonly;
use IO::Socket;
#
Readonly my $USAGE      =>  << 'END_USAGE';
usage: connect.pl local_port_base local_port_rover
END_USAGE

die( "$USAGE\n") if ($#ARGV != 2 );

my $PORTNO = $ARGV[0];
my $PORTN1 = $ARGV[1];
my $base  = IO::Socket::INET->new( PeerPort => $PORTNO,
                                  PeerHost  => '127.0.0.1',
                                  Proto => 'tcp',
                                   ) or die("$!");
my $rover = IO::Socket::INET->new( PeerPort => $PORTN1,
                                  PeerHost  => '127.0.0.1',
                                  Proto => 'tcp',
                                   ) or die("$!");
my $log_rover   = 'd';
my $pwd_rover   = 'T224398';

$base->autoflush(1);        # don't keep anything in buffer!
$rover->autoflush(1);       # don't keep anything in buffer!

print $rover "$log_rover\n";    # login
print $rover "$pwd_rover\n";



my $stream;
while ( defined($stream = <$base>) ){
   print $rover $stream ;
}

Le login sur le GB1000 se limite àune écriture sur la socket.

Tout le travail de transfert se fait dans la boucle while où il est simplement écrit que ce qui sort du tuyau $base est immédiatement mis dans le tuyau $rover.

A quoi voit-on que ça marche ? Sur pccdu, l’indication « standalone » est remplacée par « RTK float » (mais elle revient de temps en temps quand la correction n’est pas arrivée dans les temps ou n’a pas été émise). Sur l’écran du GB1000, le symbole du lien radio apparaît àcôté du nombre de satellite.

pccdu rtk

Le message RTCM 2.X

Configurons maintenant un récepteur NetRS (d’adresse IP 200.0.1.2) pour émettre un message de type RTCM sur le port 5019, toujours en tcp (la documentation du NetRS précise que dans le cas d’une connexion UDP, le client doit régulièrement émettre un message « keep alive » vers le serveur, ce que nous ne souhaitons devoir gérer en plus).

I/O Configuration

Utilisons netcat pour vérifier que ça marche comme nous le pensons :

netcat

Nous constatons (toujours plus facilement en le faisant qu’en regardant la capture d’écran ci-dessus) l’ABSENCE TOTALE de caractères de fin de ligne. Voilàqui va poser un gros problème àmon programme perl :

La lecture du tuyau $base n’est « activée » que par une fin de ligne... Il m’a fallu du temps pour comprendre ce qui se passait. Après de multiples essais, alors que mon programme tournait sans que je voie quoique ce soit aller vers le mobile, j’ai tué la socket vers la base. Immédiatement tout un tas de corrections sont passées d’un seul coup vers le mobile : il s’agissait de toutes les corrections accumulées depuis le lancement du programme àl’entrée de la socket et qui attendaient un caractère de fin de ligne pour entrer dans le tuyau...

Configurons le GB1000 pour accepter le message RTCM (set,/par/dev/tcp/d/imode,rtcm),

et modifions le mode de lecture du programme perl.

while ( sysread $base,$stream,1) ){
   syswrite $rover,$stream,1 ;
}

Il n’y que ça àchanger : on remplace les traditionnelles instructions de lecture/écriture par les appels système au plus bas niveau, pour lesquels on doit préciser le nombre d’octets àlire (ici 1 car je n’ai pas voulu m’embêter àrechercher le format du message RTCM). Et ça marche ! Ca marche d’ailleurs également dans le cas du message CMR, mais je trouvais moins pédagogique de donner immédiatement cette solution où l’on fait appel àdes fonctions qui commencent àmettre le lecteur mal àl’aise...

post scriptum :

Dans la famille RTCM, Je n’ai parlé que du message RTCM 2.X car c’est celui avec lequel j’ai eu le plus de mal. Le message RTCM 3 issu d’un NetR5 contient apparemment des fins de ligne. Son utilisation ne présente pas de difficulté nouvelle.

Je n’ai pas décrit le cas où un GB1000 est également en station de base : il suffit de rajouter le login correspondant dans le programme et ça marche immédiatement.


[1Le récepteur NetRS sur lequel je travaillais est tombé en panne pendant la rédaction de cet article. Trimble France a mis àma disposition un récepteur NetR5 pour finir mes tests, ce qui explique les changements de type de récepteur en cours d’article.