Initial commit
This commit is contained in:
commit
1d14968446
10 changed files with 66270 additions and 0 deletions
213
CMakeLists.txt
Normal file
213
CMakeLists.txt
Normal file
|
@ -0,0 +1,213 @@
|
|||
cmake_minimum_required(VERSION 2.8.3)
|
||||
project(acquisition_biosemi)
|
||||
|
||||
set(CMAKE_BUILD_TYPE Debug)
|
||||
#set(CMAKE_BUILD_TYPE Release)
|
||||
|
||||
|
||||
|
||||
## Find catkin macros and libraries
|
||||
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
|
||||
## is used, also find other catkin packages
|
||||
find_package(catkin REQUIRED COMPONENTS
|
||||
roscpp
|
||||
rospy
|
||||
std_msgs
|
||||
message_generation
|
||||
)
|
||||
|
||||
|
||||
## System dependencies are found with CMake's conventions
|
||||
# find_package(Boost REQUIRED COMPONENTS system)
|
||||
|
||||
|
||||
## Uncomment this if the package has a setup.py. This macro ensures
|
||||
## modules and global scripts declared therein get installed
|
||||
## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
|
||||
# catkin_python_setup()
|
||||
|
||||
################################################
|
||||
## Declare ROS messages, services and actions ##
|
||||
################################################
|
||||
|
||||
## To declare and build messages, services or actions from within this
|
||||
## package, follow these steps:
|
||||
## * Let MSG_DEP_SET be the set of packages whose message types you use in
|
||||
## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
|
||||
## * In the file package.xml:
|
||||
## * add a build_depend tag for "message_generation"
|
||||
## * add a build_depend and a run_depend tag for each package in MSG_DEP_SET
|
||||
## * If MSG_DEP_SET isn't empty the following dependency has been pulled in
|
||||
## but can be declared for certainty nonetheless:
|
||||
## * add a run_depend tag for "message_runtime"
|
||||
## * In this file (CMakeLists.txt):
|
||||
## * add "message_generation" and every package in MSG_DEP_SET to
|
||||
## find_package(catkin Rset(CMAKE_BUILD_TYPE Debug)
|
||||
## * add "message_runtime" and every package in MSG_DEP_SET to
|
||||
## catkin_package(CATKIN_DEPENDS ...)
|
||||
## * uncomment the add_*_files sections below as needed
|
||||
## and list every .msg/.srv/.action file to be processed
|
||||
## * uncomment the generate_messages entry below
|
||||
## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)
|
||||
|
||||
## Generate messages in the 'msg' folder
|
||||
add_message_files(
|
||||
FILES
|
||||
biosemi_result.msg
|
||||
biosemi_echantillon.msg
|
||||
)
|
||||
|
||||
## Generate services in the 'srv' folder
|
||||
# add_service_files(
|
||||
# FILES
|
||||
# Service1.srv
|
||||
# Service2.srv
|
||||
# )
|
||||
|
||||
## Generate actions in the 'action' folder
|
||||
# add_action_files(
|
||||
# FILES
|
||||
# Action1.action
|
||||
# Action2.action
|
||||
# )
|
||||
|
||||
## Generate added messages and services with any dependencies listed here
|
||||
generate_messages(
|
||||
DEPENDENCIES
|
||||
std_msgs
|
||||
)
|
||||
|
||||
################################################
|
||||
## Declare ROS dynamic reconfigure parameters ##
|
||||
################################################
|
||||
|
||||
## To declare and build dynamic reconfigure parameters within this
|
||||
## package, follow these steps:
|
||||
## * In the file package.xml:
|
||||
## * add a build_depend and a run_depend tag for "dynamic_reconfigure"
|
||||
## * In this file (CMakeLists.txt):
|
||||
## * add "dynamic_reconfigure" to
|
||||
## find_package(catkin REQUIRED COMPONENTS ...)
|
||||
## * uncomment the "generate_dynamic_reconfigure_options" section below
|
||||
## and list every .cfg file to be processed
|
||||
|
||||
## Generate dynamic reconfigure parameters in the 'cfg' folder
|
||||
# generate_dynamic_reconfigure_options(
|
||||
# cfg/DynReconf1.cfg
|
||||
# cfg/DynReconf2.cfg
|
||||
# )
|
||||
|
||||
###################################
|
||||
## catkin specific configuration ##
|
||||
###################################
|
||||
## The catkin_package macro generates cmake config files for your package
|
||||
## Declare things to be passed to dependent projects
|
||||
## INCLUDE_DIRS: uncomment this if you package contains header files
|
||||
## LIBRARIES: libraries you create in this project that dependent projects also need
|
||||
## CATKIN_DEPENDS: catkin_packages dependent projects also need
|
||||
## DEPENDS: system dependencies of this project that dependent projects also need
|
||||
catkin_package(
|
||||
# INCLUDE_DIRS include
|
||||
# LIBRARIES acquisition_biosemi
|
||||
CATKIN_DEPENDS roscpp rospy std_msgs message_runtime
|
||||
# DEPENDS system_lib
|
||||
)
|
||||
|
||||
###########
|
||||
## Build ##
|
||||
###########
|
||||
|
||||
## Specify additional locations of header files
|
||||
## Your package locations should be listed before other locations
|
||||
# include_directories(include)
|
||||
include_directories(
|
||||
${catkin_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
## Declare a C++ library
|
||||
# add_library(acquisition_biosemi
|
||||
# src/${PROJECT_NAME}/acquisition_biosemi.cpp
|
||||
# )
|
||||
|
||||
## Add cmake target dependencies of the library
|
||||
## as an example, code may need to be generated before libraries
|
||||
## either from message generation or dynamic reconfigure
|
||||
# add_dependencies(acquisition_biosemi ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
|
||||
|
||||
## Declare a C++ executable
|
||||
# add_executable(acquisition_biosemi_node src/acquisition_biosemi_node.cpp)
|
||||
|
||||
## Add cmake target dependencies of the executable
|
||||
## same as for the library above
|
||||
# add_dependencies(acquisition_biosemi_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
|
||||
|
||||
## Specify libraries to link a library or executable target against
|
||||
# target_link_libraries(acquisition_biosemi_node
|
||||
# ${catkin_LIBRARIES}
|
||||
# )
|
||||
|
||||
#############
|
||||
## Install ##
|
||||
#############
|
||||
|
||||
# all install targets should use catkin DESTINATION variables
|
||||
# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html
|
||||
|
||||
## Mark executable scripts (Python etc.) for installation
|
||||
## in contrast to setup.py, you can choose the destination
|
||||
# install(PROGRAMS
|
||||
# scripts/my_python_script
|
||||
# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
|
||||
# )
|
||||
|
||||
## Mark executables and/or libraries for installation
|
||||
# install(TARGETS acquisition_biosemi acquisition_biosemi_node
|
||||
# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
|
||||
# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
|
||||
# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
|
||||
# )
|
||||
|
||||
## Mark cpp header files for installation
|
||||
# install(DIRECTORY include/${PROJECT_NAME}/
|
||||
# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
|
||||
# FILES_MATCHING PATTERN "*.h"
|
||||
# PATTERN ".svn" EXCLUDE
|
||||
# )
|
||||
|
||||
## Mark other files for installation (e.g. launch and bag files, etc.)
|
||||
# install(FILES
|
||||
# # myfile1
|
||||
# # myfile2
|
||||
# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
|
||||
# )
|
||||
|
||||
#############
|
||||
## Testing ##
|
||||
#############
|
||||
|
||||
## Add gtest based cpp test target and link libraries
|
||||
# catkin_add_gtest(${PROJECT_NAME}-test test/test_acquisition_biosemi.cpp)
|
||||
# if(TARGET ${PROJECT_NAME}-test)
|
||||
# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
|
||||
# endif()
|
||||
|
||||
## Add folders to be run by python nosetests
|
||||
# catkin_add_nosetests(test)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
include_directories(include ${catkin_INCLUDE_DIRS})
|
||||
|
||||
add_executable(biosemi_talker src/biosemi_talker.cpp)
|
||||
target_link_libraries(biosemi_talker ${catkin_LIBRARIES})
|
||||
add_dependencies(biosemi_talker acquisition_biosemi_generate_messages_cpp)
|
||||
|
||||
add_executable(biosemi_listener src/biosemi_listener.cpp)
|
||||
target_link_libraries(biosemi_listener ${catkin_LIBRARIES})
|
||||
add_dependencies(biosemi_listener acquisition_biosemi_generate_messages_cpp)
|
||||
|
||||
add_executable(biosemi_simul src/biosemi_simul.cpp)
|
||||
target_link_libraries(biosemi_simul ${catkin_LIBRARIES})
|
||||
add_dependencies(biosemi_simul acquisition_biosemi_generate_messages_cpp)
|
19747
Enregistrements/herve001.txt
Normal file
19747
Enregistrements/herve001.txt
Normal file
File diff suppressed because it is too large
Load diff
22285
Enregistrements/herve002.txt
Normal file
22285
Enregistrements/herve002.txt
Normal file
File diff suppressed because it is too large
Load diff
23417
Enregistrements/herve003.txt
Normal file
23417
Enregistrements/herve003.txt
Normal file
File diff suppressed because it is too large
Load diff
4
msg/biosemi_echantillon.msg
Normal file
4
msg/biosemi_echantillon.msg
Normal file
|
@ -0,0 +1,4 @@
|
|||
uint32 numero
|
||||
uint32 frequence
|
||||
float64[] valeurs
|
||||
string extra
|
5
msg/biosemi_result.msg
Normal file
5
msg/biosemi_result.msg
Normal file
|
@ -0,0 +1,5 @@
|
|||
uint32 numero
|
||||
uint32 nombre
|
||||
uint32 frequence
|
||||
float64[] valeurs
|
||||
string extra
|
56
package.xml
Normal file
56
package.xml
Normal file
|
@ -0,0 +1,56 @@
|
|||
<?xml version="1.0"?>
|
||||
<package>
|
||||
<name>acquisition_biosemi</name>
|
||||
<version>0.0.0</version>
|
||||
<description>The acquisition_biosemi package</description>
|
||||
|
||||
<!-- One maintainer tag required, multiple allowed, one person per tag -->
|
||||
<!-- Example: -->
|
||||
<!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> -->
|
||||
<maintainer email="gutzwiller@todo.todo">gutzwiller</maintainer>
|
||||
|
||||
|
||||
<!-- One license tag required, multiple allowed, one license per tag -->
|
||||
<!-- Commonly used license strings: -->
|
||||
<!-- BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 -->
|
||||
<license>TODO</license>
|
||||
|
||||
|
||||
<!-- Url tags are optional, but mutiple are allowed, one per tag -->
|
||||
<!-- Optional attribute type can be: website, bugtracker, or repository -->
|
||||
<!-- Example: -->
|
||||
<!-- <url type="website">http://wiki.ros.org/acquisition_biosemi</url> -->
|
||||
|
||||
|
||||
<!-- Author tags are optional, mutiple are allowed, one per tag -->
|
||||
<!-- Authors do not have to be maintianers, but could be -->
|
||||
<!-- Example: -->
|
||||
<!-- <author email="jane.doe@example.com">Jane Doe</author> -->
|
||||
|
||||
|
||||
<!-- The *_depend tags are used to specify dependencies -->
|
||||
<!-- Dependencies can be catkin packages or system dependencies -->
|
||||
<!-- Examples: -->
|
||||
<!-- Use build_depend for packages you need at compile time: -->
|
||||
<build_depend>message_generation</build_depend>
|
||||
<!-- Use buildtool_depend for build tool packages: -->
|
||||
<!-- <buildtool_depend>catkin</buildtool_depend> -->
|
||||
<!-- Use run_depend for packages you need at runtime: -->
|
||||
<run_depend>message_runtime</run_depend>
|
||||
<!-- Use test_depend for packages you need only for testing: -->
|
||||
<!-- <test_depend>gtest</test_depend> -->
|
||||
<buildtool_depend>catkin</buildtool_depend>
|
||||
<build_depend>roscpp</build_depend>
|
||||
<build_depend>rospy</build_depend>
|
||||
<build_depend>std_msgs</build_depend>
|
||||
<run_depend>roscpp</run_depend>
|
||||
<run_depend>rospy</run_depend>
|
||||
<run_depend>std_msgs</run_depend>
|
||||
|
||||
|
||||
<!-- The export tag contains other, unspecified, tags -->
|
||||
<export>
|
||||
<!-- Other tools can request additional information be placed here -->
|
||||
|
||||
</export>
|
||||
</package>
|
50
src/biosemi_listener.cpp
Normal file
50
src/biosemi_listener.cpp
Normal file
|
@ -0,0 +1,50 @@
|
|||
#include "ros/ros.h"
|
||||
#include "acquisition_biosemi/biosemi_result.h"
|
||||
#include <iostream>
|
||||
|
||||
|
||||
static unsigned long int numero;
|
||||
|
||||
|
||||
/* Cette fonction est appelée à chaque réception de message */
|
||||
void biosemiCallback(const acquisition_biosemi::biosemi_result msg)
|
||||
{
|
||||
int num, taille;
|
||||
|
||||
taille = msg.valeurs.size();
|
||||
std::vector<double>::const_iterator i = msg.valeurs.begin();
|
||||
for(num = 0; num < msg.nombre; num ++ ) {
|
||||
std::cout.setf(std::ios::fixed, std::ios::floatfield);
|
||||
std::cout.precision(12);
|
||||
std::cout.width(12); std::cout.fill('0');
|
||||
std::cout << msg.numero + num;
|
||||
std::cout.width(0); std::cout.fill(' ');
|
||||
std::cout << "[" << msg.frequence << "]: ";
|
||||
for(int k = 0; k < taille / msg.nombre; k++) {
|
||||
std::cout << " " << *i;
|
||||
++i;
|
||||
}
|
||||
std::cout << " " << msg.extra << std::endl;
|
||||
|
||||
|
||||
if (numero != 0) {
|
||||
if (msg.numero + num != numero + 1) {
|
||||
std::cerr << "Perte de synchronisation : numero = " << msg.numero << ", ancien = " << numero << std::endl;
|
||||
ros::shutdown();
|
||||
}
|
||||
}
|
||||
numero = msg.numero + num;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
numero = 0;
|
||||
ros::init(argc, argv, "biosemi_listener");
|
||||
ros::NodeHandle n;
|
||||
ros::Subscriber sub = n.subscribe("biosemi_result", 1000, biosemiCallback);
|
||||
|
||||
ros::spin();
|
||||
|
||||
return 0;
|
||||
}
|
236
src/biosemi_simul.cpp
Normal file
236
src/biosemi_simul.cpp
Normal file
|
@ -0,0 +1,236 @@
|
|||
/*
|
||||
* biosemi_talker.cpp
|
||||
*
|
||||
*
|
||||
* Programme permettant de diffuser sous ROS les échantillons en provenance
|
||||
* du système d'acquisition biosemi.
|
||||
* Note : un message est diffusé par échantillon, un échantillon peut
|
||||
* contenir plusieurs canaux.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Ce programme transmet des messages qui contiennt :
|
||||
* - le numéro d'ordre de l'échantillon
|
||||
* - la fréquence d'échantillonnage
|
||||
* - un tableau de valeurs réelles (double) dont la taille dépend
|
||||
* des paramètres de lancement du serveur d'acquistion (nombre de canaux)
|
||||
* - une chaîne de caractères extra (pour les codes d'erreurs).
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ros/ros.h"
|
||||
#include "acquisition_biosemi/biosemi_result.h"
|
||||
#include "acquisition_biosemi/biosemi_echantillon.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
|
||||
|
||||
|
||||
#define TAILLE_BUFFER 20000
|
||||
#define FREQUENCE 256
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
static int frequence = FREQUENCE;
|
||||
static int fin_de_donnees = 0;
|
||||
|
||||
|
||||
/*************************************************************************************************************/
|
||||
|
||||
void lecture_fichier(int fd, char * buffer, int * entree) {
|
||||
ssize_t taille;
|
||||
|
||||
if (fin_de_donnees) return;
|
||||
taille = 2 * TAILLE_BUFFER - (*entree);
|
||||
if (taille > SSIZE_MAX) taille = SSIZE_MAX;
|
||||
taille = read(fd, buffer + (*entree), taille);
|
||||
if (taille <= 0) {
|
||||
fin_de_donnees = 1;
|
||||
} else {
|
||||
*entree += taille;
|
||||
buffer[*entree] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************************/
|
||||
|
||||
int recupere_ligne(acquisition_biosemi::biosemi_echantillon & echantillon, const char * buffer, int & lecture, int & entree) {
|
||||
int local_lect = 0;
|
||||
int local_fin;
|
||||
char * fin;
|
||||
double valeur;
|
||||
int ok;
|
||||
char local_buffer[TAILLE_BUFFER+1];
|
||||
int i;
|
||||
|
||||
static int compteur = 0;
|
||||
|
||||
|
||||
// Récupération d'une ligne au maximum dans un buffer local.
|
||||
for(i = 0; (i+lecture < entree) && (buffer[i+lecture] != '\n') && (buffer[i+lecture] != 0); i++) {
|
||||
local_buffer[i] = buffer[i+lecture];
|
||||
local_buffer[i+1] = '\0';
|
||||
}
|
||||
if (buffer[i+lecture] != '\n') return 0; // Fin de la ligne non trouvée.
|
||||
|
||||
// On efface l'ancien contenu :
|
||||
echantillon.valeurs.clear();
|
||||
echantillon.frequence = frequence;
|
||||
echantillon.extra = "";
|
||||
|
||||
// Lecture du numéro :
|
||||
echantillon.numero = strtoul(local_buffer + local_lect, &fin, 10);
|
||||
local_fin = fin - local_buffer;
|
||||
// Le caractère suivant est forcément un ':', sinon le numéro n'est pas présent.
|
||||
if (local_buffer[local_fin] != ':') {
|
||||
compteur += 1;
|
||||
echantillon.numero = compteur;
|
||||
} else {
|
||||
local_lect = local_fin + 1;
|
||||
}
|
||||
|
||||
|
||||
// On scanne des doubles, autant qu'on en trouve :
|
||||
do {
|
||||
ok = 0;
|
||||
valeur = strtod(local_buffer + local_lect, &fin);
|
||||
local_fin = fin - local_buffer;
|
||||
if (valeur != 0.0) {
|
||||
ok = 1; // Une valeur non nulle indique une conversion correcte.
|
||||
} else {
|
||||
// Une valeur nulle peut indiquer une conversion incorrecte, ou le fait que le nombre soit nul.
|
||||
// Il faut vérifier cela. On doit trouver des chiffres dans l'espace qui a étré scanné.
|
||||
ok = 0;
|
||||
for(int i = local_lect; i < local_fin; i++) {
|
||||
if ((local_buffer[i] >= '0') && (local_buffer[i] <= '9')) ok = 1; // Il y a des chiffres.
|
||||
}
|
||||
}
|
||||
if (ok) {
|
||||
local_lect = local_fin;
|
||||
echantillon.valeurs.push_back(valeur);
|
||||
}
|
||||
} while (ok);
|
||||
|
||||
|
||||
// On recherche s'il y a encore des caractères sur la ligne :
|
||||
while(local_buffer[local_lect] == ' ') local_lect ++;
|
||||
echantillon.extra = local_buffer + local_lect;
|
||||
|
||||
lecture += strlen(local_buffer) + 1;
|
||||
return 1; // Ici la ligne a été complètement décodée.
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************************************************/
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int fd;
|
||||
char buffer[2 * TAILLE_BUFFER + 1];
|
||||
int entree, lecture;
|
||||
acquisition_biosemi::biosemi_result msg;
|
||||
|
||||
|
||||
// Vérification des paramètres de la ligne de commande :
|
||||
|
||||
if (argc < 2) {
|
||||
cerr << "Appel par : biosemi_simul <nom du fichier> [<fréquence>]." << std::endl;
|
||||
cerr << " -- le fichier doit contienir l'enregistrement BCI." << std::endl;
|
||||
cerr << " -- la fréquence par défaut, si non spécifié, est 256 ech/sec." << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
// Connexion au fichier :
|
||||
|
||||
entree = 0;
|
||||
lecture = 0;
|
||||
fd = open(argv[1], O_RDONLY);
|
||||
if (fd == -1) {
|
||||
cout << "Erreur : fichier introuvable : " << argv[1] << "." << endl;
|
||||
exit(1);
|
||||
}
|
||||
if (argc > 2) frequence = atoi(argv[2]);
|
||||
|
||||
|
||||
// Initialisation de ROS :
|
||||
|
||||
ros::init(argc, argv, "biosemi_simul");
|
||||
ros::NodeHandle n;
|
||||
ros::Publisher biosemi_pub = n.advertise<acquisition_biosemi::biosemi_result>("biosemi_result", 3);
|
||||
ros::Rate loop_rate(10);
|
||||
|
||||
|
||||
msg.numero = 0;
|
||||
msg.nombre = 0;
|
||||
msg.frequence = 0;
|
||||
msg.valeurs.clear();
|
||||
msg.extra = "";
|
||||
while (ros::ok())
|
||||
{
|
||||
acquisition_biosemi::biosemi_echantillon ech;
|
||||
|
||||
lecture_fichier(fd, buffer, &entree);
|
||||
|
||||
while(recupere_ligne(ech, buffer, lecture, entree)) {
|
||||
if (lecture >= TAILLE_BUFFER) {
|
||||
lecture -= TAILLE_BUFFER;
|
||||
entree -= TAILLE_BUFFER;
|
||||
memcpy(buffer, buffer+TAILLE_BUFFER, TAILLE_BUFFER + 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (msg.numero == 0) msg.numero = ech.numero;
|
||||
msg.nombre += 1;
|
||||
msg.frequence = ech.frequence;
|
||||
if (ech.extra != "") msg.extra = ech.extra;
|
||||
for(std::vector<double>::const_iterator i = ech.valeurs.begin(); i != ech.valeurs.end(); ++i)
|
||||
msg.valeurs.push_back(*i);
|
||||
|
||||
|
||||
std::cout.setf(std::ios::fixed, std::ios::floatfield);
|
||||
std::cout.precision(12);
|
||||
std::cout.width(12); std::cout.fill('0');
|
||||
std::cout << ech.numero;
|
||||
std::cout.width(0); std::cout.fill(' ');
|
||||
std::cout << "[" << ech.frequence << "]: ";
|
||||
for(std::vector<double>::const_iterator i = ech.valeurs.begin(); i != ech.valeurs.end(); ++i)
|
||||
std::cout << " " << *i;
|
||||
std::cout << " " << ech.extra << " (" << msg.nombre << ")" << std::endl;
|
||||
|
||||
|
||||
|
||||
|
||||
if (msg.nombre == frequence/10) {
|
||||
biosemi_pub.publish(msg);
|
||||
ros::spinOnce();
|
||||
msg.numero = 0;
|
||||
msg.nombre = 0;
|
||||
msg.frequence = 0;
|
||||
msg.valeurs.clear();
|
||||
msg.extra = "";
|
||||
loop_rate.sleep();
|
||||
}
|
||||
}
|
||||
if (fin_de_donnees) {
|
||||
biosemi_pub.publish(msg);
|
||||
ros::spinOnce();
|
||||
msg.numero = 0;
|
||||
msg.nombre = 0;
|
||||
msg.frequence = 0;
|
||||
msg.valeurs.clear();
|
||||
msg.extra = "";
|
||||
std::cerr << "FIN DE DONNEES" << std::endl;
|
||||
usleep(300000);
|
||||
ros::shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
257
src/biosemi_talker.cpp
Normal file
257
src/biosemi_talker.cpp
Normal file
|
@ -0,0 +1,257 @@
|
|||
/*
|
||||
* biosemi_talker.cpp
|
||||
*
|
||||
*
|
||||
* Programme permettant de diffuser sous ROS les échantillons en provenance
|
||||
* du système d'acquisition biosemi.
|
||||
* Note : un message est diffusé par échantillon, un échantillon peut
|
||||
* contenir plusieurs canaux.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Ce programme transmet des messages qui contiennt :
|
||||
* - le numéro d'ordre de l'échantillon
|
||||
* - la fréquence d'échantillonnage
|
||||
* - un tableau de valeurs réelles (double) dont la taille dépend
|
||||
* des paramètres de lancement du serveur d'acquistion (nombre de canaux)
|
||||
* - une chaîne de caractères extra (pour les codes d'erreurs).
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ros/ros.h"
|
||||
#include "acquisition_biosemi/biosemi_result.h"
|
||||
#include "acquisition_biosemi/biosemi_echantillon.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
|
||||
#define TAILLE_BUFFER 20000
|
||||
#define FREQUENCE 2048
|
||||
|
||||
using namespace std;
|
||||
|
||||
static int frequence = FREQUENCE;
|
||||
static int fin_de_donnees = 0;
|
||||
|
||||
|
||||
/*************************************************************************************************************/
|
||||
|
||||
int appelleServeur(int port, char * name);
|
||||
|
||||
// Appelle un serveur par son nom et un numéro de port.
|
||||
// Renvoie un numéro de socket, ou -1 si erreur.
|
||||
|
||||
int appelleServeur(int port, char * name) {
|
||||
struct hostent *hostinfo;
|
||||
struct sockaddr_in server;
|
||||
int Socket;
|
||||
|
||||
hostinfo=gethostbyname(name);
|
||||
if (hostinfo == NULL) return -1;
|
||||
bzero((char*)&server, sizeof(server));
|
||||
memcpy(&server.sin_addr, hostinfo->h_addr, hostinfo->h_length);
|
||||
server.sin_family=AF_INET;
|
||||
server.sin_port=htons(port);
|
||||
Socket=socket(AF_INET,SOCK_STREAM,0);static int fin_de_donnees = 0;
|
||||
|
||||
if (connect(Socket, (struct sockaddr *)&server, sizeof(server)))
|
||||
return -1;
|
||||
else
|
||||
return Socket;
|
||||
}
|
||||
|
||||
/*************************************************************************************************************/
|
||||
|
||||
void lecture_reseau(int socket, char * buffer, int * entree) {
|
||||
ssize_t longueur;
|
||||
|
||||
if (*entree == 2 * TAILLE_BUFFER) return;
|
||||
longueur = recv(socket, buffer + (*entree), 2 * TAILLE_BUFFER - (*entree), 0);
|
||||
if (longueur <= 0) {
|
||||
fin_de_donnees = 1;
|
||||
} else {
|
||||
*entree += longueur;
|
||||
buffer[*entree] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************************/
|
||||
|
||||
int recupere_ligne(acquisition_biosemi::biosemi_echantillon & echantillon, const char * buffer, int & lecture, int & entree) {
|
||||
int local_lect = 0;
|
||||
int local_fin;
|
||||
char * fin;ros::spinOnce();
|
||||
double valeur;
|
||||
int ok;
|
||||
char local_buffer[TAILLE_BUFFER+1];
|
||||
int i;
|
||||
|
||||
static int compteur = 0;
|
||||
|
||||
|
||||
// Récupération d'une ligne au maximum dans un buffer local.
|
||||
for(i = 0; (i+lecture < entree) && (buffer[i+lecture] != '\n') && (buffer[i+lecture] != 0); i++) {
|
||||
local_buffer[i] = buffer[i+lecture];
|
||||
local_buffer[i+1] = '\0';
|
||||
}
|
||||
if (buffer[i+lecture] != '\n') return 0; // Fin de la ligne non trouvée.
|
||||
|
||||
// On efface l'ancien contenu :
|
||||
echantillon.valeurs.clear();
|
||||
echantillon.frequence = frequence;
|
||||
echantillon.extra = "";
|
||||
|
||||
// Lecture du numéro :
|
||||
echantillon.numero = strtoul(local_buffer + local_lect, &fin, 10);
|
||||
local_fin = fin - local_buffer;
|
||||
// Le caractère suivant est forcément un ':', sinon le numéro n'est pas présent.
|
||||
if (local_buffer[local_fin] != ':') {
|
||||
compteur += 1;
|
||||
echantillon.numero = compteur;
|
||||
} else {
|
||||
local_lect = local_fin + 1;
|
||||
}
|
||||
|
||||
|
||||
// On scanne des doubles, autant qu'on en trouve :
|
||||
do {
|
||||
ok = 0;
|
||||
valeur = strtod(local_buffer + local_lect, &fin);
|
||||
local_fin = fin - local_buffer;
|
||||
if (valeur != 0.0) {
|
||||
ok = 1; // Une valeur non nulle indique une conversion correcte.
|
||||
} else {
|
||||
// Une valeur nulle peut indiquer une conversion incorrecte, ou le fait que le nombre soit nul.
|
||||
// Il faut vérifier cela. On doit trouver des chiffres dans l'espace qui a étré scanné.
|
||||
ok = 0;
|
||||
for(int i = local_lect; i < local_fin; i++) {
|
||||
if ((local_buffer[i] >= '0') && (local_buffer[i] <= '9')) ok = 1; // Il y a des chiffres.
|
||||
}
|
||||
}
|
||||
if (ok) {
|
||||
local_lect = local_fin;
|
||||
echantillon.valeurs.push_back(valeur);
|
||||
}
|
||||
} while (ok);
|
||||
|
||||
|
||||
// On recherche s'il y a encore des caractères sur la ligne :
|
||||
while(local_buffer[local_lect] == ' ') local_lect ++;
|
||||
echantillon.extra = local_buffer + local_lect;
|
||||
|
||||
lecture += strlen(local_buffer) + 1;
|
||||
return 1; // Ici la ligne a été complètement décodée.
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************************************************/
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int Socket;
|
||||
char buffer[2 * TAILLE_BUFFER + 1];
|
||||
int entree, lecture;
|
||||
acquisition_biosemi::biosemi_result msg;
|
||||
|
||||
|
||||
// Vérification des paramètres de la ligne de commande :
|
||||
|
||||
if (argc < 2) {
|
||||
cerr << "Appel par : biosemi_talker <nom du serveur> [<numéro de port>]." << std::endl;
|
||||
cerr << " -- le serveur est la machine sous Windows reliée au système d'acquisition." << std::endl;
|
||||
cerr << " -- le numéro de port par défaut, si non spécifié, est 50000." << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
// Initialisation de ROS :
|
||||
|
||||
ros::init(argc, argv, "biosemi_talker");
|
||||
ros::NodeHandle n;
|
||||
ros::Publisher biosemi_pub = n.advertise<acquisition_biosemi::biosemi_result>("biosemi_result", 3);
|
||||
|
||||
|
||||
// Connexion au serveur réseau :
|
||||
|
||||
Socket = appelleServeur( argc >= 3 ? atoi(argv[2]) : 50000 , argv[1] );
|
||||
if (Socket < 0) {
|
||||
cout << "Erreur de connexion au serveur : " << argv[1] << endl;
|
||||
ros::shutdown();
|
||||
}
|
||||
entree = 0;
|
||||
lecture = 0;
|
||||
|
||||
|
||||
msg.numero = 0;
|
||||
msg.nombre = 0;
|
||||
msg.frequence = 0;
|
||||
msg.valeurs.clear();
|
||||
msg.extra = "";
|
||||
while (ros::ok())
|
||||
{
|
||||
acquisition_biosemi::biosemi_echantillon ech;
|
||||
|
||||
lecture_reseau(Socket, buffer, &entree);
|
||||
|
||||
while(recupere_ligne(ech, buffer, lecture, entree)) {
|
||||
if (lecture >= TAILLE_BUFFER) {ros::spinOnce();
|
||||
lecture -= TAILLE_BUFFER;
|
||||
entree -= TAILLE_BUFFER;
|
||||
memcpy(buffer, buffer+TAILLE_BUFFER, TAILLE_BUFFER + 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (msg.numero == 0) msg.numero = ech.numero;
|
||||
msg.nombre += 1;
|
||||
msg.frequence = ech.frequence;
|
||||
if (ech.extra != "") msg.extra = ech.extra;
|
||||
for(std::vector<double>::const_iterator i = ech.valeurs.begin(); i != ech.valeurs.end(); ++i)
|
||||
msg.valeurs.push_back(*i);
|
||||
|
||||
|
||||
std::cout.setf(std::ios::fixed, std::ios::floatfield);
|
||||
std::cout.precision(12);
|
||||
std::cout.width(12); std::cout.fill('0');
|
||||
std::cout << ech.numero;
|
||||
std::cout.width(0); std::cout.fill(' ');
|
||||
std::cout << "[" << ech.frequence << "]: ";
|
||||
for(std::vector<double>::const_iterator i = ech.valeurs.begin(); i != ech.valeurs.end(); ++i)
|
||||
std::cout << " " << *i;
|
||||
std::cout << " " << ech.extra << std::endl;
|
||||
|
||||
|
||||
|
||||
|
||||
if (msg.nombre == frequence/10) {
|
||||
biosemi_pub.publish(msg);
|
||||
ros::spinOnce();
|
||||
msg.numero = 0;
|
||||
msg.nombre = 0;
|
||||
msg.frequence = 0;
|
||||
msg.valeurs.clear();
|
||||
msg.extra = "";
|
||||
}
|
||||
}
|
||||
if (fin_de_donnees) {
|
||||
biosemi_pub.publish(msg);
|
||||
ros::spinOnce();
|
||||
msg.numero = 0;
|
||||
msg.nombre = 0;
|
||||
msg.frequence = 0;
|
||||
msg.valeurs.clear();
|
||||
msg.extra = "";
|
||||
ros::shutdown();
|
||||
std::cerr << "Perte de la connexion réseau." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
close(Socket);
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue