From 8f486613be58ced269db1d437e560c16558604e8 Mon Sep 17 00:00:00 2001 From: becquet Date: Thu, 10 May 2007 18:49:20 +0000 Subject: Création de chuck, le programme du robot 2007. --- i/chuck/src/Makefile.defs | 112 ++++ i/chuck/src/README | 25 + i/chuck/src/ai/Makefile.defs | 5 + i/chuck/src/ai/ai.cc | 511 ++++++++++++++++ i/chuck/src/ai/ai.hh | 86 +++ i/chuck/src/ai/test_ai.cc | 105 ++++ i/chuck/src/asserv/Makefile.defs | 5 + i/chuck/src/asserv/asserv.cc | 387 ++++++++++++ i/chuck/src/asserv/asserv.hh | 141 +++++ i/chuck/src/asserv/test_asserv.cc | 197 +++++++ i/chuck/src/config/Makefile.defs | 5 + i/chuck/src/config/config.cc | 27 + i/chuck/src/config/config.hh | 98 +++ i/chuck/src/config/config_data.cc | 148 +++++ i/chuck/src/config/config_data.hh | 68 +++ i/chuck/src/config/config_data.tcc | 59 ++ i/chuck/src/config/test_config.cc | 48 ++ i/chuck/src/data/Makefile.defs | 16 + i/chuck/src/data/data_buffer.cc | 130 ++++ i/chuck/src/data/data_buffer.hh | 83 +++ i/chuck/src/data/data_circular_buffer.cc | 123 ++++ i/chuck/src/data/data_circular_buffer.hh | 64 ++ i/chuck/src/data/data_input.cc | 37 ++ i/chuck/src/data/data_input.hh | 44 ++ i/chuck/src/data/data_input_file.cc | 46 ++ i/chuck/src/data/data_input_file.hh | 45 ++ i/chuck/src/data/data_input_zlib.cc | 84 +++ i/chuck/src/data/data_input_zlib.hh | 48 ++ i/chuck/src/data/data_output.cc | 34 ++ i/chuck/src/data/data_output.hh | 44 ++ i/chuck/src/data/test_data.cc | 56 ++ i/chuck/src/data/test_data_buffer.cc | 77 +++ i/chuck/src/data/test_data_circular_buffer.cc | 92 +++ i/chuck/src/es/Makefile.defs | 5 + i/chuck/src/es/es.cc | 752 ++++++++++++++++++++++++ i/chuck/src/es/es.hh | 207 +++++++ i/chuck/src/es/test_es.cc | 156 +++++ i/chuck/src/interpreter/Makefile.defs | 6 + i/chuck/src/interpreter/interpreter.cc | 127 ++++ i/chuck/src/interpreter/interpreter.hh | 90 +++ i/chuck/src/interpreter/interpreter.tcc | 142 +++++ i/chuck/src/interpreter/interpreter_parser.cc | 43 ++ i/chuck/src/interpreter/interpreter_parser.hh | 43 ++ i/chuck/src/interpreter/test_interpreter.cc | 139 +++++ i/chuck/src/log/Makefile.defs | 12 + i/chuck/src/log/data_circular_buffer_factory.cc | 72 +++ i/chuck/src/log/data_circular_buffer_factory.hh | 53 ++ i/chuck/src/log/log.cc | 130 ++++ i/chuck/src/log/log.hh | 82 +++ i/chuck/src/log/log_message.cc | 74 +++ i/chuck/src/log/log_message.hh | 55 ++ i/chuck/src/log/log_message.tcc | 36 ++ i/chuck/src/log/log_server.cc | 54 ++ i/chuck/src/log/log_server.hh | 50 ++ i/chuck/src/log/logger.cc | 52 ++ i/chuck/src/log/logger.hh | 68 +++ i/chuck/src/log/logger_file.cc | 144 +++++ i/chuck/src/log/logger_file.hh | 70 +++ i/chuck/src/log/logger_null.hh | 51 ++ i/chuck/src/log/logger_ram.cc | 98 +++ i/chuck/src/log/logger_ram.hh | 63 ++ i/chuck/src/log/logger_stdout.cc | 68 +++ i/chuck/src/log/logger_stdout.hh | 54 ++ i/chuck/src/log/test_log.cc | 53 ++ i/chuck/src/log/test_log_server.cc | 45 ++ i/chuck/src/motor/Makefile.defs | 5 + i/chuck/src/motor/motor.cc | 183 ++++++ i/chuck/src/motor/motor.hh | 86 +++ i/chuck/src/motor/test_motor.cc | 99 ++++ i/chuck/src/parser/Makefile.defs | 14 + i/chuck/src/parser/parser.cc | 189 ++++++ i/chuck/src/parser/parser.hh | 89 +++ i/chuck/src/parser/test_parser.cc | 86 +++ i/chuck/src/parser/yylexer.ll | 148 +++++ i/chuck/src/parser/yyparser.yy | 278 +++++++++ i/chuck/src/proto/Makefile.defs | 5 + i/chuck/src/proto/proto.cc | 457 ++++++++++++++ i/chuck/src/proto/proto.hh | 140 +++++ i/chuck/src/proto/test_proto.cc | 96 +++ i/chuck/src/scheduler/Makefile.defs | 7 + i/chuck/src/scheduler/schedulable.hh | 50 ++ i/chuck/src/scheduler/schedulable_alarm.cc | 56 ++ i/chuck/src/scheduler/schedulable_alarm.hh | 60 ++ i/chuck/src/scheduler/schedulable_read_fd.cc | 51 ++ i/chuck/src/scheduler/schedulable_read_fd.hh | 52 ++ i/chuck/src/scheduler/scheduler.cc | 103 ++++ i/chuck/src/scheduler/scheduler.hh | 53 ++ i/chuck/src/scheduler/test_scheduler.cc | 68 +++ i/chuck/src/serial/Makefile.defs | 5 + i/chuck/src/serial/serial.cc | 66 +++ i/chuck/src/serial/serial.hh | 64 ++ i/chuck/src/serial/serial_base.cc | 84 +++ i/chuck/src/serial/serial_base.hh | 68 +++ i/chuck/src/serial/serial_dev.cc | 168 ++++++ i/chuck/src/serial/serial_dev.hh | 54 ++ i/chuck/src/serial/serial_stdio.cc | 81 +++ i/chuck/src/serial/serial_stdio.hh | 48 ++ i/chuck/src/serial/test_serial.cc | 88 +++ i/chuck/src/socket/Makefile.defs | 12 + i/chuck/src/socket/address.cc | 93 +++ i/chuck/src/socket/address.hh | 76 +++ i/chuck/src/socket/server_socket.cc | 86 +++ i/chuck/src/socket/server_socket.hh | 48 ++ i/chuck/src/socket/socket_client.cc | 115 ++++ i/chuck/src/socket/socket_client.hh | 63 ++ i/chuck/src/socket/socket_databuffer.cc | 97 +++ i/chuck/src/socket/socket_databuffer.hh | 52 ++ i/chuck/src/socket/socket_server.cc | 90 +++ i/chuck/src/socket/socket_server.hh | 56 ++ i/chuck/src/socket/socket_text.cc | 236 ++++++++ i/chuck/src/socket/socket_text.hh | 80 +++ i/chuck/src/socket/test_server.cc | 91 +++ i/chuck/src/socket/test_socket.cc | 156 +++++ i/chuck/src/socket/test_socket_databuffer.cc | 125 ++++ i/chuck/src/socket/test_socket_old.cc | 76 +++ i/chuck/src/tester/Makefile.defs | 5 + i/chuck/src/tester/test_tester.cc | 78 +++ i/chuck/src/tester/tester.cc | 141 +++++ i/chuck/src/tester/tester.hh | 77 +++ i/chuck/src/timer/Makefile.defs | 5 + i/chuck/src/timer/test_timer.cc | 47 ++ i/chuck/src/timer/timer.cc | 89 +++ i/chuck/src/timer/timer.hh | 51 ++ i/chuck/src/utils/Makefile.defs | 11 + i/chuck/src/utils/any.hh | 125 ++++ i/chuck/src/utils/any.tcc | 185 ++++++ i/chuck/src/utils/bind.hh | 91 +++ i/chuck/src/utils/callback.hh | 96 +++ i/chuck/src/utils/callback.tcc | 140 +++++ i/chuck/src/utils/errno_exception.hh | 48 ++ i/chuck/src/utils/fd_set.cc | 53 ++ i/chuck/src/utils/fd_set.hh | 54 ++ i/chuck/src/utils/hexa.cc | 113 ++++ i/chuck/src/utils/hexa.hh | 49 ++ i/chuck/src/utils/list_ostream_output.hh | 62 ++ i/chuck/src/utils/mathutil.hh | 57 ++ i/chuck/src/utils/meta/Makefile.defs | 3 + i/chuck/src/utils/meta/is_equal.hh | 44 ++ i/chuck/src/utils/meta/is_string.hh | 45 ++ i/chuck/src/utils/meta/remove_reference.hh | 44 ++ i/chuck/src/utils/meta/test_meta.cc | 57 ++ i/chuck/src/utils/non_copyable.hh | 41 ++ i/chuck/src/utils/signalhandler.hh | 52 ++ i/chuck/src/utils/signalhandler.tcc | 66 +++ i/chuck/src/utils/test_any.cc | 50 ++ i/chuck/src/utils/test_bind.cc | 57 ++ i/chuck/src/utils/test_callback.cc | 84 +++ i/chuck/src/utils/test_signalhandler.cc | 15 + 148 files changed, 12932 insertions(+) create mode 100644 i/chuck/src/Makefile.defs create mode 100644 i/chuck/src/README create mode 100644 i/chuck/src/ai/Makefile.defs create mode 100644 i/chuck/src/ai/ai.cc create mode 100644 i/chuck/src/ai/ai.hh create mode 100644 i/chuck/src/ai/test_ai.cc create mode 100644 i/chuck/src/asserv/Makefile.defs create mode 100644 i/chuck/src/asserv/asserv.cc create mode 100644 i/chuck/src/asserv/asserv.hh create mode 100644 i/chuck/src/asserv/test_asserv.cc create mode 100644 i/chuck/src/config/Makefile.defs create mode 100644 i/chuck/src/config/config.cc create mode 100644 i/chuck/src/config/config.hh create mode 100644 i/chuck/src/config/config_data.cc create mode 100644 i/chuck/src/config/config_data.hh create mode 100644 i/chuck/src/config/config_data.tcc create mode 100644 i/chuck/src/config/test_config.cc create mode 100644 i/chuck/src/data/Makefile.defs create mode 100644 i/chuck/src/data/data_buffer.cc create mode 100644 i/chuck/src/data/data_buffer.hh create mode 100644 i/chuck/src/data/data_circular_buffer.cc create mode 100644 i/chuck/src/data/data_circular_buffer.hh create mode 100644 i/chuck/src/data/data_input.cc create mode 100644 i/chuck/src/data/data_input.hh create mode 100644 i/chuck/src/data/data_input_file.cc create mode 100644 i/chuck/src/data/data_input_file.hh create mode 100644 i/chuck/src/data/data_input_zlib.cc create mode 100644 i/chuck/src/data/data_input_zlib.hh create mode 100644 i/chuck/src/data/data_output.cc create mode 100644 i/chuck/src/data/data_output.hh create mode 100644 i/chuck/src/data/test_data.cc create mode 100644 i/chuck/src/data/test_data_buffer.cc create mode 100644 i/chuck/src/data/test_data_circular_buffer.cc create mode 100644 i/chuck/src/es/Makefile.defs create mode 100644 i/chuck/src/es/es.cc create mode 100644 i/chuck/src/es/es.hh create mode 100644 i/chuck/src/es/test_es.cc create mode 100644 i/chuck/src/interpreter/Makefile.defs create mode 100644 i/chuck/src/interpreter/interpreter.cc create mode 100644 i/chuck/src/interpreter/interpreter.hh create mode 100644 i/chuck/src/interpreter/interpreter.tcc create mode 100644 i/chuck/src/interpreter/interpreter_parser.cc create mode 100644 i/chuck/src/interpreter/interpreter_parser.hh create mode 100644 i/chuck/src/interpreter/test_interpreter.cc create mode 100644 i/chuck/src/log/Makefile.defs create mode 100644 i/chuck/src/log/data_circular_buffer_factory.cc create mode 100644 i/chuck/src/log/data_circular_buffer_factory.hh create mode 100644 i/chuck/src/log/log.cc create mode 100644 i/chuck/src/log/log.hh create mode 100644 i/chuck/src/log/log_message.cc create mode 100644 i/chuck/src/log/log_message.hh create mode 100644 i/chuck/src/log/log_message.tcc create mode 100644 i/chuck/src/log/log_server.cc create mode 100644 i/chuck/src/log/log_server.hh create mode 100644 i/chuck/src/log/logger.cc create mode 100644 i/chuck/src/log/logger.hh create mode 100644 i/chuck/src/log/logger_file.cc create mode 100644 i/chuck/src/log/logger_file.hh create mode 100644 i/chuck/src/log/logger_null.hh create mode 100644 i/chuck/src/log/logger_ram.cc create mode 100644 i/chuck/src/log/logger_ram.hh create mode 100644 i/chuck/src/log/logger_stdout.cc create mode 100644 i/chuck/src/log/logger_stdout.hh create mode 100644 i/chuck/src/log/test_log.cc create mode 100644 i/chuck/src/log/test_log_server.cc create mode 100644 i/chuck/src/motor/Makefile.defs create mode 100644 i/chuck/src/motor/motor.cc create mode 100644 i/chuck/src/motor/motor.hh create mode 100644 i/chuck/src/motor/test_motor.cc create mode 100644 i/chuck/src/parser/Makefile.defs create mode 100644 i/chuck/src/parser/parser.cc create mode 100644 i/chuck/src/parser/parser.hh create mode 100644 i/chuck/src/parser/test_parser.cc create mode 100644 i/chuck/src/parser/yylexer.ll create mode 100644 i/chuck/src/parser/yyparser.yy create mode 100644 i/chuck/src/proto/Makefile.defs create mode 100644 i/chuck/src/proto/proto.cc create mode 100644 i/chuck/src/proto/proto.hh create mode 100644 i/chuck/src/proto/test_proto.cc create mode 100644 i/chuck/src/scheduler/Makefile.defs create mode 100644 i/chuck/src/scheduler/schedulable.hh create mode 100644 i/chuck/src/scheduler/schedulable_alarm.cc create mode 100644 i/chuck/src/scheduler/schedulable_alarm.hh create mode 100644 i/chuck/src/scheduler/schedulable_read_fd.cc create mode 100644 i/chuck/src/scheduler/schedulable_read_fd.hh create mode 100644 i/chuck/src/scheduler/scheduler.cc create mode 100644 i/chuck/src/scheduler/scheduler.hh create mode 100644 i/chuck/src/scheduler/test_scheduler.cc create mode 100644 i/chuck/src/serial/Makefile.defs create mode 100644 i/chuck/src/serial/serial.cc create mode 100644 i/chuck/src/serial/serial.hh create mode 100644 i/chuck/src/serial/serial_base.cc create mode 100644 i/chuck/src/serial/serial_base.hh create mode 100644 i/chuck/src/serial/serial_dev.cc create mode 100644 i/chuck/src/serial/serial_dev.hh create mode 100644 i/chuck/src/serial/serial_stdio.cc create mode 100644 i/chuck/src/serial/serial_stdio.hh create mode 100644 i/chuck/src/serial/test_serial.cc create mode 100644 i/chuck/src/socket/Makefile.defs create mode 100644 i/chuck/src/socket/address.cc create mode 100644 i/chuck/src/socket/address.hh create mode 100644 i/chuck/src/socket/server_socket.cc create mode 100644 i/chuck/src/socket/server_socket.hh create mode 100644 i/chuck/src/socket/socket_client.cc create mode 100644 i/chuck/src/socket/socket_client.hh create mode 100644 i/chuck/src/socket/socket_databuffer.cc create mode 100644 i/chuck/src/socket/socket_databuffer.hh create mode 100644 i/chuck/src/socket/socket_server.cc create mode 100644 i/chuck/src/socket/socket_server.hh create mode 100644 i/chuck/src/socket/socket_text.cc create mode 100644 i/chuck/src/socket/socket_text.hh create mode 100644 i/chuck/src/socket/test_server.cc create mode 100644 i/chuck/src/socket/test_socket.cc create mode 100644 i/chuck/src/socket/test_socket_databuffer.cc create mode 100644 i/chuck/src/socket/test_socket_old.cc create mode 100644 i/chuck/src/tester/Makefile.defs create mode 100644 i/chuck/src/tester/test_tester.cc create mode 100644 i/chuck/src/tester/tester.cc create mode 100644 i/chuck/src/tester/tester.hh create mode 100644 i/chuck/src/timer/Makefile.defs create mode 100644 i/chuck/src/timer/test_timer.cc create mode 100644 i/chuck/src/timer/timer.cc create mode 100644 i/chuck/src/timer/timer.hh create mode 100644 i/chuck/src/utils/Makefile.defs create mode 100644 i/chuck/src/utils/any.hh create mode 100644 i/chuck/src/utils/any.tcc create mode 100644 i/chuck/src/utils/bind.hh create mode 100644 i/chuck/src/utils/callback.hh create mode 100644 i/chuck/src/utils/callback.tcc create mode 100644 i/chuck/src/utils/errno_exception.hh create mode 100644 i/chuck/src/utils/fd_set.cc create mode 100644 i/chuck/src/utils/fd_set.hh create mode 100644 i/chuck/src/utils/hexa.cc create mode 100644 i/chuck/src/utils/hexa.hh create mode 100644 i/chuck/src/utils/list_ostream_output.hh create mode 100644 i/chuck/src/utils/mathutil.hh create mode 100644 i/chuck/src/utils/meta/Makefile.defs create mode 100644 i/chuck/src/utils/meta/is_equal.hh create mode 100644 i/chuck/src/utils/meta/is_string.hh create mode 100644 i/chuck/src/utils/meta/remove_reference.hh create mode 100644 i/chuck/src/utils/meta/test_meta.cc create mode 100644 i/chuck/src/utils/non_copyable.hh create mode 100644 i/chuck/src/utils/signalhandler.hh create mode 100644 i/chuck/src/utils/signalhandler.tcc create mode 100644 i/chuck/src/utils/test_any.cc create mode 100644 i/chuck/src/utils/test_bind.cc create mode 100644 i/chuck/src/utils/test_callback.cc create mode 100644 i/chuck/src/utils/test_signalhandler.cc (limited to 'i/chuck/src') diff --git a/i/chuck/src/Makefile.defs b/i/chuck/src/Makefile.defs new file mode 100644 index 0000000..aa882b7 --- /dev/null +++ b/i/chuck/src/Makefile.defs @@ -0,0 +1,112 @@ +# Flags. +CXXFLAGS = -Wall -g +CPPFLAGS = -MMD $(INCLUDES) +INCLUDES = -I$(SRCDIR) -I. + +# Tests de coverage (man gcov). +ifeq ($(COV),) +CXXFLAGS += -O2 +else +CXXFLAGS += -fprofile-arcs -ftest-coverage +endif + +# Profiling (man gprof). +ifneq ($(PROF),) +CXXFLAGS += -pg +LDFLAGS += -pg +endif + +# Messages sur une ligne. +CXXFLAGS += -fmessage-length=0 + +SUBDIRS = utils utils/meta \ + parser \ + interpreter config tester \ + log serial timer \ + data scheduler \ + proto asserv es \ + motor socket ai + +# Répertoire où placer les objets. +OBJ_DIR := obj + + +# Utilise le compilateur C++ pour l'édition des liens. +LINK.o = $(CXX) $(LDFLAGS) $(TARGET_ARCH) +# Et les outils GNU pour lex et yacc. +LEX := flex +YACC := bison + +# Où trouver les sources, apdmc. +vpath %.cc $(SUBDIRS:%=$(SRCDIR)/%) $(EXTRA_SUBDIRS) +vpath %.ll $(SUBDIRS:%=$(SRCDIR)/%) $(EXTRA_SUBDIRS) +vpath %.yy $(SUBDIRS:%=$(SRCDIR)/%) $(EXTRA_SUBDIRS) + +# régle par défault. Le build-all permet de reporter à plus tard sa +# définition. +all: build-all + +# Inclus les autres répertoires. +include $(SUBDIRS:%=$(SRCDIR)/%/Makefile.defs) \ + $(EXTRA_SUBDIRS:%=%/Makefile.defs) + +OBJECTS := $(filter %.o,$(foreach PROGRAM,$(PROGRAMS),$($(PROGRAM)_OBJECTS))) +OBJECTS := $(OBJECTS:%.o=$(OBJ_DIR)/%.o) + +build-all: $(PROGRAMS) + +utest: $(UTESTS:%=%.utest) + +# Fabrique les règles pour créer les exécutables. +define PROGRAMS_template +$(1): $$($(1)_OBJECTS:%.o=$$(OBJ_DIR)/%.o) + $$(LINK.o) $$^ $$(LOADLIBES) $$(LDLIBS) -o $$@ +endef + +$(foreach prog,$(PROGRAMS),$(eval $(call PROGRAMS_template,$(prog)))) + +# Creation of utest rules +define UTESTS_template +ifndef $(1)_UTEST +$(1)_UTEST = PATH=$$(PATH):. $$^ +endif +$(1).utest: + @echo "$$($(1)_UTEST)"; \ + $$($(1)_UTEST); \ + RETVAL=$$$$?; \ + echo -n "$(1).utest: "; \ + if [ "$$$$RETVAL" -eq "0" ]; \ + then \ + echo "Succeed"; \ + else \ + echo "Failed"; \ + fi; \ + exit $$$$RETVAL +endef + +$(foreach utest,$(UTESTS),$(eval $(call UTESTS_template,$(utest)))) + +# Régles implicites. +%.cc: %.ll + $(LEX) $< + +%.cc: %.yy + $(YACC) -o $@ $< + +$(OBJ_DIR)/%.o: %.cc + @mkdir -p $(OBJ_DIR) + $(COMPILE.cc) $(OUTPUT_OPTION) $< + +# Dépendances. +-include $(OBJECTS:%.o=%.d) + +# Ménage. +clean: + rm -f $(OBJ_DIR)/*.o $(OBJ_DIR)/*.d $(PROGRAMS) + rm -f *.bbg *.bb *.da *.gcov + rm -f gmon.out + rm -f $(EXTRA_CLEAN) + rmdir --ignore-fail-on-non-empty $(OBJ_DIR) + +.PHONY: all build-all clean +.SUFFIXES: diff --git a/i/chuck/src/README b/i/chuck/src/README new file mode 100644 index 0000000..90d7926 --- /dev/null +++ b/i/chuck/src/README @@ -0,0 +1,25 @@ +marvin - programme du robot 2006. + +Programme du concours du robot qui envois les balle en haut... et dans les +trous aussi. + + +Copyright (C) 2006 Efrei Robotique + +Robot APB Team/Efrei 2006. + Web: http://assos.efrei.fr/robot/ + Email: robot AT efrei DOT fr + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. diff --git a/i/chuck/src/ai/Makefile.defs b/i/chuck/src/ai/Makefile.defs new file mode 100644 index 0000000..5016f06 --- /dev/null +++ b/i/chuck/src/ai/Makefile.defs @@ -0,0 +1,5 @@ +PROGRAMS += test_ai + +ai_OBJECTS = ai.o $(motor_OBJECTS) $(es_OBJECTS) $(scheduler_OBJECTS) + +test_ai_OBJECTS = test_ai.o $(ai_OBJECTS) $(tester_OBJECTS) diff --git a/i/chuck/src/ai/ai.cc b/i/chuck/src/ai/ai.cc new file mode 100644 index 0000000..c9be04a --- /dev/null +++ b/i/chuck/src/ai/ai.cc @@ -0,0 +1,511 @@ +// AI.CC +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Nicolas Haller +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: http://perso.efrei.fr/~haller/ +// Email: +// }}} +#include "ai.hh" +#include "config/config.hh" +#include "timer/timer.hh" + +#include + +/// Fonction callback useless +static void +callback (void) +{} + +//constructeur +Ai::Ai (const Config & config) + :es_(config), log_ ("Ai"), + schedulableMotor_(callback, motor_.getFd()), + schedulableEs_(callback, es_.getFd()), + round_duration_ (config.get ("ai.round_duration")), + schedule_time_ (config.get ("ai.schedule_time")), + reference_sensor_mask_ (config.get ("ai.ref_sensor_mask")) +{ + scheduler_.insert (schedulableMotor_); + scheduler_.insert (schedulableEs_); +} + +Ai::~Ai(void) +{ + // On réinitialise + // Initialise les moteurs + // XXX + motor_.reset (); + // initialise la carte es + es_.reset (); + // On sync + do + { + scheduler_.schedule (500, true); + } + while (!sync ()); +} + +// Initialisation du robal +void +Ai::init (void) +{ + // Initialisation de motor + motor_.reset (); + // Initialisation de la carte Es + es_.reset (); + // Paf on sync + while (!update ()); +} + +/// Stop the mouvement of the motor +void +Ai::stop (void) +{ + motor_.stop (); + // XXX In fact, we should wait a little here... + while (!update ()); +} + +/// Synchronize data of under class +bool +Ai::sync (void) +{ + bool motor = motor_.sync (); + bool es = es_.sync (); + return es && motor; +} + +/// Wait for something to happened +bool +Ai::update (void) +{ + /// Wait schedule_time + scheduler_.schedule (schedule_time_, true); + bool retour = sync (); + // On vérifie que le match n'est pas fini + if (Timer::getRoundTime () > round_duration_) + throw std::runtime_error ("End of match ! You win !"); + return retour; +} + +/// Function to wait a little but still syncing data +void +Ai::temporisation(int msec) +{ + // Get current time of process + int time = Timer::getProgramTime(); + time += msec; + // Update until we have spend enough time + do + { + update(); + } + while (time > Timer::getProgramTime()); +} + +/// Wait until jack is out (true) or in (false) +void +Ai::waitJack (bool out) +{ + do + { + update (); + } + while (es_.isJackOut () != out); +} + +/// Init things for a match. +void +Ai::prepare (void) +{ + es_.lcdPrint(""); + es_.lcdPrint("Prepa match..."); + es_.lcdPrint("Inserer Jack"); + es_.setOthersStat (10); + while (!update ()); + // XXX We should check if the jack is not already in + // We first wait for the jack to be put inside + waitJack (false); + // We reference all the color + referenceSensors (); + es_.barilletInit(); + es_.lcdPrint("Barillet pret ?"); + es_.lcdPrint("Virer le jack !"); + while (!update ()); + // We first wait for the jack to be put inside + waitJack (true); + // Set actual position + motor_.getAsserv().setPos(0,0,0); + // Ok the match begin ! Go go go ! + Timer::startRound (); + es_.setOthersStat (0); + // Shut up fucking beach ! + es_.setOthersStat (0); + es_.setOthersStat (0); + while (!update ()); +} + +/// Some after after a match +void +Ai::afterMatch(void) +{ + // On attend de mettre le jack après le match + es_.lcdPrint("FIN DU MATCH"); +// es_.lcdPrint("Inserer jack..."); + while (!update()); + waitJack(false); + // On vide le barillet + es_.barilletEmpty(); + es_.lcdPrint("Vidange barillet"); + while (!update()); + waitJack(true); + // On init les cartes histoire de + es_.reset(); + motor_.reset(); + es_.lcdPrint("Power off!!"); + while (!update()); +} + +/// Reference sensors +void +Ai::referenceSensors (void) +{ + // Reference sensors + es_.refColor (reference_sensor_mask_); + // Update data + while (!update ()); + // Disable capturing all sensors + es_.enableAllSensors (false); + // Update data + while (!update ()); +} + +/// programme d'homologation du robal +void Ai::progHomoloRobal(void) +{ + /// On init le robal + prepare(); + es_.barilletDebutLancement(); + while (!update ()); + temporisation (1000); + es_.barilletLancement(); + while (!update ()); + /// on avance un poil parce que le mur c'est mal + std::cout << "Move !" << std::endl; + motorMove(500, 0); + std::cout << "Rotate !" << std::endl; + motorRotate(-0.54); + std::cout << "Move !" << std::endl; + motorMove(1200, 0); + std::cout << "Rotate !" << std::endl; + motorRotate(1.40); + motorMove(500, 0); +// temporisation (100); + std::cout << "Find hole !" << std::endl; + motorBasicFindHole (); + + /// On tourne XXX +/// motorRotate(-M_PI/4); + /// On cherche au moins une balle (sinon c'est con) +/// motorMove(1000, 0); /// XXX Voir la distance + /// XXX Avancer d'une certaine facon pour choper des balles + /// XXX Ouais ba y'a encore ddes truc à faire là + /// On cherche un tru (repositionnement??) +/// motor_.lockGoodHole(); +/// while (!update ()); +/// motor_.findHole(); +/// while (!update ()); + /// On trouve un trou, chouette + /// Aspirer le trou + //es_.extraitBalle(); + /// mettre une baballe + es_.dropWhiteBall(); + while (!update ()); + temporisation (3000); + es_.deposeBalle (); + while (!update ()); + temporisation (3000); + motorMove(300, 0); + + std::cout << "Find hole !" << std::endl; + motorBasicFindHole (); + es_.dropWhiteBall(); + while (!update ()); + temporisation (3000); + es_.deposeBalle (); + while (!update ()); + temporisation (3000); + motorMove(300, 0); + /// Tourner 3 fois en chantant du Mickael Jackson + /// Again.... + /// Fin du match + afterMatch(); +} + +void +Ai::progMatch(void) +{ + double dummy, aStart, aEnd; + + // Init of cards + init (); + /// On prépare le robot + prepare(); + /// Faire des crêpes... + /// Init du barillet + es_.barilletDebutLancement(); + while (!update ()); + log_ ("match") << "Totem activator"; + es_.totemActivator (true); + /// En avant guingamp + log_ ("match") << "Eloignement du bord"; + motorMove(480,0); + es_.barilletLancement(); + while (!update ()); + /// On tourner de -90° + log_ ("match") << "Petite rotation de 90°"; + motorMove(216,-216); + /// On dit bonjour au mur + log_ ("match") << "Va à l'opposé"; + if (!motorMove (1000, 0)) + { + log_ ("match") << "Un mur ! Reculons"; + motorMove (-60, 0); + } + /// On tourne bizarrement mais de 90° + log_ ("match") << "On tourne à 90° en deux fois"; + motorMove(-36,36); + motorMove(180, 180); + /// On avance un peu + log_ ("match") << "On avance de l'autre coté"; + motorMove (1420, 0); + log_ ("match") << "On recule un peu"; + motorMove (-150, 0); + log_ ("match") << "On tourne"; + motorMove (216, 216); + motorMove (-150, 0); + + /* Here, we are in front of all our holes */ + + int rotationSens = 1; + const double distanceMax[2] = { -1600., 200. }; + // Force a turn back ! + double distanceCur, remainingDist; + int ret; + + /* Save angle */ + motor_.getPosition (dummy, dummy, aStart); + do + { + log_ ("match") << "Start loop for finding holes"; + + // Save Y position each time + motor_.getPosition (dummy, distanceCur, dummy); + + // Look for an hole ! + if (rotationSens % 2) + remainingDist = std::abs (distanceMax[1] - distanceCur); + else + remainingDist = std::abs (distanceMax[0] - distanceCur); + // Protection again stupid computing + if (remainingDist > 0.) + ret = motorSmartFindHole (remainingDist); + else + // Force a turn back ! + ret = 0; + switch (ret) + { + case 0: + // Here we should turn back in the other way + log_ ("match") << "Trop long, demi tour !"; + if (rotationSens % 2) + motor_.move (432, -432); + else + motor_.move (432, 432); + rotationSens++; + /* Compute the new angle */ + motor_.getPosition (dummy, dummy, aStart); + break; + case -2: + /// La couleur est unknown + log_ ("match") << "Hooooo une couleur de l'espace!!!!"; + // break; + case 2: + case 1: + { + log_ ("match") << "Ok on a une couleur!"; + bool retDrop; + //if (((ret == es_.blueColor_) && es_.isColorModeBlue () ) + // || ((ret != es_.blueColor_) && !es_.isColorModeBlue ())) + if (true) + { + // If it is our colour, put a white ball, + log_ ("match") << "C'est notre couleur -> drop white !"; + retDrop = es_.dropWhiteBall(); + while (!update ()); + if (retDrop) + { + log_ ("match") << "Tempo & depot!"; + temporisation (3000); + es_.deposeBalle (); + temporisation (1000); + while (!update ()); + } + } + else + { + // otherwise, put a black one. + log_ ("match") << "Pas notre couleur, drop noir!"; + retDrop = es_.dropBlackBall(); + while (!update ()); + if (retDrop) + { + log_ ("match") << "Tempo & depot!"; + temporisation (3000); + es_.deposeBalle (); + temporisation (1000); + while (!update ()); + } + } + // Put ourself back in the right direction + motor_.getPosition (dummy, dummy, aEnd); + log_ ("match") << "Remise en place de l'angle : " << aStart << " end " << aEnd; + motor_.rotate (aStart - aEnd); + } + break; + default: + log_ ("match") << "Hooooo on a default!!!!"; + break; + } + } while (true); + + afterMatch(); +} + +/// Avance le robal et dit si il a finit (true) ou si il a bloqué +bool +Ai::motorMove (int d, int a) +{ + motor_.move(d, a); /// XXX Voir la distance + do + { + update (); + } + while (!motor_.finish ()/* && !motor_.blocked()*/); + if(motor_.finish()) + return true; + return false; +} + +void +Ai::motorRotate (double d) +{ + motor_.rotate (d); + do + { + update (); + } + while (!motor_.finish ()); +} + +void +Ai::motorBasicFindHole (void) +{ + motor_.findHole (); + do + { + update (); + } + while (!motor_.finish ()); + es_.enableAllSensors (true); + es_.setRVBHoleStat (2); + temporisation (500); + log_ ("FindHole") << "We see" << es_.colorSeen (es_.holeRVB_) ; + es_.setRVBHoleStat (0); +} + +/// Renvoie une couleur définie dans es ou -1 si on s'est mangé un mur ou 0 si +/// distanceOut +int +Ai::motorSmartFindHole (double distOut) +{ + /// On sauvegarde la position actuelle + double bx, x, by, y, ba, a; + double dist; + motor_.getPosition(bx, by, ba); + /// on lance le robal à la recherche d'un tru + motor_.findHole(); + do + { + update(); + if (distOut != 0) + { + /// On regarde si on a pas atteint la distOut + motor_.getPosition(x, y, a); + /// XXX C'est propre ça? + dist = sqrt(((x - bx)*(x - bx)) + ((y - by)*(y - by))); + if (dist > distOut) + return 0; + } + /// on regarde si les capteurs voit un trou + if(es_.colorSeen(es_.leftFrontRVB_) == es_.redColor_ || + es_.colorSeen(es_.leftFrontRVB_) == es_.blueColor_) + { + // Si c'est le cas on repositionne le robot + motor_.stop(); + while(!update()); + // XXX Vérifier l'angle + motorRotate(0.21); + motor_.findHole(); + } + else if(es_.colorSeen(es_.rightFrontRVB_) == es_.redColor_ || + es_.colorSeen(es_.rightFrontRVB_) == es_.blueColor_) + { + // Si c'est le cas on repositionne le robot + motor_.stop(); + while(!update()); + // XXX Vérifier l'angle + log_ ("SmartFindHole") << "Rotation spéciale ho un trou sous le capteur"; + motorRotate(-0.21); + motor_.findHole(); + } + } + while (!motor_.finish() /*&& !motor_.blocked()*/); + /// On regarde si on a blocké +// if(motor_.blocked()) +// return -1; + if(motor_.finish()) + { + es_.enableAllSensors (true); + es_.setRVBHoleStat (2); + temporisation (500); + int ret = es_.colorSeen(es_.holeRVB_); + es_.setRVBHoleStat (0); + es_.enableAllSensors (false); + return ret; + } + /// XXX Le return qui ne doit jamais arriver normalement... + return 0; +} + +/// Procedure to unblock the robal +void +Ai::motorDeblock (void) +{ +} diff --git a/i/chuck/src/ai/ai.hh b/i/chuck/src/ai/ai.hh new file mode 100644 index 0000000..29598b4 --- /dev/null +++ b/i/chuck/src/ai/ai.hh @@ -0,0 +1,86 @@ +#ifndef ai_hh +#define ai_hh +// ai.hh +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Nicolas Haller +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: http://perso.efrei.fr/~haller/ +// Email: +// }}} +/// Intelligence supérieur(à celui d'une balle de ping-pong) artificielle +/// (comme une blonde) du robot. + +#include "motor/motor.hh" +#include "es/es.hh" +#include "scheduler/scheduler.hh" +#include "scheduler/schedulable_read_fd.hh" +#include "log/log.hh" + +class Ai +{ + private: + // Modules de contrôles du robot + Motor motor_; + Es es_; + /// Logger + Log log_; + // Le scheduler + scheduler::Scheduler scheduler_; + scheduler::SchedulableReadFd schedulableMotor_; + scheduler::SchedulableReadFd schedulableEs_; + // Paramètres générales du robot + const int round_duration_; + const int schedule_time_; + const int reference_sensor_mask_; + bool mustRotate_; + public: + /// Constructeur + Ai(const Config & config); + /// Destructeur du robot + ~Ai(void); + + /// Initialisation du robal + void init(void); + /// Arrête complêtement le robot + void stop(void); + /// Fonction de tempo + void temporisation (int msec); + /// Attend le jack rentre(false) ou sorte (true) + void waitJack (bool out); + /// Attend une mise à jour... + bool update (void); + /// La célèbre fonction sync + bool sync (void); + /// Init things for a match. + void prepare (void); + /// Some after after a match + void afterMatch(void); + /// Reference sensors + void referenceSensors (void); + /// programme d'homologation du robal + void progHomoloRobal(void); + /// programme de match du robal + void progMatch(void); + bool motorMove (int d, int a); + void motorRotate (double d); + void motorBasicFindHole (void); + int motorSmartFindHole (double distOut); + void motorDeblock(void); +}; +#endif // ai_hh diff --git a/i/chuck/src/ai/test_ai.cc b/i/chuck/src/ai/test_ai.cc new file mode 100644 index 0000000..6a7d09f --- /dev/null +++ b/i/chuck/src/ai/test_ai.cc @@ -0,0 +1,105 @@ +// test_ai.cc +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Dufour Jérémy +// +// Robot APB Team/Efrei 2004. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} + +#include "tester/tester.hh" +#include "ai/ai.hh" +#include "timer/timer.hh" + +class TestAi : public Tester +{ + private: + Ai ai_; + /// Called after each command + void postcall (void) + { + while (!ai_.update ()) + ; + } + /// Wait. + void wait (int ms) + { + int t, stop; + t = Timer::getProgramTime (); + stop = t + ms; + while (t < stop) + { + ai_.temporisation (stop - t); + t = Timer::getProgramTime (); + } + } + public: + TestAi(int argc, char ** argv) + :Tester(argc, argv), ai_(config_) + {} + void preRun (void) + { + Interpreter &interpreter = getInterpreter(); + // Add functions + interpreter.add("init", Interpreter::memFunc(ai_, &Ai::init), + "Initialise le robal(void)"); + interpreter.add("prepare", Interpreter::memFunc(ai_, &Ai::prepare), + "Lance la procédure pré-Match"); + interpreter.add("afterMatch", Interpreter::memFunc(ai_, + &Ai::afterMatch), + "Lance la procédure post match"); + interpreter.add("stop", Interpreter::memFunc(ai_, &Ai::stop), + "Stop le robal(void)"); + interpreter.add("tempo", Interpreter::memFunc(ai_, + &Ai::temporisation), + "On temporise(int msec)"); + interpreter.add("jack", Interpreter::memFunc(ai_, &Ai::waitJack), + "On attend que le jack sorte/rentre(bool sorte)"); + interpreter.add("sensors", Interpreter::memFunc(ai_, + &Ai::referenceSensors), + "Initialise les capteurs RVB(void)"); + interpreter.add("homologation", Interpreter::memFunc(ai_, + &Ai::progHomoloRobal), + "Programme d'homologation du robal"); + interpreter.add("match", Interpreter::memFunc(ai_, &Ai::progMatch), + "Programme de match qui déchire du robal"); + interpreter.add("findHoleBasic", Interpreter::memFunc(ai_, &Ai::motorBasicFindHole), + "Find a hole, basic version"); + interpreter.add ("_postcall", + Interpreter::memFunc (*this, &TestAi::postcall)); + } + void postRun(void) + { + // On init le robal histoire de ... + ai_.init(); + } +}; + +int main (int argc, char **argv) +{ + try + { + TestAi ta(argc, argv); + ta.run (); + } + catch (const std::exception &e) + { + std::cerr << e.what () << std::endl; + } +} diff --git a/i/chuck/src/asserv/Makefile.defs b/i/chuck/src/asserv/Makefile.defs new file mode 100644 index 0000000..22ffdb2 --- /dev/null +++ b/i/chuck/src/asserv/Makefile.defs @@ -0,0 +1,5 @@ +PROGRAMS += test_asserv + +asserv_OBJECTS = asserv.o $(proto_OBJECTS) + +test_asserv_OBJECTS = test_asserv.o $(asserv_OBJECTS) $(tester_OBJECTS) diff --git a/i/chuck/src/asserv/asserv.cc b/i/chuck/src/asserv/asserv.cc new file mode 100644 index 0000000..e196803 --- /dev/null +++ b/i/chuck/src/asserv/asserv.cc @@ -0,0 +1,387 @@ +// asserv.cc +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Nicolas Schodet +// +// Robot APB Team/Efrei 2006. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "asserv.hh" +#include "config/config.hh" + +#include + +/// Constructor. +Asserv::Asserv (Asserv::Receiver &receiver) + : proto_ (*this), receiver_ (receiver) +{ + // Get Config + Config &config = Config::getInstance (); + intervalCounterStat_ = config.get ("asserv.counter_stat", 0); + intervalPos_ = config.get ("asserv.pos_report"); + intervalSpeedStat_ = config.get ("asserv.speed_stat", 0); + intervalPosStat_ = config.get ("asserv.pos_stat", 0); + intervalPwmStat_ = config.get ("asserv.pwm_stat", 0); + intervalTimerStat_ = config.get ("asserv.timer_stat", 0); + intervalInPort_ = config.get ("asserv.in_port_report"); + footing_ = config.get ("asserv.footing"); + tAccel_ = config.get ("asserv.t_accel"); + aAccel_ = config.get ("asserv.a_accel"); + tMaxSpeed_ = config.get ("asserv.t_max_speed"); + aMaxSpeed_ = config.get ("asserv.a_max_speed"); + tMaxSpeedSlow_ = config.get ("asserv.t_max_speed_slow"); + aMaxSpeedSlow_ = config.get ("asserv.a_max_speed_slow"); + tkp_ = config.get ("asserv.tkp"); + tki_ = config.get ("asserv.tki"); + tkd_ = config.get ("asserv.tkd"); + akp_ = config.get ("asserv.akp"); + aki_ = config.get ("asserv.aki"); + akd_ = config.get ("asserv.akd"); + esat_ = config.get ("asserv.esat"); + isat_ = config.get ("asserv.isat"); + lInvertPwm_ = config.get ("asserv.l_invert_pwm"); + rInvertPwm_ = config.get ("asserv.r_invert_pwm"); + stepPerMm_ = config.get ("asserv.step_per_mm"); + tty_ = config.get ("asserv.tty"); + proto_.open (tty_); + reset (); +} + +/// Essaie de purger la liste d'émission et indique si elle est vide. +bool +Asserv::sync (void) +{ + return proto_.sync (); +} + +/// Attend que toute les émissions soit terminées. +bool +Asserv::wait (int timeout/*-1*/) +{ + return proto_.wait (timeout); +} + +/// Récupère le File Descriptor +int +Asserv::getFd (void) const +{ + return proto_.getFd (); +} + +/// Reset the board and send parameters. +void +Asserv::reset (void) +{ + proto_.send ('z'); + setIntervalCounterStat (intervalCounterStat_); + setIntervalPos (intervalPos_); + setIntervalSpeedStat (intervalSpeedStat_); + setIntervalPosStat (intervalPosStat_); + setIntervalPwmStat (intervalPwmStat_); + setIntervalTimerStat (intervalTimerStat_); + setIntervalInPort (intervalInPort_); + setFooting (footing_); + setAccel (tAccel_, aAccel_); + setMaxSpeed (tMaxSpeed_, aMaxSpeed_, tMaxSpeedSlow_, aMaxSpeedSlow_); + setCoef (tkp_, tki_, tkd_, akp_, akd_, akd_, esat_, isat_); + setPwmDir (lInvertPwm_, rInvertPwm_); +} + +/// Set PWM. +void +Asserv::pwm (int l, int r) +{ + proto_.send ('w', "ww", l, r); +} + +/// Position consign offset. +void +Asserv::offset (double t, double a) +{ + proto_.send ('c', "ww", mmToStep (t), mmToStep (a)); +} + +/// Set speed. +void +Asserv::speed (int t, int a) +{ + proto_.send ('s', "bb", t, a); +} + +/// Speed controlled position consign offset. +void +Asserv::speedTo (double t, double a, int seq) +{ + proto_.send ('s', "ddb", mmToStep (t), mmToStep (a), seq); +} + +/// Speed controlled angle consign offset. +void +Asserv::speedAngle (double a, int seq) +{ + proto_.send ('s', "ddb", 0, radToStep (a), seq); +} + +/// Find a hole. +void +Asserv::findHole (int seq) +{ + proto_.send ('h', "b", seq); +} + +/// Acknoledge. +void +Asserv::ack (int seq) +{ + proto_.send ('a', "b", seq); +} + +/// Change counter stat interval. +void +Asserv::setIntervalCounterStat (int i) +{ + intervalCounterStat_ = i; + proto_.send ('C', "b", i); +} + +/// Change position report interval. +void +Asserv::setIntervalPos (int i) +{ + intervalPos_ = i; + proto_.send ('X', "b", i); +} + +/// Change speed stat interval. +void +Asserv::setIntervalSpeedStat (int i) +{ + intervalSpeedStat_ = i; + proto_.send ('S', "b", i); +} + +/// Change position control stat interval. +void +Asserv::setIntervalPosStat (int i) +{ + intervalPosStat_ = i; + proto_.send ('P', "b", i); +} + +/// Change pwm stat interval. +void +Asserv::setIntervalPwmStat (int i) +{ + intervalPwmStat_ = i; + proto_.send ('W', "b", i); +} + +/// Change timer stat interval. +void +Asserv::setIntervalTimerStat (int i) +{ + intervalTimerStat_ = i; + proto_.send ('T', "b", i); +} + +/// Change input port report interval. +void +Asserv::setIntervalInPort (int i) +{ + intervalInPort_ = i; + proto_.send ('I', "b", i); +} + +/// Set current position. +void +Asserv::setPos (double x, double y, double a) +{ + setXPos (x); + setYPos (y); + setAngle (a); +} + +/// Set current x position. +void +Asserv::setXPos (double x) +{ + proto_.send ('p', "bd", 'X', mmToStep (x)); +} + +/// Set current y position. +void +Asserv::setYPos (double y) +{ + proto_.send ('p', "bd", 'Y', mmToStep (y)); +} + +/// Set current angle. +void +Asserv::setAngle (double a) +{ + proto_.send ('p', "bd", 'A', radToAvr (a)); +} + +/// Set footing. +void +Asserv::setFooting (int f) +{ + footing_ = f; + proto_.send ('p', "bw", 'f', f); +} + +/// Set acceleration. +void +Asserv::setAccel (int t, int a) +{ + tAccel_ = t; + aAccel_ = a; + proto_.send ('p', "bww", 'a', t, a); +} + +/// Set maximum speed for automatic movements. +void +Asserv::setMaxSpeed (int t, int a, int ts, int as) +{ + tMaxSpeed_ = t; + aMaxSpeed_ = a; + tMaxSpeedSlow_ = ts; + aMaxSpeedSlow_ = as; + proto_.send ('p', "bbbbb", 's', t, a, ts, as); +} + +/// Set motor control coeficients. +void +Asserv::setCoef (int tkp, int tki, int tkd, int akp, int aki, int akd, + int esat, int isat) +{ + tkp_ = tkp; + tki_ = tki; + tkd_ = tkd; + akp_ = akp; + aki_ = aki; + akd_ = akd; + esat_ = esat; + isat_ = isat; + proto_.send ('p', "bww", 'p', tkp, akp); + proto_.send ('p', "bww", 'i', tki, aki); + proto_.send ('p', "bww", 'd', tkd, akd); + proto_.send ('p', "bw", 'E', esat); + proto_.send ('p', "bw", 'I', isat); +} + +/// Set PWM direction. +void +Asserv::setPwmDir (bool invertL, bool invertR) +{ + lInvertPwm_ = invertL; + rInvertPwm_ = invertR; + proto_.send ('p', "bbb", 'w', invertL ? 1 : 0, invertR ? 1 : 0); +} + +/// Store to eeprom. +void +Asserv::storeParams (void) +{ + proto_.send ('p', "bb", 'E', 1); +} + +/// Clear eeprom. +void +Asserv::clearParams (void) +{ + proto_.send ('p', "bb", 'E', 0); +} + +/// Implémentation du proto::Receiver. +void +Asserv::receive (char command, const Proto::Frame &frame) +{ + int seq, l, r, x, y, a, t, te, ti, ae, ai, port; + switch (command) + { + case 'A': + if (proto_.decode (frame, "b", seq)) + receiver_.receiveAck (seq); + break; + case 'C': + if (proto_.decode (frame, "ww", l, r)) + receiver_.receiveCounterStat (l, r); + break; + case 'X': + if (proto_.decode (frame, "DDD", x, y, a)) + receiver_.receivePos (stepToMm (x / 256), stepToMm (y / 256), avrToRad (a)); + break; + case 'S': + if (proto_.decode (frame, "BB", t, a)) + receiver_.receiveSpeedStat (t, a); + break; + case 'P': + if (proto_.decode (frame, "WWWW", te, ti, ae, ai)) + receiver_.receivePosStat (te, ti, ae, ai); + break; + case 'W': + if (proto_.decode (frame, "WW", l, r)) + receiver_.receivePwmStat (l, r); + break; + case 'T': + // TODO (si on a le temps). + break; + case 'I': + if (proto_.decode (frame, "w", port)) + receiver_.receiveInPort (port); + break; + } +} + +/// Convert mm to steps. +int +Asserv::mmToStep (double mm) const +{ + return static_cast (mm * stepPerMm_); +} + +/// Convert steps to mm. +double +Asserv::stepToMm (int step) const +{ + return static_cast (step) / stepPerMm_; +} + +/// Convert rad to avr angles. +int +Asserv::radToAvr (double a) const +{ + return static_cast (a * M_1_PI * 0.5 * (1 << 24)) & 0xffffff; +} + +/// Convert avr angles to rad. +double +Asserv::avrToRad (int a) const +{ + return static_cast (a) * 2 * M_PI / (1 << 24); +} + +/// Convert rad to steps. +int +Asserv::radToStep (double a) const +{ + return static_cast (static_cast (footing_) * a * 0.5); +} + diff --git a/i/chuck/src/asserv/asserv.hh b/i/chuck/src/asserv/asserv.hh new file mode 100644 index 0000000..ddbc104 --- /dev/null +++ b/i/chuck/src/asserv/asserv.hh @@ -0,0 +1,141 @@ +#ifndef asserv_hh +#define asserv_hh +// asserv.hh +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Nicolas Schodet +// +// Robot APB Team/Efrei 2006. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} + +#include "proto/proto.hh" + +/// Dialog class with the motor control board. +/// Units: +/// - step: one step distance. +/// - period: one motor control sampling period. +class Asserv : public Proto::Receiver +{ + public: + /// Asserv clients must implement Receiver. + class Receiver + { + public: + virtual ~Receiver (void) { } + virtual void receiveAck (int seq) = 0; + virtual void receiveCounterStat (int l, int r) = 0; + virtual void receivePos (double x, double y, double a) = 0; + virtual void receiveSpeedStat (int t, int a) = 0; + virtual void receivePosStat (int te, int ti, int ae, int ai) = 0; + virtual void receivePwmStat (int l, int r) = 0; + virtual void receiveTimerStat (const int *t, int tn) = 0; + virtual void receiveInPort (unsigned int port) = 0; + }; + private: + Proto proto_; + std::string tty_; + Receiver &receiver_; + int intervalCounterStat_, intervalPos_, intervalSpeedStat_, + intervalPosStat_, intervalPwmStat_, intervalTimerStat_, + intervalInPort_; + int footing_; + int tAccel_, aAccel_; + int tMaxSpeed_, aMaxSpeed_, tMaxSpeedSlow_, aMaxSpeedSlow_; + int tkp_, tki_, tkd_, akp_, aki_, akd_, esat_, isat_; + bool lInvertPwm_, rInvertPwm_; + double stepPerMm_; + public: + /// Constructor. + Asserv (Asserv::Receiver &receiver); + /// Essaie de purger la liste d'émission et indique si elle est vide. + bool sync (void); + /// Attend que toute les émissions soit terminées. + bool wait (int timeout = -1); + /// Récupère le File Descriptor + int getFd (void) const; + /// Reset the board and send parameters. + void reset (void); + /// Set PWM. + void pwm (int l, int r); + /// Position consign offset. + void offset (double t, double a); + /// Set speed. + void speed (int t, int a); + /// Speed controlled position consign offset. + void speedTo (double t, double a, int seq); + /// Speed controlled angle consign offset. + void speedAngle (double a, int seq); + /// Find a hole. + void findHole (int seq); + /// Acknoledge. + void ack (int seq); + /// Change counter stat interval. + void setIntervalCounterStat (int i); + /// Change position report interval. + void setIntervalPos (int i); + /// Change speed stat interval. + void setIntervalSpeedStat (int i); + /// Change position control stat interval. + void setIntervalPosStat (int i); + /// Change pwm stat interval. + void setIntervalPwmStat (int i); + /// Change timer stat interval. + void setIntervalTimerStat (int i); + /// Change input port report interval. + void setIntervalInPort (int i); + /// Set current position. + void setPos (double x, double y, double a); + /// Set current x position. + void setXPos (double x); + /// Set current y position. + void setYPos (double y); + /// Set current angle. + void setAngle (double a); + /// Set footing. + void setFooting (int f); + /// Set acceleration. + void setAccel (int t, int a); + /// Set maximum speed for automatic movements. + void setMaxSpeed (int t, int a, int ts, int as); + /// Set motor control coeficients. + void setCoef (int tkp, int tki, int tkd, int akp, int aki, int akd, + int esat, int isat); + /// Set PWM direction. + void setPwmDir (bool invertL, bool invertR); + /// Store to eeprom. + void storeParams (void); + /// Clear eeprom. + void clearParams (void); + /// Implémentation du proto::Receiver. + void receive (char command, const Proto::Frame &frame); + private: + /// Convert mm to steps. + int mmToStep (double mm) const; + /// Convert steps to mm. + double stepToMm (int step) const; + /// Convert rad to avr angles. + int radToAvr (double a) const; + /// Convert avr angles to rad. + double avrToRad (int a) const; + /// Convert rad to steps. + int radToStep (double a) const; +}; + +#endif // asserv_hh diff --git a/i/chuck/src/asserv/test_asserv.cc b/i/chuck/src/asserv/test_asserv.cc new file mode 100644 index 0000000..2796e33 --- /dev/null +++ b/i/chuck/src/asserv/test_asserv.cc @@ -0,0 +1,197 @@ +// test_asserv.cc +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "asserv.hh" +#include "tester/tester.hh" +#include "timer/timer.hh" + +#include +#include +#include + +class TestAsserv : public Tester, public Asserv::Receiver +{ + private: + Asserv asserv_; + int seq_; + bool ok_; + public: + /// Constructor. + TestAsserv (int argc, char **argv) + : Tester (argc, argv), asserv_ (*this), seq_ (0), ok_ (true) + { } + /// Next seq number. + inline void nextSeq (void) + { + seq_++; + if (seq_ > 100) + seq_ = 1; + } + /// Speed controlled position consign offset, handle seq. + void speedTo (double t, double a) + { + nextSeq (); + ok_ = false; + asserv_.speedTo (t, a, seq_); + } + /// Speed controlled angle consign offset, handle seq. + void speedAngle (double a) + { + nextSeq (); + ok_ = false; + asserv_.speedAngle (a, seq_); + } + /// Find a hole, handle seq. + void findHole (void) + { + nextSeq (); + ok_ = false; + asserv_.findHole (seq_); + } + /// Wait. + void wait (int ms) + { + int t, stop; + t = Timer::getProgramTime (); + stop = t + ms; + while (t < stop) + { + asserv_.wait (stop - t); + t = Timer::getProgramTime (); + } + } + /// Called after each command called. + void postcall (void) + { + while (!asserv_.wait () || !ok_) + ; + } + /// Executed before checking/running commands. Good place to add command + /// to the interpreter. + void preRun (void) + { + Interpreter &i = getInterpreter (); + i.add ("wait", Interpreter::memFunc (*this, &TestAsserv::wait), + "wait MS\nwait for a delay in millisecond"); + i.add ("reset", Interpreter::memFunc (asserv_, &Asserv::reset), + "reset\nreset the asserv board"); + i.add ("pwm", Interpreter::memFunc (asserv_, &Asserv::pwm), + "pwm LEFT RIGHT\n" + "directly set pwm values, use with caution"); + i.add ("offset", Interpreter::memFunc (asserv_, &Asserv::offset), + "offset THETA(mm) ALPHA(mm)\n" + "add value to current position, use for pid callibration"); + i.add ("speed", Interpreter::memFunc (asserv_, &Asserv::speed), + "speed THETA ALPHA\n" + "unlimited speed consign"); + i.add ("speedTo", Interpreter::memFunc (*this, &TestAsserv::speedTo), + "speedTo THETA(mm) ANGLE(mm)\n" + "speed consign limited in distance"); + i.add ("speedAngle", + Interpreter::memFunc (*this, &TestAsserv::speedAngle), + "speedAngle ANGLE(rad)\n" + "speed consign limited in angle"); + i.add ("findHole", Interpreter::memFunc (*this, &TestAsserv::findHole), + "findHole\nfind a hole"); + i.add ("setPos", Interpreter::memFunc (asserv_, &Asserv::setPos), + "setPos X(mm) Y(mm) A(rad)\n" + "set current position"); + i.add ("setXPos", Interpreter::memFunc (asserv_, &Asserv::setYPos), + "setPos X(mm)\n" + "set current X position"); + i.add ("setYPos", Interpreter::memFunc (asserv_, &Asserv::setXPos), + "setPos Y(mm)\n" + "set current Y position"); + i.add ("setAngle", Interpreter::memFunc (asserv_, &Asserv::setAngle), + "setPos A(rad)\n" + "set current angle"); + i.add ("storeParams", + Interpreter::memFunc (asserv_, &Asserv::storeParams), + "storeParams\nstore parameters to eeprom"); + i.add ("clearParams", + Interpreter::memFunc (asserv_, &Asserv::clearParams), + "clearParams\nclear parameters stored in eeprom"); + i.add ("_postcall", + Interpreter::memFunc (*this, &TestAsserv::postcall)); + } + /// Executed after running commands. + void postRun (void) + { + asserv_.reset (); + } + void receiveAck (int seq) + { + if ((seq & 0x7f) == seq_) + { + std::cout << "ack received" << std::endl; + asserv_.ack (seq); + ok_ = true; + } + } + void receiveCounterStat (int l, int r) + { + std::cout << "C " << l << ' ' << r << std::endl; + } + void receivePos (double x, double y, double a) + { + std::cout << "X " << x << ' ' << y << ' ' << a << std::endl; + } + void receiveSpeedStat (int t, int a) + { + std::cout << "S " << t << ' ' << a << std::endl; + } + void receivePosStat (int te, int ti, int ae, int ai) + { + std::cout << "P " << te << ' ' << ti << ' ' << ae << ' ' << ai << + std::endl; + } + void receivePwmStat (int l, int r) + { + std::cout << "W " << l << ' ' << r << std::endl; + } + void receiveTimerStat (const int *t, int tn) + { + std::cout << "T "; + std::copy (t, t + tn, std::ostream_iterator (std::cout, " ")); + } + void receiveInPort (unsigned int port) + { + std::cout << "I " << std::hex << std::setw (4) << std::setfill ('0') + << port << std::dec << std::endl; + } +}; + +int +main (int argc, char **argv) +{ + try + { + TestAsserv ta (argc, argv); + ta.run (); + } + catch (const std::exception &e) + { + std::cerr << e.what () << std::endl; + } +} diff --git a/i/chuck/src/config/Makefile.defs b/i/chuck/src/config/Makefile.defs new file mode 100644 index 0000000..a06f2a7 --- /dev/null +++ b/i/chuck/src/config/Makefile.defs @@ -0,0 +1,5 @@ +PROGRAMS += test_config + +config_OBJECTS = config_data.o config.o $(parser_OBJECTS) + +test_config_OBJECTS = $(config_OBJECTS) test_config.o diff --git a/i/chuck/src/config/config.cc b/i/chuck/src/config/config.cc new file mode 100644 index 0000000..333bd4a --- /dev/null +++ b/i/chuck/src/config/config.cc @@ -0,0 +1,27 @@ +// config.cc +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Dufour Jérémy +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: %WEB% +// Email: +// }}} +#include "config.hh" + + +Config *Config::instance_ = 0; diff --git a/i/chuck/src/config/config.hh b/i/chuck/src/config/config.hh new file mode 100644 index 0000000..3034b1a --- /dev/null +++ b/i/chuck/src/config/config.hh @@ -0,0 +1,98 @@ +#ifndef config_hh +#define config_hh +// config.hh +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Nicolas Schodet +// +// Robot APB Team/Efrei 2006. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "config_data.hh" +#include + +#include + +/// Classe d'accés à la configuration. +/// Singleton, created by hand. +class Config +{ + ConfigData configData_; + public: + typedef std::list IntList; + typedef std::list FloatList; + typedef std::list StringList; + private: + static Config *instance_; + public: + /// Boa constricteur, voir ConfigData. + Config (int &argc, char **&argv) + : configData_ (argc, argv) + { + create (); + } + /// Boa constricteur, voir ConfigData. + Config (int &argc, char **&argv, const std::string &file) + : configData_ (argc, argv, file) + { + create (); + } + /// Check and fill the private instance_ variables for singleton + void create () + { + if (instance_) + throw std::runtime_error ("Config already created"); + instance_ = this; + } + + /// Récupère une valeur de configuration, fonction générique. + template + const T &get (const std::string &id) const + { + return configData_.get (id); + } + /// Récupère une valeur de configuration, fonction générique avec valeur + /// par défaut pour éviter l'exception en cas d'abscence de valeur. + template + const T &get (const std::string &id, const T &defaut) const + { + return configData_.get (id, defaut); + } + /// Récupère une valeur de configuration. + const any &get (const std::string &id) const + { + return configData_.get (id); + } + /// Récupère une valeur de configuration avec valeur par défaut pour + /// éviter le renvoie d'exception. + const any &get (const std::string &id, const any &defaut) const + { + return configData_.get (id, defaut); + } + /// Get the unique instance of the class + static inline Config & + getInstance () + { + if (!instance_) + throw std::runtime_error ("Config not created"); + return *instance_; + } +}; + +#endif // config_hh diff --git a/i/chuck/src/config/config_data.cc b/i/chuck/src/config/config_data.cc new file mode 100644 index 0000000..e4dcf75 --- /dev/null +++ b/i/chuck/src/config/config_data.cc @@ -0,0 +1,148 @@ +// config_data.cc +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Nicolas Schodet +// +// Robot APB Team/Efrei 2006. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "config.hh" +#include "config_data.hh" +#include "parser/parser.hh" + +#include + +/// Constructeur. Traite les arguments de la ligne de commande et lit le +/// fichier de configuration. Les arguments traités sont retiré de la +/// ligne de commande. +ConfigData::ConfigData (int &argc, char **&argv) +{ + init (argc, argv, "rc/config"); +} + +/// Constructeur. Fourni en plus un fichier de configuration différent de +/// celui par défaut. +ConfigData::ConfigData (int &argc, char **&argv, const std::string &file) +{ + init (argc, argv, file); +} + +/// Récupère une valeur de configuration. +const any & +ConfigData::get (const std::string &id) const +{ + Data::const_iterator i = data_.find (id); + if (i == data_.end ()) + throw std::runtime_error (id + ": config item not found"); + return i->second; +} + +/// Récupère une valeur de configuration avec une valeur par défaut. Ne +/// renvoye pas d'exception. +const any & +ConfigData::get (const std::string &id, const any &defaut) const +{ + Data::const_iterator i = data_.find (id); + // If not found, return default values + if (i == data_.end ()) + return defaut; + else + return i->second; +} + +/// Ajoute une valeur de configuration. VAL prend l'ancienne valeur ou un any +/// vide. +void +ConfigData::add (const std::string &id, any &val) +{ + any &a = data_[id]; + a.swap (val); +} + +/// Classe dérivé de Parser pour le parsing de conf. +class ConfigParser : public Parser +{ + ConfigData &data_; + public: + /// Constructeur. + ConfigParser (ConfigData &data) : data_ (data) { } + /// Fonction appelée lors d'une affectation. VAL peut être modifié, il est + /// détruit suite à l'appel. + virtual void assign (const std::string &id, any &val) + { + data_.add (id, val); + } +}; + +/// Initialise (lit la ligne de commande et les fichiers de config. +void +ConfigData::init (int &argc, char **&argv, const std::string &file) +{ + std::string configFile (file); + std::string configString; + // Parse la ligne de commande. + for (int i = 1; i < argc; ) + { + int del = 0; + // -F CONFIG_FILE + if (argv[i][0] == '-' && argv[i][1] == 'F') + { + if (argv[i][2] != '\0') + { + del = 1; + configFile = &argv[i][2]; + } + else if (i + 1 < argc) + { + del = 2; + configFile = argv[i + 1]; + } + } + // -C CONFIG_STRING + if (argv[i][0] == '-' && argv[i][1] == 'C') + { + configString += ';'; + if (argv[i][2] != '\0') + { + del = 1; + configString += &argv[i][2]; + } + else if (i + 1 < argc) + { + del = 2; + configString += argv[i + 1]; + } + } + // Supprime ces arguments de la liste. + if (del) + { + for (int j = i; j < argc - del + 1; j++) + argv[j] = argv[j + del]; + argc -= del; + } + else + i++; + } + // Lit le fichier de config. + ConfigParser p (*this); + p.parseFile (configFile); + // Parse les chaînes supplémentaires. + p.parseString (configString); +} + diff --git a/i/chuck/src/config/config_data.hh b/i/chuck/src/config/config_data.hh new file mode 100644 index 0000000..51caabd --- /dev/null +++ b/i/chuck/src/config/config_data.hh @@ -0,0 +1,68 @@ +#ifndef config_data_hh +#define config_data_hh +// config_data.hh +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Nicolas Schodet +// +// Robot APB Team/Efrei 2006. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "utils/any.hh" + +#include +#include + +/// Classe contenant les informations de configuration. +class ConfigData +{ + typedef std::map Data; + Data data_; + public: + /// Constructeur. Traite les arguments de la ligne de commande et lit le + /// fichier de configuration. Les arguments traités sont retiré de la + /// ligne de commande. + ConfigData (int &argc, char **&argv); + /// Constructeur. Fourni en plus un fichier de configuration différent de + /// celui par défaut. + ConfigData (int &argc, char **&argv, const std::string &file); + /// Récupère une valeur de configuration, fonction générique. + template + const T &get (const std::string &id) const; + /// Récupère une valeur de configuration, fonction générique avec valeur + /// par défaut. Cette fonction ne renvoie d'exception que si il y a un + /// problème de type et non de valeur non existante. + template + const T &get (const std::string &id, const T &defaut) const; + /// Récupère une valeur de configuration. + const any &get (const std::string &id) const; + /// Récupère une valeur de configuration avec une valeur par défaut. Ne + /// renvoye pas d'exception. + const any &get (const std::string &id, const any &defaut) const; + /// Ajoute une valeur de configuration. VAL prend l'ancienne valeur ou un + /// any vide. + void add (const std::string &id, any &val); + private: + /// Initialise (lit la ligne de commande et les fichiers de config. + void init (int &argc, char **&argv, const std::string &file); +}; + +#include "config_data.tcc" + +#endif // config_data_hh diff --git a/i/chuck/src/config/config_data.tcc b/i/chuck/src/config/config_data.tcc new file mode 100644 index 0000000..71fa6d6 --- /dev/null +++ b/i/chuck/src/config/config_data.tcc @@ -0,0 +1,59 @@ +// config_data.tcc +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Nicolas Schodet +// +// Robot APB Team/Efrei 2006. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} + +#include + +/// Récupère une valeur de configuration, fonction générique. +template +const T & +ConfigData::get (const std::string &id) const +{ + const any &a = get (id); + const T *v = any_cast (&a); + if (!v) + throw std::runtime_error (id + ": config item with bad type"); + return *v; +} + +/// Récupère une valeur de configuration, fonction générique avec valeur +/// par défaut. Cette fonction ne renvoie d'exception que si il y a un +/// problème de type et non de valeur non existante. +template +const T & +ConfigData::get (const std::string &id, const T &defaut) const +{ + // Construct an empty any + any empty; + // Get the value with an empty one by default + const any &a = get (id, empty); + // Empty value returned, not found + if (a.empty ()) + return defaut; + const T *v = any_cast (&a); + if (!v) + throw std::runtime_error (id + ": config item with bad type"); + return *v; +} + diff --git a/i/chuck/src/config/test_config.cc b/i/chuck/src/config/test_config.cc new file mode 100644 index 0000000..3b3e368 --- /dev/null +++ b/i/chuck/src/config/test_config.cc @@ -0,0 +1,48 @@ +// test_config.cc +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Nicolas Schodet +// +// Robot APB Team/Efrei 2006. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "config.hh" + +#include +#include + +int +main (int argc, char **argv) +{ + try + { + // Create manually the instance of the config class + Config c (argc, argv); + // Example for getting the unique instance + Config &ci = Config::getInstance (); + for (int i = 1; i < argc; ++i) + std::cout << ci.get (argv[i]) << std::endl; + } + catch (const std::exception &e) + { + std::cerr << e.what () << std::endl; + return 1; + } + return 0; +} diff --git a/i/chuck/src/data/Makefile.defs b/i/chuck/src/data/Makefile.defs new file mode 100644 index 0000000..c0fe78d --- /dev/null +++ b/i/chuck/src/data/Makefile.defs @@ -0,0 +1,16 @@ +PROGRAMS += test_data test_data_buffer test_data_circular_buffer + +data_OBJECTS = data_input.o data_input_file.o data_input_zlib.o \ + data_buffer.o data_output.o data_circular_buffer.o -lz + +test_data_OBJECTS = test_data.o $(data_OBJECTS) + +test_data_buffer_OBJECTS = test_data_buffer.o data_buffer.o + +test_data_circular_buffer_OBJECTS = test_data_circular_buffer.o data_circular_buffer.o + +#UTESTS += data + +#data.utest: test_data + +#data_UTEST = ./test_data /tmp/toto.tar.gz > /dev/null diff --git a/i/chuck/src/data/data_buffer.cc b/i/chuck/src/data/data_buffer.cc new file mode 100644 index 0000000..c0d8cef --- /dev/null +++ b/i/chuck/src/data/data_buffer.cc @@ -0,0 +1,130 @@ +// data_buffer.cc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Dufour Jérémy +// +// Robot APB Team/Efrei 2004. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "data_buffer.hh" + +#include // std::memcpy +#include // std::runtime_error +#include // std::swap + +static const unsigned min_size = 10; + +/// Constructeur par defaut +DataBuffer::DataBuffer (void) + : size_ (min_size), headPos_ (0), tailPos_ (0), type_ (NoType) +{ + buffer_ = new uint8_t [size_]; +} + +/// Constructeur par recopie. +DataBuffer::DataBuffer (const DataBuffer &d) + : headPos_ (0), type_ (NoType) +{ + unsigned sizeUse = d.tailPos_ - d.headPos_; + size_ = tailPos_ = sizeUse; + type_ = d.type_; + buffer_ = new uint8_t [size_]; + std::memcpy (buffer_, &d.buffer_[headPos_], sizeUse); +} + +/// Constructeur avec données. +DataBuffer::DataBuffer (uint8_t *data, unsigned size, unsigned sizeAllocated, + dataType_e type) + : size_ (sizeAllocated), headPos_ (0), tailPos_ (size), type_ (type) +{ + if (!data || size > sizeAllocated) + throw std::invalid_argument ("Paramêtres invalides"); + buffer_ = new uint8_t [size_]; + std::memcpy (buffer_, data, tailPos_); +} + +/// Surcharge de l'opérateur d'affectation +DataBuffer & +DataBuffer::operator= (const DataBuffer &d) +{ + DataBuffer b (d); + b.swap (*this); + return *this; +} + +/// Lit des données. Même convention que le read de la libc, mais lance +/// une exception en cas d'erreur. +unsigned +DataBuffer::read (uint8_t *buf, unsigned size) +{ + if (!buf) + throw std::invalid_argument ("Paramêtres invalides"); + unsigned sizeTmp = tailPos_ - headPos_; + // On regarde combien de données peuvent être lues + if (size < sizeTmp) + sizeTmp = size; + std::memcpy (buf, &buffer_[headPos_], sizeTmp); + headPos_ += sizeTmp; + // Si il n'y a plus de données dans le buffer, on recommence de puis 0 + if (headPos_ == tailPos_) + headPos_ = tailPos_ = 0; + return sizeTmp; +} + +/// Écrit des données. Même convention que le write de la libc, mais lance +/// une exception en cas d'erreur. +void +DataBuffer::write (const uint8_t *buf, unsigned size) +{ + // Vérification des paramêtres + if (!buf) + throw std::invalid_argument ("Parametres invalides"); + // Agrandissement du buffer + grow (size); + // Ecriture des données + std::memcpy (&buffer_[tailPos_], buf, size); + tailPos_ += size; +} + +/// Augmente la taille du buffer pour correspondre à size. +void +DataBuffer::grow (const unsigned size) +{ + // Taille restant non utilisé dans le buffer + unsigned tailleLibre = size_ - tailPos_; + // Si la taille du buffer n'est pas suffisante + if (tailleLibre < size) + { + // On augmente de deux fois la taille + DataBuffer d (&buffer_[headPos_], tailPos_ - headPos_, + 2 * size + size_, type_); + d.swap (*this); + } +} + +/// Echange les buffers. +void +DataBuffer::swap (DataBuffer &d) +{ + std::swap (buffer_, d.buffer_); + std::swap (size_, d.size_); + std::swap (headPos_, d.headPos_); + std::swap (tailPos_, d.tailPos_); + std::swap (type_, d.type_); +} diff --git a/i/chuck/src/data/data_buffer.hh b/i/chuck/src/data/data_buffer.hh new file mode 100644 index 0000000..7b71a4d --- /dev/null +++ b/i/chuck/src/data/data_buffer.hh @@ -0,0 +1,83 @@ +#ifndef data_buffer_hh +#define data_buffer_hh +// data_buffer.hh +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Dufour Jérémy +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: %WEB% +// Email: +// }}} + +#include "data_input.hh" +#include "data_output.hh" + +#include // uint8_t + +/// Classe contenant un buffer de données accessible en lecture et en +/// écriture. +class DataBuffer : public DataInput, public DataOutput +{ + public: + /// Type de données possible du buffer. + enum dataType_e { + NoType, + Image, + AskImage + }; + private: + /// Buffer de données. + uint8_t *buffer_; + /// Taille alloué en mémoire pour le buffer. + unsigned size_; + /// Position du début et de la fin des données dans le buffer. + unsigned headPos_, tailPos_; + /// Type de données du buffer. + dataType_e type_; + /// Augmente la taille du buffer pour correspondre à size. + void grow (const unsigned size); + public: + /// Constructeur par défaut. + DataBuffer (void); + /// Constructeur par recopie. + DataBuffer (const DataBuffer &d); + /// Constructeur avec données. + DataBuffer (uint8_t *data, unsigned size, unsigned sizeAllocated, + dataType_e type = NoType); + /// Destructeur par défaut. + ~DataBuffer (void) { delete [] buffer_; } + /// Surcharge de l'opérateur d'affectation + DataBuffer &operator= (const DataBuffer &d); + /// Lit des données. Même convention que le read de la libc, mais lance + /// une exception en cas d'erreur. + unsigned read (uint8_t *buf, unsigned size); + /// Écrit des données. Même convention que le write de la libc, mais lance + /// une exception en cas d'erreur. + void write (const uint8_t *buf, unsigned size); + /// Taille utile du buffer. + unsigned size (void) const { return tailPos_ - headPos_; } + /// Echange les buffers. + void swap (DataBuffer &d); + /// Type de données du buffer. + dataType_e type (void) const { return type_; } + /// Change le type de données du buffer. + void setType (const dataType_e type) { type_ = type; } + /// Empty/clear the content of the buffer. + void clear (void) { tailPos_ = headPos_ = 0; } +}; +#endif // data_buffer_hh diff --git a/i/chuck/src/data/data_circular_buffer.cc b/i/chuck/src/data/data_circular_buffer.cc new file mode 100644 index 0000000..be17526 --- /dev/null +++ b/i/chuck/src/data/data_circular_buffer.cc @@ -0,0 +1,123 @@ +// data_circular_buffer.cc +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Dufour Jérémy +// +// Robot APB Team/Efrei 2004. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "data_circular_buffer.hh" + +#include // std::memcpy +#include // std::runtime_error +#include // std::swap, std::min + +#include // XXX + +/// Default constructor. +/// Size is the allocated size in memory. +DataCircularBuffer::DataCircularBuffer (unsigned size) + : size_ (size + 1), startPos_ (0), endPos_ (0) +{ + // The + 1 for size is because, in some cases, we will have an empty case. + buffer_ = new uint8_t [size_]; +} + +/// Destructor. +DataCircularBuffer::~DataCircularBuffer (void) +{ + delete [] buffer_; +} + +/// Read data of maximum size in the data pointer (data must be allocated of +/// size). +unsigned +DataCircularBuffer::read (uint8_t *data, unsigned size) +{ + if (!data || !size) + throw std::invalid_argument ("Invalid parameter"); + return internalRead (data, size); +} + +/// Internal read, do the real job. +unsigned +DataCircularBuffer::internalRead (uint8_t *data, unsigned size) +{ + // Size of data to read + unsigned sizeToRead = std::min (maxReadableData (), size); + // Size of data to read for the end of the buffer + unsigned sizeToReadEnd = std::min (size_ - startPos_, sizeToRead); + // Copy end part of buffer + if (data) + std::memcpy (&data[0], &buffer_[startPos_], sizeToReadEnd); + // Need to do the begin part of buffer ? + int sizeToReadStart = sizeToRead - sizeToReadEnd; + if (sizeToReadStart > 0) + { + if (data) + std::memcpy (&data[sizeToReadEnd], &buffer_[0], sizeToReadStart); + // Move start of data + startPos_ = 0 + sizeToReadStart; + } + else + // Move start of data + startPos_ = (startPos_ + sizeToRead) % size_; + return sizeToRead; +} + +/// Write data of size length. +void +DataCircularBuffer::write (const uint8_t *data, unsigned size) +{ + if (!data || !size) + throw std::invalid_argument ("Invalid parameter"); + + // Max size we can write + unsigned sizeToWrite = std::min (size, size_ - 1); + + // Read data before overwrite it if needed + int sizeToRead = sizeToWrite - (size_ - maxReadableData ()) + 1; + if (sizeToRead > 0) + if (internalRead (0, sizeToRead) != (unsigned) sizeToRead) + throw std::runtime_error ("Unexpected error"); + + // Max size we can write until the end of the buffer + unsigned sizeToWriteEnd = std::min (size_ - endPos_, sizeToWrite); + // Write first part. + std::memcpy (&buffer_[endPos_], &data[size - sizeToWrite + 0], sizeToWriteEnd); + // More to write ? + unsigned sizeToWriteStart = sizeToWrite - sizeToWriteEnd; + if (sizeToWriteStart > 0) + { + std::memcpy (&buffer_[0], &data[size - sizeToWrite + sizeToWriteEnd], sizeToWriteStart); + endPos_ = 0 + sizeToWriteStart; + } + else + endPos_ = (endPos_ + sizeToWrite) % size_; +} + +/// Swap data between tow DataCircularBuffer. +void +DataCircularBuffer::swap (DataCircularBuffer &d) +{ + std::swap (buffer_, d.buffer_); + std::swap (size_, d.size_); + std::swap (startPos_, d.startPos_); + std::swap (endPos_, d.endPos_); +} diff --git a/i/chuck/src/data/data_circular_buffer.hh b/i/chuck/src/data/data_circular_buffer.hh new file mode 100644 index 0000000..f08426d --- /dev/null +++ b/i/chuck/src/data/data_circular_buffer.hh @@ -0,0 +1,64 @@ +#ifndef data_circular_buffer_hh +#define data_circular_buffer_hh +// data_circular_buffer.hh +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Dufour Jérémy +// +// Robot APB Team/Efrei 2004. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} + +#include "data_input.hh" +#include "data_output.hh" + +#include // uint8_t + +class DataCircularBuffer : public DataInput, public DataOutput +{ + private: + /// Calculate the quantity of maximum data we can read. + unsigned maxReadableData (void) + { return (endPos_ + size_ - startPos_) % size_; } + /// Internal read, do the real job. + unsigned internalRead (uint8_t *data, unsigned size); + /// Buffer. + uint8_t *buffer_; + /// Size of the buffer. + unsigned size_; + /// Start and end positions of data in the buffer. + unsigned startPos_, endPos_; + public: + /// Default constructor. + /// Size is the allocated size in memory. + DataCircularBuffer (unsigned size); + /// Destructor. + ~DataCircularBuffer (void); + /// Read data of maximum size in the data pointer (data must be allocated + /// of size). + unsigned read (uint8_t *data, unsigned size); + /// Write data of size length. + void write (const uint8_t *data, unsigned size); + /// Size of the buffer. + unsigned size (void) const { return size_; } + /// Swap data between tow DataCircularBuffer. + void swap (DataCircularBuffer &d); +}; + +#endif // data_circular_buffer_hh diff --git a/i/chuck/src/data/data_input.cc b/i/chuck/src/data/data_input.cc new file mode 100644 index 0000000..cfc9b2a --- /dev/null +++ b/i/chuck/src/data/data_input.cc @@ -0,0 +1,37 @@ +// data_input.cc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "data_input.hh" + +/// Lit un caractère. Renvois -1 en cas de fin de fichier. +int +DataInput::getc (void) +{ + uint8_t c; + if (read (&c, 1) == 1) + return c & 0xff; + else + return -1; +} + diff --git a/i/chuck/src/data/data_input.hh b/i/chuck/src/data/data_input.hh new file mode 100644 index 0000000..ae59366 --- /dev/null +++ b/i/chuck/src/data/data_input.hh @@ -0,0 +1,44 @@ +#ifndef data_input_hh +#define data_input_hh +// data_input.hh +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} + +#include + +/// Classe d'entrée de données. C'est une sorte de istream simplifié +/// permettant d'accéder à des données en lecture. +class DataInput +{ + public: + /// Destructeur. + virtual ~DataInput (void) { } + /// Lit des données. Même convention que le read de la libc, mais lance + /// une exception en cas d'erreur. + virtual unsigned read (uint8_t *buf, unsigned size) = 0; + /// Lit un caractère. Renvois -1 en cas de fin de fichier. + int getc (void); +}; + +#endif // data_input_hh diff --git a/i/chuck/src/data/data_input_file.cc b/i/chuck/src/data/data_input_file.cc new file mode 100644 index 0000000..75b7500 --- /dev/null +++ b/i/chuck/src/data/data_input_file.cc @@ -0,0 +1,46 @@ +// data_input_file.cc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "data_input_file.hh" +#include "utils/errno_exception.hh" + +/// Constructeur. +DataInputFile::DataInputFile (const std::string &name) + : name_ (name), file_ (name.c_str ()) +{ + if (!file_) + throw errno_exception (name_, errno); +} + +/// Lit des données. Même convention que le read de la libc, mais lance +/// une exception en cas d'erreur. +unsigned +DataInputFile::read (uint8_t *buf, unsigned size) +{ + file_.read (reinterpret_cast (buf), size); + if (file_.bad ()) + throw errno_exception (name_, errno); + return file_.gcount (); +} + diff --git a/i/chuck/src/data/data_input_file.hh b/i/chuck/src/data/data_input_file.hh new file mode 100644 index 0000000..29d22ca --- /dev/null +++ b/i/chuck/src/data/data_input_file.hh @@ -0,0 +1,45 @@ +#ifndef data_input_file_hh +#define data_input_file_hh +// data_input_file.hh +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "data_input.hh" + +#include +#include + +/// Data depuis un fichier standard. +class DataInputFile : public DataInput +{ + std::string name_; + std::ifstream file_; + public: + /// Constructeur. + DataInputFile (const std::string &name); + /// Lit des données. Même convention que le read de la libc, mais lance + /// une exception en cas d'erreur. + unsigned read (uint8_t *buf, unsigned size); +}; + +#endif // data_input_file_hh diff --git a/i/chuck/src/data/data_input_zlib.cc b/i/chuck/src/data/data_input_zlib.cc new file mode 100644 index 0000000..f8f5322 --- /dev/null +++ b/i/chuck/src/data/data_input_zlib.cc @@ -0,0 +1,84 @@ +// data_input_zlib.cc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "data_input_zlib.hh" + +#include + +/// Constructeur. +DataInputZlib::DataInputZlib (DataInput &data) + : data_ (data), inBuf_ (0) +{ + // Allocate input buffer. + inBuf_ = new uint8_t[inBufSize_]; + // Initialise the zlib structure. + zStream_.next_in = 0; + zStream_.avail_in = 0; + zStream_.next_out = 0; + zStream_.avail_out = 0; + zStream_.zalloc = 0; + zStream_.zfree = 0; + zStream_.opaque = 0; + if (inflateInit2 (&zStream_, 32 + 15) != Z_OK) + { + delete[] inBuf_; + throw std::runtime_error (zStream_.msg); + } +} + +/// Destructeur. +DataInputZlib::~DataInputZlib (void) +{ + inflateEnd (&zStream_); + delete[] inBuf_; +} + +/// Lit des données. Même convention que le read de la libc, mais lance +/// une exception en cas d'erreur. +unsigned +DataInputZlib::read (uint8_t *buf, unsigned size) +{ + // Set output buffer. + zStream_.next_out = buf; + zStream_.avail_out = size; + // While not satisfied. + while (zStream_.avail_out) + { + // Feed more data. + if (zStream_.avail_in == 0) + { + zStream_.next_in = inBuf_; + zStream_.avail_in = data_.read (inBuf_, inBufSize_); + } + // Uncompress. + int r = inflate (&zStream_, Z_SYNC_FLUSH); + // Check result. + if (r == Z_STREAM_END) + return size - zStream_.avail_out; + else if (r != Z_OK) + throw std::runtime_error (zStream_.msg); + } + return size; +} + diff --git a/i/chuck/src/data/data_input_zlib.hh b/i/chuck/src/data/data_input_zlib.hh new file mode 100644 index 0000000..0b7cf5f --- /dev/null +++ b/i/chuck/src/data/data_input_zlib.hh @@ -0,0 +1,48 @@ +#ifndef data_input_zlib_hh +#define data_input_zlib_hh +// data_input_zlib.hh +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "data_input.hh" + +#include + +/// Data depuis un data compressé en zlib. +class DataInputZlib : public DataInput +{ + DataInput &data_; + uint8_t *inBuf_; + static const unsigned inBufSize_ = 1024; + z_stream zStream_; + public: + /// Constructeur. + DataInputZlib (DataInput &data); + /// Destructeur. + ~DataInputZlib (void); + /// Lit des données. Même convention que le read de la libc, mais lance + /// une exception en cas d'erreur. + unsigned read (uint8_t *buf, unsigned size); +}; + +#endif // data_input_zlib_hh diff --git a/i/chuck/src/data/data_output.cc b/i/chuck/src/data/data_output.cc new file mode 100644 index 0000000..ed04e97 --- /dev/null +++ b/i/chuck/src/data/data_output.cc @@ -0,0 +1,34 @@ +// data_output.cc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "data_output.hh" + +/// Écrit un caractère. +void +DataOutput::putc (int c) +{ + uint8_t uc = c; + write (&uc, 1); +} + diff --git a/i/chuck/src/data/data_output.hh b/i/chuck/src/data/data_output.hh new file mode 100644 index 0000000..7141892 --- /dev/null +++ b/i/chuck/src/data/data_output.hh @@ -0,0 +1,44 @@ +#ifndef data_output_hh +#define data_output_hh +// data_output.hh +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} + +#include + +/// Classe de sortie de données. C'est une sorte de ostream simplifié +/// permettant d'accéder à des données en écriture. +class DataOutput +{ + public: + /// Destructeur. + virtual ~DataOutput (void) { } + /// Écrit des données. Même convention que le write de la libc, mais lance + /// une exception en cas d'erreur. + virtual void write (const uint8_t *buf, unsigned size) = 0; + /// Écrit un caractère. + void putc (int c); +}; + +#endif // data_output_hh diff --git a/i/chuck/src/data/test_data.cc b/i/chuck/src/data/test_data.cc new file mode 100644 index 0000000..acc57ac --- /dev/null +++ b/i/chuck/src/data/test_data.cc @@ -0,0 +1,56 @@ +// test_data.cc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "data_input_file.hh" +#include "data_input_zlib.hh" + +#include +#include +#include + +int +main (int argc, char **argv) +{ + try + { + if (argc != 2) + throw std::runtime_error ("Syntax: test_data file"); + DataInputFile f (argv[1]); + DataInputZlib z (f); + uint8_t buf[1024]; + int r = z.read (buf, 1024); + while (r != 0) + { + write (1, buf, r); + r = z.read (buf, r); + } + } + catch (const std::exception &e) + { + std::cerr << e.what () << std::endl; + return 1; + } + return 0; +} + diff --git a/i/chuck/src/data/test_data_buffer.cc b/i/chuck/src/data/test_data_buffer.cc new file mode 100644 index 0000000..36095ab --- /dev/null +++ b/i/chuck/src/data/test_data_buffer.cc @@ -0,0 +1,77 @@ +// test_data_buffer.cc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Dufour Jérémy +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: %WEB% +// Email: +// }}} + +#include "data_buffer.hh" + +#include +#include +#include + +void +check_data (uint8_t *b1, uint8_t *b2, unsigned size) +{ + for (unsigned i = 0; i < size; i ++) + if (b1[i] != b2[i]) + throw std::runtime_error ("Erreur, buffers invalides"); +} + +int +main (int argc, char **argv) +{ + try + { + DataBuffer d; + uint8_t bufW[100]; + uint8_t bufR[150]; + // Remplissage des buffers de test + memset (bufW, 42, 100); + memset (bufR, 1, 150); + // On en écrit 50 + d.write (bufW, 50); + // On en lit 42 + if (d.read (bufR, 42) == 42) + check_data (bufW, bufR, 42); + else + throw std::runtime_error ("Erreur de taille de données"); + // On en re écrit 50 + d.write (&bufW[50], 50); + unsigned pos = 42; + unsigned status; + // On lit jusqu'à la fin + do + { + status = d.read (&bufR[pos], 10); + if (status) + check_data (&bufW[pos], &bufR[pos], status); + pos += status; + } while (status); + // On vérifie que tout a été bien lue + } + catch (const std::runtime_error &r) + { + std::cerr << r.what () << std::endl; + return 1; + } + return 0; +} diff --git a/i/chuck/src/data/test_data_circular_buffer.cc b/i/chuck/src/data/test_data_circular_buffer.cc new file mode 100644 index 0000000..9bdc063 --- /dev/null +++ b/i/chuck/src/data/test_data_circular_buffer.cc @@ -0,0 +1,92 @@ +// test_data_circular_buffer.cc +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Dufour Jérémy +// +// Robot APB Team/Efrei 2004. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "data_circular_buffer.hh" + +#include +#include +#include +#include + +#define MAX_SIZE_BUFF 101 +#define MAX_SIZE_CIRC 99 + +unsigned +randVal (double max) +{ + return 1 + (int) (max * std::rand () / (RAND_MAX + 1.0)); +} + +int +main (void) +{ + // Init random + std::srand (std::time (NULL)); + try + { + DataCircularBuffer d (MAX_SIZE_CIRC); + uint8_t buffOrig[MAX_SIZE_BUFF]; + uint8_t buffRes[MAX_SIZE_BUFF]; + + int i, compt, tmp; + // Fill buffer + for (i = 0; i < MAX_SIZE_BUFF; i++) + memset (&buffOrig[i], i, 1); + + // Fill circular buffer + compt = 0; + for (i = 0; i < 42; i++) + { + tmp = randVal (MAX_SIZE_BUFF - compt); + d.write (&buffOrig[compt], tmp); + compt = (tmp + compt) % MAX_SIZE_BUFF; + } + + // Read + compt = 0; + unsigned res; + do + { + tmp = randVal (7.); + res = d.read (&buffRes[compt], tmp); + compt += tmp; + } while (res != 0); + + // Compare + for (i = 0; i < MAX_SIZE_CIRC - 1; i++) + { + if (buffRes [i] != buffOrig [(buffRes[0] +i) % MAX_SIZE_BUFF]) + throw std::runtime_error ("Test failed !"); + } + + } + + catch (const std::exception &e) + { + std::cerr << e.what () << std::endl; + return 1; + } + return 0; +} + diff --git a/i/chuck/src/es/Makefile.defs b/i/chuck/src/es/Makefile.defs new file mode 100644 index 0000000..66a4e6f --- /dev/null +++ b/i/chuck/src/es/Makefile.defs @@ -0,0 +1,5 @@ +PROGRAMS += test_es + +es_OBJECTS = es.o + +test_es_OBJECTS = test_es.o $(es_OBJECTS) $(tester_OBJECTS) $(proto_OBJECTS) diff --git a/i/chuck/src/es/es.cc b/i/chuck/src/es/es.cc new file mode 100644 index 0000000..66a8fc9 --- /dev/null +++ b/i/chuck/src/es/es.cc @@ -0,0 +1,752 @@ +// es.cc +// robert - programme du robot 2005 {{{ +// +// Copyright (C) 2005 Nicolas Haller +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} + +#include "es/es.hh" +#include "config/config.hh" + +#include +#include + +/// Constructeur +Es::Es (const Config & config) + : proto_ (*this), log_ ("Es"), lcdKeyPressed_ (-1), front_sensor_ (false), + jackIn_ (false), colorModeBlue_ +(false),positionBarillet_(avant0),frontTurbineIsFull_(false), unknownColor_ +(-2), redColor_ (2), blueColor_ (1), greenColor_ (0), whiteColor_ (5), + blackColor_ (4), leftFrontRVB_ (0), rightFrontRVB_ (1), holeRVB_ (2), + frontBallRVB_ (3), rearBallRVB_ (4) +{ + // Récupération des valeurs de configuration dans le fichier + loadConfig (config); + proto_.open (tty_); + + sharps_.resize (3); + // Normalement, le barillet est vide... + for(int i = 0; i < 5 ; i++) + stockBarillet[i] = empty; + + for (int compt = 0; compt < 5; compt++) + { + seenColors_[compt] = unknownColor_; + lastSeenColors_[compt] = unknownColor_; + comptSeenColors_[compt] = 0; + } +} + +bool +Es::wait (int timeout /*-1*/) +{ + return proto_.wait (timeout); +} + +/// Récupère le File Descriptor +int +Es::getFd (void) +{ + return proto_.getFd(); +} + +bool Es::sync (void) +{ + return proto_.sync (); +} + +void +Es::loadConfig (const Config & config) +{ + tty_ = config.get("es.tty"); + ackFreq_ = config.get ("es.ack_freq"); + mainStat_ = config.get ("es.main_stat"); + rvbSensorFalseIC_ = config.get ("es.rvb_sensors_false_ic"); + rvbSensorMaxOv_ = config.get ("es.rvb_sensors_max_ov"); + rvbSniffRefRatio_ = config.get ("es.rvb_sniff_ref_ratio"); + rvbSniffGreenLimit_ = config.get ("es.rvb_sniff_green_limit"); + rvbSniffClearLimit_ = config.get ("es.rvb_sniff_clear_limit"); + rvbSensorMaskStat_ = config.get ("es.rvb_sensor_mask_stat"); + rvbSensorStat_ = config.get ("es.rvb_sensor_stat"); + rvbSniffMaskStat_ = config.get ("es.rvb_sniff_mask_stat"); + rvbSniffStat_ = config.get ("es.rvb_sniff_stat"); + rvbSniffFrontStat_ = config.get ("es.rvb_sniff_front_stat"); + rvbBallStat_ = config.get ("es.rvb_ball_stat"); + othersStat_ = config.get ("es.others_stat"); + lcdKeyStat_ = config.get ("es.lcd_key_stat"); + thresholdFrontSensors_ = config.get ("es.threshold_front_sensors"); + thresholdBallSensors_ = config.get ("es.threshold_ball_sensors"); + thresholdHoleSensors_ = config.get ("es.threshold_hole_sensors"); +} + +void +Es::reset (void) +{ + // On reset l'AVR + proto_.send ('z'); + + // First, enable all sensors + setRVBSensorsConfig (rvbSensorFalseIC_, rvbSensorMaxOv_); + + // Send configurations + setMainStat (mainStat_); + setAckStat (ackFreq_); + setRVBSniffConfig (rvbSniffRefRatio_, rvbSniffGreenLimit_, + rvbSniffClearLimit_); + setRVBSensorsStat (rvbSensorMaskStat_, rvbSensorStat_); + setRVBSniffStat (rvbSniffMaskStat_, rvbSniffStat_); + setRVBBallStat (rvbBallStat_); + setOthersStat (othersStat_); + setRVBSniffFrontStat (rvbSniffFrontStat_); + lcdGetKey (lcdKeyStat_); + + enableAllSensors (true); + log_ ("Es", Log::debug) << "Reset Es done."; +} + +/// Stat for the main () +void +Es::setMainStat (int freq) +{ + proto_.send ('Z', "b", freq); +} + +/// Shut up ! +void +Es::shutUp (void) +{ + proto_.send ('f'); +} + +/// Set frequency of ack +void +Es::setAckStat (int freq) +{ + ackFreq_ = freq; + proto_.send ('F', "b", ackFreq_); +} + +/// Get the state of the jack +bool +Es::isJackOut (void) +{ + return !jackIn_; +} + +/// Get the color mode of the button +bool +Es::isColorModeBlue (void) +{ + return colorModeBlue_; +} + +// Envoie de la config des sensors RVB +void Es::setRVBSensorsConfig(int false_ic, int max_ov) +{ + proto_.send ('p',"bb", false_ic, max_ov); +} + +// Envoie de la config des sniff RVB +void Es::setRVBSniffConfig (int ref_ratio, int green_limit, int clear_limit) +{ + proto_.send ('x', "bww", ref_ratio, green_limit, clear_limit); +} + +// Règle les stats des sensors RVB +void Es::setRVBSensorsStat(int mask_captor, int freq) +{ + proto_.send ('S', "wb", mask_captor, freq); +} + +// règle la couleur actuelle comme référente +void Es::refColor(int mask_captor, int mode) +{ + proto_.send ('r', "wb", mask_captor, mode); +} + +/// Règle les stats d'affichage de la couleur +void +Es::setRVBSniffStat (int mask_captor, int freq) +{ + proto_.send ('A', "wb", mask_captor, freq); +} + +/// Configure statistic for the sensor of the ball +void +Es::setRVBBallStat (int freq) +{ + proto_.send ('B', "b", freq); +} + +/// Set frequency of front sensor in analyse mode +void +Es::setRVBSniffFrontStat (int freq) +{ + proto_.send ('C', "b", freq); +} + +/// Enable all the sensors or just the 4 and 1 near the ground +void +Es::enableAllSensors (bool enable) +{ + if (enable) + proto_.send ('u', "b", 1); + else + proto_.send ('u', "b", 0); +} + +/// Set frequency of jack, selectoul printed out function +void +Es::setOthersStat (int freq) +{ + proto_.send ('O', "b", freq); +} + +// Discute avec les servo... +void Es::setServoPos (int servo_mask, int servoPos) +{ + proto_.send ('m', "bb", servo_mask, servoPos); +} + +/// Set update frequency of sharps +void +Es::setSharpUpdate (int sharp_mask, int freq) +{ + proto_.send ('h', "bb", sharp_mask, freq); +} + +/// Set statistics frequency of sharps +void +Es::setSharpStat (int sharp_mask, int freq) +{ + proto_.send ('H', "bb", sharp_mask, freq); +} + +/// Set configuration of threshold sharps +void +Es::setSharpThreshold (int sharp_num, int threshold_high, + int threshold_low) +{ + proto_.send ('o', "bww", sharp_num, threshold_high, threshold_low); +} + +/// Print something on the LCD (max 16 char) +void +Es::lcdPrint (const std::string &message) +{ + std::memset (lcd_mess_char_, ' ', 16); + int size = message.size (); + std::memcpy (lcd_mess_char_, message.data (), size > 16 ? 16 : size); + proto_.sendStr ('l', lcd_mess_char_, 16); +} + +/// Get the current pressed keys of the LCD +void +Es::lcdGetKey (int freq) +{ + proto_.send ('L', "b", freq); +} + +// Règle la vitesse des turbines +void Es::setTurbineSpeed(int turbNb, int speed) +{ + proto_.send ('v', "bw", turbNb, speed); +} + +// Règle le sens de rotation du barillet +void Es::setTheMeaningOfRotationOfBarillet(int answer) +{ + proto_.send ('w', "b", answer); +} + +/// Init the barillet and put it at the right place +void +Es::barilletInit (void) +{ + proto_.send ('i'); + frontTurbineIsFull_ = false; +} + +/// Init turbine to minimal speed +void Es::barilletDebutLancement (void) +{ + proto_.send ('g'); + frontTurbineIsFull_ = false; +} + +/// Init front turbine to full speed +void Es::barilletLancement (void) +{ + proto_.send ('h'); + frontTurbineIsFull_ = true; + log_ ("Es::Barillet", Log::debug) << "Lancement turbine avant."; +} + +/// Put barillet in sleep mode +void +Es::barilletSleep (void) +{ + proto_.send ('s'); + frontTurbineIsFull_ = false; +} + +// Dépose une balle du barillet +void +Es::deposeBalle(void) +{ + proto_.send ('d'); + barilletDebutLancement(); + log_ ("Es::Barillet", Log::debug) << "DROP!! "; + frontTurbineIsFull_ = false; + wait (400); + barilletLancement(); +} + +/// Dépose une balle blanche +bool +Es::dropWhiteBall(void) +{ + for(int i = 0; i < 5; i++) + if(stockBarillet[i] == white) + { + log_ ("Es::Barillet", Log::debug) << "Balle blanche detected en trou: " << i; + switch (i) + { + case 0: + rotationBarillet(arriere0); + positionBarillet_ = arriere0; + stockBarillet[0] = empty; + break; + case 1: + rotationBarillet(arriere1); + positionBarillet_ = arriere1; + stockBarillet[1] = empty; + break; + case 2: + rotationBarillet(arriere2); + positionBarillet_ = arriere2; + stockBarillet[2] = empty; + break; + case 3: + rotationBarillet(arriere3); + positionBarillet_ = arriere3; + stockBarillet[3] = empty; + break; + case 4: + rotationBarillet(arriere4); + positionBarillet_ = arriere4; + stockBarillet[4] = empty; + break; + } + //deposeBalle(); + return true; + } + return false; +} + +/// Dépose une balle noire +bool +Es::dropBlackBall(void) +{ + for(int i = 0; i < 5; i++) + if(stockBarillet[i] == black) + { + log_ ("Es::Barillet", Log::debug) << "Balle noire detected en trou: " << i; + switch (i) + { + case 0: + rotationBarillet(arriere0); + positionBarillet_ = arriere0; + stockBarillet[0] = empty; + break; + case 1: + rotationBarillet(arriere1); + positionBarillet_ = arriere1; + stockBarillet[1] = empty; + break; + case 2: + rotationBarillet(arriere2); + positionBarillet_ = arriere2; + stockBarillet[2] = empty; + break; + case 3: + rotationBarillet(arriere3); + positionBarillet_ = arriere3; + stockBarillet[3] = empty; + break; + case 4: + rotationBarillet(arriere4); + positionBarillet_ = arriere4; + stockBarillet[4] = empty; + break; + } + //deposeBalle(); + return true; + } + return false; +} + +/// Place un trou vide à l'avant +bool +Es::setEmptyHoleFront(void) +{ + if(barilletIsFull()) + return false; + for(int i = 0; i < 5; i++) + if(stockBarillet[i] == empty) + { + log_ ("Es::Barillet", Log::debug) << "vide detected en trou: " << i; + switch (i) + { + case 0: + rotationBarillet(avant0); + positionBarillet_ = avant0; + break; + case 1: + rotationBarillet(avant1); + positionBarillet_ = avant1; + break; + case 2: + rotationBarillet(avant2); + positionBarillet_ = avant2; + break; + case 3: + rotationBarillet(avant3); + positionBarillet_ = avant3; + break; + case 4: + rotationBarillet(avant4); + positionBarillet_ = avant4; + break; + } + return true; + } + return false; +} +/// Extrait une balle +void +Es::extraitBalle(void) +{ + proto_.send ('e'); + frontTurbineIsFull_ = false; + log_ ("Es::Barillet", Log::debug) << "Extraction baballe."; +} + +/// Rotation du barillet +void Es::rotationBarillet(int posFinal) +{ + proto_.send ('t', "b", posFinal); + frontTurbineIsFull_ = false; +} + +/// Empty everything in the barillet +void Es::barilletEmpty (void) +{ + proto_.send ('n'); + frontTurbineIsFull_ = false; +} + +void Es::receive(char command, const Proto::Frame & frame) +{ + int errCode, red, blue, clear, green, compt, value; + int stat1, stat2, stat3, stat4; + + switch (command) + { + /* Main stat */ + case 'Z': + if (proto_.decode (frame, "bbbb", stat1, stat2, stat3, stat4)) + { + log_ ("Stats main", Log::debug) << stat1 << " " << stat2 << " " + << stat3 << " " << stat4; + } + break; + /* Ack */ + case 'F': + if (proto_.decode (frame, "b", errCode)) + { + log_ ("Ack", Log::debug) << "ErrCode :" << errCode; + switch (errCode) + { + case 1: + front_sensor_ = true; + break; + case 2: // une balle miam par l'avant + newBallFront(); + break; + case 3: // une balle miam par l'arrière + newBallRear(); + break; + case 4: + // A ball has been by the sensor at the front of the barillet + enableAllSensors (true); + setRVBBallStat (5); + break; + } + shutUp (); + } + break; + /* RVB Sensors raw stat */ + case 'S': + if (proto_.decode (frame, "wwwww", compt, red, blue, clear, green)) + { + log_ ("Stats RVB Raw", Log::debug) << "[" << compt << "] = {" + << red << "," << blue << "," << clear << "," << green << "}"; + } + break; + /* RVB Sniff stats */ + case 'A': + if (proto_.decode (frame, "bb", compt, value)) + { + log_ ("Stats RVB Sniff", Log::debug) << "[" << compt << "] = " + << decodeColor (value); + } + break; + case 'C': + if (proto_.decode (frame, "bb", stat1, stat2)) + { + log_ ("Stats RVB Front", Log::debug) << decodeColor (stat1) + << " - " << decodeColor (stat2); + updateAnalysisSensor (stat2, leftFrontRVB_, thresholdFrontSensors_); + updateAnalysisSensor (stat1, rightFrontRVB_, thresholdFrontSensors_); + } + break; + /* RVB Hole */ + case 'D': + if (proto_.decode (frame, "b", stat1)) + { + log_ ("Stats RVB Hole", Log::debug) << decodeColor (stat1); + updateAnalysisSensor (stat1, holeRVB_, thresholdHoleSensors_); + } + break; + /* RVB Balls */ + case 'B': + if (proto_.decode (frame, "bb", stat1 /* Rear */, stat2 /* Front */)) + { +// log_ ("Stats RVB Ball", Log::debug) << "[" << decodeColor +// (stat1) << "] [" << decodeColor (stat2) << "]"; + updateAnalysisSensor (stat1, rearBallRVB_, thresholdBallSensors_); + updateAnalysisSensor (stat2, frontBallRVB_, thresholdBallSensors_); + log_ ("Ball") << "Devant : " << (colorSeen (frontBallRVB_) == + whiteColor_ ? "white" : "black") << " Arr : " << (colorSeen + (rearBallRVB_) == whiteColor_ ? "white" : "black"); + } + break; + /* Others */ + case 'O': + if (proto_.decode (frame, "b", value)) + { + // XXX Use a decallage please + if (value & 0x01) + jackIn_ = true; + else + jackIn_ = false; + if (value & 0x02) + colorModeBlue_ = true; + else + colorModeBlue_ = false; +// log_ ("Others", Log::debug) << "Color mode " << (colorModeBlue_ ? "Blue" : "Red") +// << (jackIn_ ? ", jack in..." : ", jack out !!!"); + } + break; + /* LCD */ + case 'L': + if (proto_.decode (frame, "b", value)) + lcdKeyPressed_ = value; + break; + /* Sharps */ + case 'H': + if (proto_.decode (frame, "ww", compt, value)) + { + std::cout << "[" << compt << "]" << " = " << value << std::endl; + sharps_[compt] = value; + } + break; + /* Barillet */ + case 'W': + if (proto_.decode (frame, "bb", stat1, stat2)) + { + log_ ("Barillet", Log::debug) << stat1 << " " << stat2; + } + break; + } +} + +void Es::setRVBHoleStat (int freq) +{ + proto_.send ('D', "b", freq); +} + +/// Decode a color into a string +std::string +Es::decodeColor (int color) +{ + switch (color) + { + case 0: + return "green"; + break; + case 1: + return "blue"; + break; + case 2: + return "red"; + break; + case 3: + return "other"; + break; + case 4: + return "black"; + break; + case 5: + return "white"; + break; + default: + return "unknow"; + } +} + +/// Analyse une balle arrivant par devant +void +Es::newBallFront(void) +{ + /// La turbine est off + frontTurbineIsFull_ = false; + /// On analyse la baballe + switch (positionBarillet_) + { + case avant0: + stockBarillet[0] = ((colorSeen(frontBallRVB_))==whiteColor_)?white:white; + positionBarillet_ = avant4; + log_ ("Es::Barillet", Log::debug) << "trou 0:" << ((stockBarillet[0] == white)?"white":"pas white"); + break; + case avant1: + stockBarillet[1] = ((colorSeen(frontBallRVB_))==whiteColor_)?white:white; + positionBarillet_ = avant0; + log_ ("Es::Barillet", Log::debug) << "trou 1:" << ((stockBarillet[1] == white)?"white":"pas white"); + break; + case avant2: + stockBarillet[2] = ((colorSeen(frontBallRVB_))==whiteColor_)?white:white; + positionBarillet_ = avant1; + log_ ("Es::Barillet", Log::debug) << "trou 2:" << ((stockBarillet[2] == white)?"white":"pas white"); + break; + case avant3: + stockBarillet[3] = ((colorSeen(frontBallRVB_))==whiteColor_)?white:white; + positionBarillet_ = avant2; + log_ ("Es::Barillet", Log::debug) << "trou 3:" << ((stockBarillet[3] == white)?"white":"pas white"); + break; + case avant4: + stockBarillet[4] = ((colorSeen(frontBallRVB_))==whiteColor_)?white:white; + positionBarillet_ = avant3; + log_ ("Es::Barillet", Log::debug) << "trou 4:" << ((stockBarillet[4] == white)?"white":"pas white"); + break; + default: + log_ ("Es::Barillet", Log::debug) << "trou default..."; + break; + } + /// On regarde si on redémarre la turbine + if(!barilletIsFull()) + barilletLancement(); + log_ ("Es::Barillet", Log::debug) << "gobage balle par l'avant."; + enableAllSensors (false); + setRVBBallStat (0); +} + +/// Analyse une balle arrivant par derrière +void +Es::newBallRear(void) +{ + /// On analyse la baballe + switch (positionBarillet_) + { + case arriere0: + stockBarillet[0] = ((colorSeen(frontBallRVB_))==whiteColor_)?white:white; + positionBarillet_ = arriere4; + log_ ("Es::Barillet", Log::debug) << "trou 0"; + break; + case arriere1: + stockBarillet[1] = ((colorSeen(frontBallRVB_))==whiteColor_)?white:white; + positionBarillet_ = arriere0; + log_ ("Es::Barillet", Log::debug) << "trou 1"; + break; + case arriere2: + stockBarillet[2] = ((colorSeen(frontBallRVB_))==whiteColor_)?white:white; + positionBarillet_ = arriere1; + log_ ("Es::Barillet", Log::debug) << "trou 2"; + break; + case arriere3: + stockBarillet[3] = ((colorSeen(frontBallRVB_))==whiteColor_)?white:white; + positionBarillet_ = arriere2; + log_ ("Es::Barillet", Log::debug) << "trou 3"; + break; + case arriere4: + stockBarillet[4] = ((colorSeen(frontBallRVB_))==whiteColor_)?white:white; + positionBarillet_ = arriere3; + log_ ("Es::Barillet", Log::debug) << "trou 4"; + break; + default: + break; + } + log_ ("Es::Barillet", Log::debug) << "gobage balle par l'arriere."; + enableAllSensors (false); + setRVBBallStat (0); +} + +/// Update system for one sensor +void +Es::updateAnalysisSensor (int value, int index, int threshold) +{ + if (value == lastSeenColors_[index]) + comptSeenColors_[index]++; + else + { + comptSeenColors_[index] = 0; + lastSeenColors_[index] = value; + } + if (comptSeenColors_[index] > threshold) + seenColors_[index] = lastSeenColors_[index]; +} + +/// Say if barillet is full +bool +Es::barilletIsFull(void) +{ + for (int i = 0; i < 5; i++) + if (stockBarillet[i] == empty) + return false; + return true; +} +/// What color do you see my lord ? +int +Es::colorSeen (int sensor_num) +{ + return seenColors_[sensor_num]; +} + +/// Totems activator +void +Es::totemActivator (bool out) +{ + // Right + setServoPos (2, out ? 0 : 200); + // Left + setServoPos (4, out ? 200 : 0); +} diff --git a/i/chuck/src/es/es.hh b/i/chuck/src/es/es.hh new file mode 100644 index 0000000..0a53ff3 --- /dev/null +++ b/i/chuck/src/es/es.hh @@ -0,0 +1,207 @@ +#ifndef es_hh +#define es_hh +// es.hh +// robert - programme du robot 2005 {{{ +// +// Copyright (C) 2005 Nicolas Haller +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} + +#include "proto/proto.hh" + +#include +#include + +class Config; + +/// Gère la carte es et ses capteurs et actionneurs +class Es : public Proto::Receiver +{ + public: + enum etatBarillet{empty,white,black}; + enum posBar{avant0 = 0x00, arriere2 = 0x04, avant4 = 0x08, arriere1 = + 0x0C, avant3 = 0x10, arriere0 = 0x14, avant2 = 0x18, arriere4 = 0x1C, + avant1 = 0x20, arriere3 = 0x24}; + typedef std::vector Sharps; + + private: + // Objet Proto de communication vers la carte es + Proto proto_; + // le tty est ... + std::string tty_; + /// Système de log + Log log_; + /// For LCD communication + char lcd_mess_char_[16]; + /// Key pressed by the LCD Keyboard + int lcdKeyPressed_, lcdKeyStat_; + /// Frontal choc ! + bool front_sensor_; + /// Ack frequency + int ackFreq_; + /// Main stat frequency + int mainStat_; + /// Config of RVB sensors + int rvbSensorFalseIC_, rvbSensorMaxOv_; + /// Config of RVB sniff + int rvbSniffRefRatio_, rvbSniffGreenLimit_, rvbSniffClearLimit_; + /// RVB Sensors raw stats + int rvbSensorMaskStat_, rvbSensorStat_; + /// RVB Sniff stats + int rvbSniffMaskStat_, rvbSniffStat_; + /// RVB Sensors raw stats + int rvbBallStat_; + /// Sharps + Sharps sharps_; + /// Others module, jack & colour + bool jackIn_, colorModeBlue_; + int othersStat_; + /// Stat of front sensors + int rvbSniffFrontStat_; + int thresholdFrontSensors_, thresholdBallSensors_, thresholdHoleSensors_; + /// Stock du barillet + etatBarillet stockBarillet[5]; + /// Position du barillet + posBar positionBarillet_; + /// System for analyse a ball + int seenColors_[5], lastSeenColors_[5], comptSeenColors_[5]; + /// Si la turbine avant est allumé + bool frontTurbineIsFull_; + + public: + // Some fucking defines ! + const int unknownColor_, redColor_, blueColor_, greenColor_, whiteColor_, + blackColor_; + const int leftFrontRVB_, rightFrontRVB_, holeRVB_, frontBallRVB_, + rearBallRVB_; + /// Constructeur + Es (const Config & config); + /// On attend ... + bool wait (int timeout = -1); + /// Récupère le File Descriptor + int getFd (void); + /// définition du receiver::receive + void receive (char command, const Proto::Frame & frame); + /// sync.. + bool sync (void); + /// Charge les paramètre du fichier de config + void loadConfig (const Config & config); + + /// Initialise les capteurs et actionneurs, reset + void reset (void); + /// Stat for the main () + void setMainStat (int freq); + /// Shut up ! + void shutUp (void); + /// Set frequency of ack + void setAckStat (int freq); + /// Get the state of the jack + bool isJackOut (void); + /// Get the color mode of the button + bool isColorModeBlue (void); + + /// Envoie de la config des sensors RVB + void setRVBSensorsConfig(int false_ic, int max_ov); + /// Envoie de la config des sniff RVB + void setRVBSniffConfig(int ref_ratio, int green_limit, int clear_limit); + /// Règle les stats des sensors RVB + void setRVBSensorsStat(int mask_captor, int freq); + /// règle la couleur actuelle comme référente + void refColor(int mask_captor, int mode = 0); + /// Règle les stats d'affichage de la couleur + void setRVBSniffStat (int mask_captor, int freq); + /// Configure statistic for the sensor of the ball + void setRVBBallStat (int freq); + /// Set frequency of front sensor in analyse mode + void setRVBSniffFrontStat (int freq); + /// Enable all the sensors or just the 4 and 1 near the ground + void enableAllSensors (bool enable); + // + void setRVBHoleStat (int freq); + + /// Set frequency of jack, selectoul printed out function + /// Use this function with frequency 0 to disable this stat. + void setOthersStat (int freq); + + /// Discute avec les servo... + void setServoPos (int servo_mask, int servoPos); + + /// Set update frequency of sharps + void setSharpUpdate (int sharp_mask, int freq); + /// Set statistics frequency of sharps + void setSharpStat (int sharp_mask, int freq); + /// Set configuration of threshold sharps + void setSharpThreshold (int sharp_num, int threshold_high, + int threshold_low); + + /// Print something on the LCD (max 32 char) + void lcdPrint (const std::string &message); + /// Get the current pressed keys of the LCD + void lcdGetKey (int freq); + + /// Règle la vitesse des turbines + void setTurbineSpeed (int turbNb, int speed); + /// Règle le sens de rotation du barillet + void setTheMeaningOfRotationOfBarillet (int answer); + /// Init the barillet and put it at the right place + void barilletInit (void); + /// Init turbine to minimal speed + void barilletDebutLancement (void); + /// Init front turbine to full speed + void barilletLancement (void); + /// Put barillet in sleep mode + void barilletSleep (void); + /// Dépose une balle du barillet + void deposeBalle(void); + /// Dépose une balle blanche + bool dropWhiteBall(void); + /// Dépose une balle noire + bool dropBlackBall(void); + /// Place un trou vide à l'avant + bool setEmptyHoleFront(void); + /// Extrait une balle + void extraitBalle(void); + /// Rotation du barillet + void rotationBarillet(int posFinal); + /// Empty everything in the barillet + void barilletEmpty (void); + /// Say if barillet is full + bool barilletIsFull(void); + /// What color do you see my lord ? + int colorSeen (int sensor_num); + /// Totems activator + void totemActivator (bool out); + /// Front sensor + bool frontSensor (void) { return front_sensor_; } + /// Clear sensor + void clearFrontSensor (void) { front_sensor_ = false; } + + private: + /// Decode a color into a string + std::string decodeColor (int color); + /// Analyse une balle arrivant par devant + void newBallFront (void); + /// Analyse une balle arrivant par derrière + void newBallRear (void); + /// Update system for one sensor + void updateAnalysisSensor (int value, int index, int threshold); +}; +#endif // es_hh diff --git a/i/chuck/src/es/test_es.cc b/i/chuck/src/es/test_es.cc new file mode 100644 index 0000000..2990d73 --- /dev/null +++ b/i/chuck/src/es/test_es.cc @@ -0,0 +1,156 @@ +// test_es.cc +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Nicolas Haller +// +// Robot APB Team/Efrei 2006. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} + +#include "tester/tester.hh" +#include "es/es.hh" +#include "timer/timer.hh" + +#include + +class TestEs : public Tester +{ + private: + Es es_; + /// Called after each command called. + void postcall (void) + { + while (!es_.wait ()) + ; + } + /// Wait. + void wait (int ms) + { + int t, stop; + t = Timer::getProgramTime (); + stop = t + ms; + while (t < stop) + { + es_.wait (stop - t); + t = Timer::getProgramTime (); + } + } + public: + // Constructor + TestEs (int argc, char ** argv) + : Tester (argc, argv), es_(config_) { } + void preRun (void) + { + Interpreter &interpreter = getInterpreter (); + // Add functions. + interpreter.add ("reset", Interpreter::memFunc (es_, &Es::reset), + "Reset ()"); + interpreter.add ("wait", Interpreter::memFunc (*this, &TestEs::wait), + "Blocking wait (time)\n" + " - time : time to wait in ms"); + interpreter.add + ("colorRef", Interpreter::memFunc (es_, &Es::refColor), + "Reference current color as green for sensors (mask)"); + interpreter.add + ("rvbAll", Interpreter::memFunc (es_, &Es::enableAllSensors), + "Drop a ball at the rear ()"); + interpreter.add + ("servoPos", Interpreter::memFunc (es_, &Es::setServoPos), + "Set servo position (mask, pos)"); + interpreter.add + ("sharpUp", Interpreter::memFunc (es_, &Es::setSharpUpdate), + "Set sharp update frequency (mask, freq)"); + interpreter.add + ("sharpStat", Interpreter::memFunc (es_, &Es::setSharpStat), + "Set sharp stats (mask, freq)"); + interpreter.add + ("sharpThreshold", Interpreter::memFunc (es_, &Es::setSharpThreshold), + "Set sharp threshold (num, high, low)\n" + " - num : sharp number (1-3)\n" + " - high : high threshold\n" + " - low : low threshold"); + interpreter.add + ("lcdPrint", Interpreter::memFunc (es_, &Es::lcdPrint), + "Print a message (32 char max) onto the LCD (message)"); + interpreter.add + ("lcdKey", Interpreter::memFunc (es_, &Es::lcdGetKey), + "Set stat for key if pressed (freq)"); + interpreter.add + ("turbSpeed", Interpreter::memFunc (es_, &Es::setTurbineSpeed), + "Set turbine speed (num, speed)\n" + " - num : 1 front, 2 rear\n" + " - speed : 256 - 819"); + interpreter.add + ("turbMinSpeed", Interpreter::memFunc (es_, + &Es::barilletDebutLancement), + "Turbine minimal speed ()"); + interpreter.add + ("turbFrontFull", Interpreter::memFunc (es_, + &Es::barilletLancement), + "Turbine front full speed ()"); + interpreter.add + ("barSleep", Interpreter::memFunc (es_, &Es::barilletSleep), + "Barillet in sleep mode (low speed turbine)"); + interpreter.add + ("turbDepose", Interpreter::memFunc (es_, &Es::deposeBalle), + "Drop a ball at the rear ()"); + interpreter.add + ("barDropWhite", Interpreter::memFunc (es_, &Es::dropWhiteBall), + "drop une balle blanche"); + interpreter.add("barDropBlack", Interpreter::memFunc (es_, + &Es::dropBlackBall), + "drop une balle noire"); + interpreter.add("barSetEmpty", Interpreter::memFunc (es_, + &Es::setEmptyHoleFront), + "met un trou vide en position avale une balle"); + interpreter.add + ("barExtract", Interpreter::memFunc (es_, &Es::extraitBalle), + "Extract a ball ()"); + interpreter.add + ("barInit", Interpreter::memFunc (es_, &Es::barilletInit), + "Init barillet ()"); + interpreter.add + ("barGoTo", Interpreter::memFunc (es_, &Es::rotationBarillet), + "Barillet go to position (pos)\n" + " - pos : in 40° of a round"); + interpreter.add + ("barPurge", Interpreter::memFunc (es_, &Es::barilletEmpty), + "Extract a ball ()"); + interpreter.add ("_postcall", + Interpreter::memFunc (*this, &TestEs::postcall)); + } + void postRun (void) + { + es_.reset (); + } +}; + +int +main (int argc, char **argv) +{ + try + { + TestEs te (argc, argv); + te.run (); + } + catch (const std::exception &e) + { + std::cerr << e.what () << std::endl; + } +} diff --git a/i/chuck/src/interpreter/Makefile.defs b/i/chuck/src/interpreter/Makefile.defs new file mode 100644 index 0000000..32c9e48 --- /dev/null +++ b/i/chuck/src/interpreter/Makefile.defs @@ -0,0 +1,6 @@ +PROGRAMS += test_interpreter + +interpreter_OBJECTS = interpreter.o interpreter_parser.o \ + $(utils_OBJECTS) $(parser_OBJECTS) + +test_interpreter_OBJECTS = test_interpreter.o $(interpreter_OBJECTS) diff --git a/i/chuck/src/interpreter/interpreter.cc b/i/chuck/src/interpreter/interpreter.cc new file mode 100644 index 0000000..bbf4767 --- /dev/null +++ b/i/chuck/src/interpreter/interpreter.cc @@ -0,0 +1,127 @@ +// interpreter.cc +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Nicolas Schodet +// +// Robot APB Team/Efrei 2006. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "interpreter.hh" +#include "interpreter_parser.hh" + +/// Destructor. +Interpreter::~Interpreter (void) +{ + for (Funcs::iterator i = funcs_.begin (); i != funcs_.end (); ++i) + { + delete i->second.func; + } +} + +/// Add a function, Interpreter owns f. +void +Interpreter::add (const std::string &s, Func *f, const std::string &desc) +{ + if (!funcs_.insert (Funcs::value_type (s, FuncDesc (f, desc))).second) + { + // Interpreter owns f, therefore, f must be deleted. + delete f; + throw std::runtime_error ("function \'" + s + + "\' inserted two times"); + } +} + +/// Add a function without description, Interpreter owns f. +void +Interpreter::add (const std::string &s, Func *f) +{ + add (s, f, ""); +} + +/// Test if a function is defined. +bool +Interpreter::exists (const std::string &s) const +{ + Funcs::const_iterator i; + i = funcs_.find (s); + return i != funcs_.end (); +} + +/// Call a function by name. +void +Interpreter::call (const std::string &s, const Args &a, + bool dryrun/*false*/) const +{ + Funcs::const_iterator i; + i = funcs_.find (s); + if (i == funcs_.end ()) + throw std::runtime_error ("function \'" + s + "\' does not exist"); + try + { + (*i->second.func) (a, dryrun); + } + catch (const std::exception &e) + { + throw std::runtime_error ("while calling \'" + s + "\', " + + e.what ()); + } +} + +/// Interpret a string. +void +Interpreter::interpretString (const std::string &s, bool dryrun/*false*/) +{ + InterpreterParser p (*this, dryrun); + p.parseString (s); +} + +/// Interpret a file. +void +Interpreter::interpretFile (const std::string &file, bool dryrun/*false*/) +{ + InterpreterParser p (*this, dryrun); + p.parseFile (file); +} + +/// Return an help string. +std::string +Interpreter::help (void) const +{ + std::string ret; + for (Funcs::const_iterator i = funcs_.begin (); i != funcs_.end (); ++i) + { + ret += i->first; + if (!i->second.desc.empty ()) + { + ret += " : "; + // Well, if you really want to implement this better, please do... + for (std::string::const_iterator j = i->second.desc.begin (); + j != i->second.desc.end (); j++) + { + if (*j == '\n') + ret += "\n "; + else + ret += *j; + } + } + ret += '\n'; + } + return ret; +} + diff --git a/i/chuck/src/interpreter/interpreter.hh b/i/chuck/src/interpreter/interpreter.hh new file mode 100644 index 0000000..3341ea1 --- /dev/null +++ b/i/chuck/src/interpreter/interpreter.hh @@ -0,0 +1,90 @@ +#ifndef interpreter_hh +#define interpreter_hh +// interpreter.hh +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Nicolas Schodet +// +// Robot APB Team/Efrei 2006. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "utils/any.hh" + +#include + +class Interpreter +{ + public: + /// Function arguments. + typedef any Arg; + /// Function arguments list. + typedef std::list Args; + /// Functions must inherit from this type. + class Func + { + public: + /// Mandatory virtual destructor. + virtual ~Func (void) + { } + /// Called on function invocation, getting the argument list and + /// returning true on success. + virtual void operator() (const Args &, bool dryrun) = 0; + }; + private: + /// Func class construction helper. + template + class MemFunc; + private: + struct FuncDesc + { + Func *func; + std::string desc; + FuncDesc (Func *func_, const std::string &desc_) + : func (func_), desc (desc_) { } + }; + /// Type of the private function map. + typedef std::map Funcs; + /// The function map itself. + Funcs funcs_; + public: + /// Destructor. + ~Interpreter (void); + /// Add a function, Interpreter owns f. + void add (const std::string &s, Func *f, const std::string &desc); + /// Add a function without description, Interpreter owns f. + void add (const std::string &s, Func *f); + /// Test if a function is defined. + bool exists (const std::string &s) const; + /// Call a function by name. + void call (const std::string &s, const Args &a, + bool dryrun = false) const; + /// Interpret a string. + void interpretString (const std::string &s, bool dryrun = false); + /// Interpret a file. + void interpretFile (const std::string &file, bool dryrun = false); + /// Return an help string. + std::string help (void) const; + /// Take all the template sophistications out of the programmer hands. + template + static Func *memFunc (T &i, F f); +}; + +#include "interpreter.tcc" + +#endif // interpreter_hh diff --git a/i/chuck/src/interpreter/interpreter.tcc b/i/chuck/src/interpreter/interpreter.tcc new file mode 100644 index 0000000..5af0e0a --- /dev/null +++ b/i/chuck/src/interpreter/interpreter.tcc @@ -0,0 +1,142 @@ +#ifndef interpreter_tcc +#define interpreter_tcc +// interpreter.tcc +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Nicolas Schodet +// +// Robot APB Team/Efrei 2006. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "utils/meta/remove_reference.hh" + +#include + +/// Func class construction helper. +template +class Interpreter::MemFunc +{ +}; + +/// Partially specialised for member functions taking an arguments list. +template +class Interpreter::MemFunc +: public Func +{ + T &i_; + typedef void (T::*F) (const Interpreter::Args &, bool); + F f_; + public: + MemFunc (T &i, F f) : i_ (i), f_ (f) { } + void operator() (const Args &a, bool dryrun) + { + (i_.*f_) (a, dryrun); + } +}; + +/// Partially specialised for members functions taking no argument. +template +class Interpreter::MemFunc : public Func +{ + T &i_; + typedef R (T::*F) (void); + F f_; + public: + MemFunc (T &i, F f) : i_ (i), f_ (f) { } + void operator() (const Args &a, bool dryrun) + { + if (!a.empty ()) + throw std::runtime_error ("no argument expected"); + if (!dryrun) + (i_.*f_) (); + } +}; + +/// Partially specialised for members functions taking one argument. +template +class Interpreter::MemFunc : public Func +{ + T &i_; + typedef R (T::*F) (A1); + F f_; + public: + MemFunc (T &i, F f) : i_ (i), f_ (f) { } + void operator() (const Args &a, bool dryrun) + { + Args::const_iterator i = a.begin (); + if (a.size () != 1) + throw std::runtime_error ("one argument expected"); + A1 a1 = any_cast::type> (*i); + if (!dryrun) + (i_.*f_) (a1); + } +}; + +/// Partially specialised for members functions taking two arguments. +template +class Interpreter::MemFunc : public Func +{ + T &i_; + typedef R (T::*F) (A1, A2); + F f_; + public: + MemFunc (T &i, F f) : i_ (i), f_ (f) { } + void operator() (const Args &a, bool dryrun) + { + Args::const_iterator i = a.begin (); + if (a.size () != 2) + throw std::runtime_error ("two arguments expected"); + A1 a1 = any_cast::type> (*i); + A2 a2 = any_cast::type> (*++i); + if (!dryrun) + (i_.*f_) (a1, a2); + } +}; + +/// Partially specialised for members functions taking three arguments. +template +class Interpreter::MemFunc : public Func +{ + T &i_; + typedef R (T::*F) (A1, A2, A3); + F f_; + public: + MemFunc (T &i, F f) : i_ (i), f_ (f) { } + void operator() (const Args &a, bool dryrun) + { + Args::const_iterator i = a.begin (); + if (a.size () != 3) + throw std::runtime_error ("three arguments expected"); + A1 a1 = any_cast::type> (*i); + A2 a2 = any_cast::type> (*++i); + A3 a3 = any_cast::type> (*++i); + if (!dryrun) + (i_.*f_) (a1, a2, a3); + } +}; + +/// Take all the template sophistications out of the programmer hands. +template +Interpreter::Func * +Interpreter::memFunc (T &i, F f) +{ + return new MemFunc (i, f); +} + +#endif // interpreter_tcc diff --git a/i/chuck/src/interpreter/interpreter_parser.cc b/i/chuck/src/interpreter/interpreter_parser.cc new file mode 100644 index 0000000..f10e8ec --- /dev/null +++ b/i/chuck/src/interpreter/interpreter_parser.cc @@ -0,0 +1,43 @@ +// interpreter_parser.cc +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Nicolas Schodet +// +// Robot APB Team/Efrei 2006. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "interpreter_parser.hh" +#include "interpreter.hh" + +/// Constructor. +InterpreterParser::InterpreterParser (Interpreter &interpreter, + bool dryrun/*false*/) + : interpreter_ (interpreter), dryrun_ (dryrun) +{ +} + +/// Function called by the parser to make a call. +void +InterpreterParser::call (const std::string &id, AnyList &args) +{ + interpreter_.call (id, args, dryrun_); + if (interpreter_.exists ("_postcall")) + interpreter_.call ("_postcall", AnyList (), dryrun_); +} + diff --git a/i/chuck/src/interpreter/interpreter_parser.hh b/i/chuck/src/interpreter/interpreter_parser.hh new file mode 100644 index 0000000..3bd256d --- /dev/null +++ b/i/chuck/src/interpreter/interpreter_parser.hh @@ -0,0 +1,43 @@ +#ifndef interpreter_parser_hh +#define interpreter_parser_hh +// interpreter_parser.hh +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Nicolas Schodet +// +// Robot APB Team/Efrei 2006. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "parser/parser.hh" + +class Interpreter; + +/// Parser used by Interpreter. +class InterpreterParser : public Parser +{ + Interpreter &interpreter_; + bool dryrun_; + public: + /// Constructor. + InterpreterParser (Interpreter &interpreter, bool dryrun = false); + /// Function called by the parser to make a call. + void call (const std::string &id, AnyList &args); +}; + +#endif // interpreter_parser_hh diff --git a/i/chuck/src/interpreter/test_interpreter.cc b/i/chuck/src/interpreter/test_interpreter.cc new file mode 100644 index 0000000..631d10d --- /dev/null +++ b/i/chuck/src/interpreter/test_interpreter.cc @@ -0,0 +1,139 @@ +// test_interpreter.cc +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Nicolas Schodet +// +// Robot APB Team/Efrei 2006. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "interpreter.hh" + +#include +#include +#include + +class TestInterpreter +{ + Interpreter t; + public: + void funcA (const Interpreter::Args &a, bool dryrun) + { + if (!dryrun) + std::cout << " a " << a << std::endl; + } + bool funcB (void) + { + std::cout << " b ( )" << std::endl; + return true; + } + int funcC (int i) + { + std::cout << " c ( " << i << " )" << std::endl; + return 0; + } + void funcD (const std::string &s) + { + std::cout << " d ( " << s << " )" << std::endl; + } + void funcE (int i, const std::string &s, double d) + { + std::cout << " e ( " << i << ' ' << s << ' ' << d << " )" << std::endl; + } + void call (const std::string &s, const Interpreter::Args &a) + { + try + { + std::cout << "call " << s << ' ' << a << std::endl; + t.call (s, a); + } + catch (const std::exception &e) + { + // Do not use std::cerr as there should be only normal errors. + std::cout << ' ' << e.what () << std::endl; + } + } + void interpretString (const std::string &s) + { + try + { + std::cout << "interpret dry \"" << s << "\"" << std::endl; + t.interpretString (s, true); + std::cout << "interpret \"" << s << "\"" << std::endl; + t.interpretString (s); + } + catch (const std::exception &e) + { + // Do not use std::cerr as there should be only normal errors. + std::cout << ' ' << e.what () << std::endl; + } + } + int main (void) + { + // Add functions. + t.add ("a", Interpreter::memFunc (*this, &TestInterpreter::funcA), + "a ARGS...\n" + "the wonderful `a' function taking any number of any arguments"); + t.add ("b", Interpreter::memFunc (*this, &TestInterpreter::funcB), + "b\ntakes no argument"); + t.add ("c", Interpreter::memFunc (*this, &TestInterpreter::funcC), + "c THE_MIGHTY_NUMBER\n" + "takes one integer"); + t.add ("d", Interpreter::memFunc (*this, &TestInterpreter::funcD), + "d THE_STRING\n" + "takes one string"); + t.add ("e", Interpreter::memFunc (*this, &TestInterpreter::funcE), + "e INT STRING DOUBLE\n" + "takes one integer, one string and one double"); + // Make argument lists. + Interpreter::Args a[4]; + a[1].push_back (71117); + a[2].push_back (std::string ("robert")); + a[3].push_back (42); + a[3].push_back (std::string ("merguez")); + a[3].push_back (51.1664); + // Need help? + std::cout << t.help () << std::endl; + // Call all those wonderful functions. + call ("unknown", a[0]); + for (unsigned int i = 0; i < sizeof (a) / sizeof (a[0]); ++i) + { + for (char f = 'a'; f <= 'e'; f++) + { + call (std::string (1, f), a[i]); + } + } + // Now, with the interpreter. + interpretString ("a = 42"); + interpretString ("42"); + for (char f = 'a'; f <= 'e'; f++) + { + interpretString (std::string (1, f)); + interpretString (std::string (1, f) + " 42 "); + interpretString (std::string (1, f) + " \"robert\";; "); + interpretString (std::string (1, f) + " 757 \"tintin\" 0.3141516e+1"); + } + return 0; + } +}; + +int main (void) +{ + TestInterpreter tt; + return tt.main (); +} diff --git a/i/chuck/src/log/Makefile.defs b/i/chuck/src/log/Makefile.defs new file mode 100644 index 0000000..43aaed4 --- /dev/null +++ b/i/chuck/src/log/Makefile.defs @@ -0,0 +1,12 @@ +PROGRAMS += test_log test_log_server + +log_server_OBJECTS = log_server.o $(socket_databuffer_OBJECTS) + +log_OBJECTS = log.o log_message.o logger.o \ + logger_stdout.o logger_file.o logger_ram.o \ + data_circular_buffer_factory.o \ + $(log_server_OBJECTS) \ + $(config_OBJECTS) $(data_OBJECTS) + +test_log_OBJECTS = test_log.o $(log_OBJECTS) +test_log_server_OBJECTS = test_log_server.o $(log_server_OBJECTS) $(data_OBJECTS) diff --git a/i/chuck/src/log/data_circular_buffer_factory.cc b/i/chuck/src/log/data_circular_buffer_factory.cc new file mode 100644 index 0000000..a45d3bc --- /dev/null +++ b/i/chuck/src/log/data_circular_buffer_factory.cc @@ -0,0 +1,72 @@ +// data_circular_buffer_factory.cc +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Dufour Jérémy +// +// Robot APB Team/Efrei 2004. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "data_circular_buffer_factory.hh" +#include "log_server.hh" + +#include + +/// Initialisation of static member. +DataCircularBuffer *DataCircularBufferFactory::dbBuffer_ = 0; +unsigned DataCircularBufferFactory::refCount_ = 0; + +/// Default empty constructor. +DataCircularBufferFactory::DataCircularBufferFactory (void) +{ + refCount_++; +} +/// Destructor. +DataCircularBufferFactory::~DataCircularBufferFactory (void) +{ + refCount_--; + // End of use ? + if (!refCount_ && dbBuffer_) + { + // XXX Create a server in a try/catch block for removing exception. + try + { + LogServer(*dbBuffer_, "", 2442); + } + catch(std::exception & ex) + { + std::cout << ex.what() << std::endl; + } +// uint8_t c; +// while (dbBuffer_-> read (&c, 1)) +// std::cout << c; + delete dbBuffer_; + dbBuffer_ = 0; + } +} + +/// Get a DataCircularBuffer. +DataCircularBuffer & +DataCircularBufferFactory::getDataCircularBuffer (void) +{ + if (!dbBuffer_) + // 100Ko + // TODO: config ? + dbBuffer_ = new DataCircularBuffer (100000); + return *dbBuffer_; +} diff --git a/i/chuck/src/log/data_circular_buffer_factory.hh b/i/chuck/src/log/data_circular_buffer_factory.hh new file mode 100644 index 0000000..8f0874f --- /dev/null +++ b/i/chuck/src/log/data_circular_buffer_factory.hh @@ -0,0 +1,53 @@ +#ifndef data_circular_buffer_factory_hh +#define data_circular_buffer_factory_hh +// data_circular_buffer_factory.hh +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Dufour Jérémy +// +// Robot APB Team/Efrei 2004. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} + +#include "data/data_circular_buffer.hh" + +/// The purpose of this class is to provide a factory of data_circular_buffer. +/// In fact, we will create only one data_circula_buffer and we provide a +/// reference to this one to logger_ram. When the data_circular_buffer will be +/// deleted, we will launch a socket server for fetching data remotely with a +/// netcat. + +class DataCircularBufferFactory +{ + friend class LoggerRam; + friend class Tester; + private: + /// The only DataCircularBuffer. + static DataCircularBuffer *dbBuffer_; + /// Reference counter. + static unsigned refCount_; + /// Default empty constructor. + DataCircularBufferFactory (void); + /// Destructor. + ~DataCircularBufferFactory (void); + /// Get a DataCircularBuffer. + DataCircularBuffer & getDataCircularBuffer (void); +}; + +#endif // data_circular_buffer_factory_hh diff --git a/i/chuck/src/log/log.cc b/i/chuck/src/log/log.cc new file mode 100644 index 0000000..cd7bb32 --- /dev/null +++ b/i/chuck/src/log/log.cc @@ -0,0 +1,130 @@ +// log.cc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2004 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "log.hh" + +#include "config/config.hh" +#include "logger.hh" + +#include + +/// Constructeur. +Log::Log (const char *module, const char *instance) + : module_ (module), instance_ (instance) +{ + // Get Config + Config &config = Config::getInstance (); + // Get default level log + std::string defaultLvl = config.get("log.level.default", + "info"); + level_ = toLevel (defaultLvl); + // Get private level if exist + level_ = toLevel (config.get + (std::string ("log.level.") + module_, defaultLvl)); + + // Create the null logger + loggerNull_ = Logger::create ("null"); + // Create the real logger + logger_ = Logger::create (config.get + (std::string ("log.logger.") + module_, + config.get + (std::string ("log.logger.default"), "stdout"))); +} + +Log::~Log (void) +{ + delete loggerNull_; + delete logger_; +} + +/// Crée un nouveau LogMessage. +LogMessage +Log::operator() (const char *msg, Level level/*info*/) const +{ + // Check level + if (level <= getLevel()) + // Use real logger + return LogMessage (*this, *logger_, msg, level); + else + // Use null logger + return LogMessage (*this, *loggerNull_, msg, level); +} + +/// Traduit le niveau de log. +std::string +Log::toString (Level level) +{ + switch (level) + { + case none: + return "none"; + case fatal: + return "fatal"; + case error: + return "error"; + case warning: + return "warning"; + case info: + return "info"; + case debug: + return "debug"; + case verydebug: + return "verydebug"; + default: + return "logunknown"; + } +} + +/// Traduit le niveau de log. +Log::Level +Log::toLevel (const std::string &level) +{ + switch (level[0]) + { + case 'n': + return none; + case 'f': + return fatal; + case 'e': + return error; + case 'w': + return warning; + case 'i': + return info; + case 'd': + return debug; + case 'v': + return verydebug; + default: + return levelReserved; + } +} + +/// Change un niveau de log en masque. +Log::Level +Log::toLevelMask (Log::Level level) +{ + return static_cast ((level - 1) | level); +} + diff --git a/i/chuck/src/log/log.hh b/i/chuck/src/log/log.hh new file mode 100644 index 0000000..1141962 --- /dev/null +++ b/i/chuck/src/log/log.hh @@ -0,0 +1,82 @@ +#ifndef log_hh +#define log_hh +// log.h +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2004 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include +#include + +class LogMessage; +class Logger; + +/// Classe de log. Permet de construire des LogMessage. +class Log +{ + public: + enum Level + { + none = 0x00, + fatal = 0x01, + error = 0x02, + warning = 0x04, + info = 0x08, + debug = 0x10, + verydebug = 0x20, + levelReserved = 0xffff + }; + private: + const char *module_; + const char *instance_; + Level level_; + /// Null logger. + Logger *loggerNull_; + /// Real logger. + Logger *logger_; + + public: + /// Constructeur. + Log (const char *module, const char *instance = 0); + /// Destructor. + ~Log (void); + /// Crée un nouveau LogMessage. + LogMessage operator() (const char *msg, Level level = info) const; + /// Récupère le module. + const char *getModule (void) const { return module_; } + /// Récupère l'instance. + const char *getInstance (void) const { return instance_; } + /// Traduit le niveau de log. + static std::string toString (Level level); + /// Traduit le niveau de log. + static Level toLevel (const std::string &level); + /// Change un niveau de log en masque. + static Level toLevelMask (Level level); + /// Récupère le niveau de log + Level getLevel(void) const { return level_; } + /// Set le niveau de log + void setLevel(Level level) { level_ = level; } +}; + +#include "log_message.hh" + +#endif // log_hh diff --git a/i/chuck/src/log/log_message.cc b/i/chuck/src/log/log_message.cc new file mode 100644 index 0000000..4305374 --- /dev/null +++ b/i/chuck/src/log/log_message.cc @@ -0,0 +1,74 @@ +// log_message.cc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2004 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "log_message.hh" + +#include + +/// Constructeur. +LogMessage::LogMessage (const Log &log, Logger &logger, const char *msg, + Log::Level level) +: logger_ (logger) +{ + logger_.start (log, msg, level); +} + +/// Destructeur. +LogMessage::~LogMessage (void) +{ + logger_.stop (); +} + +/// Output a string or a variable name. +LogMessage & +LogMessage::operator<< (const char *s) +{ + logger_ << s; + return *this; +} + +/// Output a string or a variable name. +LogMessage & +LogMessage::operator<< (const std::string &s) +{ + logger_ << s; + return *this; +} + +/// Output a integer. +LogMessage & +LogMessage::operator<< (int i) +{ + logger_ << i; + return *this; +} + +/// Output a double. +LogMessage & +LogMessage::operator<< (double d) +{ + logger_ << d; + return *this; +} + diff --git a/i/chuck/src/log/log_message.hh b/i/chuck/src/log/log_message.hh new file mode 100644 index 0000000..718e6ae --- /dev/null +++ b/i/chuck/src/log/log_message.hh @@ -0,0 +1,55 @@ +#ifndef log_message_hh +#define log_message_hh +// log_message.hh +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2004 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} + +#include "log.hh" +#include "logger.hh" + +class LogMessage +{ + private: + Logger &logger_; + public: + /// Constructeur. + LogMessage (const Log &log, Logger &logger, const char *msg, Log::Level level); + /// Destructeur. + ~LogMessage (void); + /// Output a string or a variable name. + LogMessage &operator<< (const char *s); + /// Output a string or a variable name. + LogMessage &operator<< (const std::string &s); + /// Output a integer. + LogMessage &operator<< (int i); + /// Output a double. + LogMessage &operator<< (double d); + /// Output a OutputStreamable as a string. + template + LogMessage &operator<< (const OutputStreamable &o); +}; + +#include "log_message.tcc" + +#endif // log_message_hh diff --git a/i/chuck/src/log/log_message.tcc b/i/chuck/src/log/log_message.tcc new file mode 100644 index 0000000..4928d59 --- /dev/null +++ b/i/chuck/src/log/log_message.tcc @@ -0,0 +1,36 @@ +// log_message.tcc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2004 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} + +#include + +/// Output a OutputStreamable as a string. +template +LogMessage & +LogMessage::operator<< (const OutputStreamable &o) +{ + logger_ << o; + return *this; +} + diff --git a/i/chuck/src/log/log_server.cc b/i/chuck/src/log/log_server.cc new file mode 100644 index 0000000..126ed66 --- /dev/null +++ b/i/chuck/src/log/log_server.cc @@ -0,0 +1,54 @@ +// log_server.cc +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Nicolas Haller +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "log_server.hh" +#include "socket/socket_client.hh" + +LogServer::LogServer(DataInput & di, const Address & address) + :ss_(address),di_(di) +{ +} + +LogServer::LogServer(DataInput & di, const std::string & address, + int port) + :ss_(address, port),di_(di) +{ +} + +void +LogServer::listen(void) +{ + int charBuffer; + + const unsigned BUFFER_SIZE = 256; + // Buffer de taille completement arbitraire + uint8_t buffer[BUFFER_SIZE]; + // Ouvre les oreilles du socket + ss_.listen(1); + // Attend gentillement une connection + SocketClient sc(ss_); + // Paf on envoie la sauce + while((charBuffer = di_.read(buffer, BUFFER_SIZE)) != 0) + sc.write(buffer, charBuffer); +} diff --git a/i/chuck/src/log/log_server.hh b/i/chuck/src/log/log_server.hh new file mode 100644 index 0000000..a18de15 --- /dev/null +++ b/i/chuck/src/log/log_server.hh @@ -0,0 +1,50 @@ +#ifndef log_server_hh +#define log_server_hh +// log_server.hh +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Nicolas Haller +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} + +#include "socket/socket_server.hh" +#include "data/data_input.hh" + +/// Classe pour récupérer les logs. +/// La classe construit un serveur en fin de match pour pouvoir récupérer les +/// logs de la pc104 +class LogServer +{ + private: + /// La socket serveur qui attend la ze connection + SocketServer ss_; + /// La dataBuffer à transmettre (avec les logs dedans c'est mieux) + DataInput & di_; + public: + /// Constructeur + LogServer(DataInput & di, const Address & address); + /// Constructeur + LogServer(DataInput & di, const std::string & address, int port); + /// Mise en écoute du serveur + void listen(void); +}; + +#endif // log_server_hh diff --git a/i/chuck/src/log/logger.cc b/i/chuck/src/log/logger.cc new file mode 100644 index 0000000..128aa16 --- /dev/null +++ b/i/chuck/src/log/logger.cc @@ -0,0 +1,52 @@ +// logger.cc +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Dufour Jérémy +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: %WEB% +// Email: +// }}} +#include "logger.hh" + +#include "logger_null.hh" +#include "logger_stdout.hh" +#include "logger_file.hh" +#include "logger_ram.hh" + +#include + +/// Create a logger from the name. +Logger * +Logger::create (const std::string &loggerName) +{ + if (loggerName == "null") + return new LoggerNull; + else if (loggerName == "stdout") + return new LoggerStdout; + else if (loggerName.substr (0, 4) == "file") + if (loggerName.size () < 6) + throw std::runtime_error ("Missing filename"); + else + return new LoggerFile (loggerName.substr (5)); + else + if (loggerName.substr (0, 3) == "ram") + return new LoggerRam; + throw std::invalid_argument ("Unknown logger : " + loggerName); + return 0; +} + diff --git a/i/chuck/src/log/logger.hh b/i/chuck/src/log/logger.hh new file mode 100644 index 0000000..cc47095 --- /dev/null +++ b/i/chuck/src/log/logger.hh @@ -0,0 +1,68 @@ +#ifndef logger_hh +#define logger_hh +// logger.hh +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Dufour Jérémy +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: %WEB% +// Email: +// }}} + +#include "log.hh" + +#include + +class Logger +{ + public: + /// Empty destructor. + virtual ~Logger (void) { } + /// Create a logger. + static Logger *create (const std::string &loggerName); + /// Called when a message will be logged. + virtual void start (const Log &log, const char *msg, Log::Level level) = 0; + /// Called when a message has been logged. + virtual void stop (void) = 0; + /// Output a string or a variable name. + virtual Logger &operator<< (const char *s) = 0; + /// Output a string or a variable name. + virtual Logger &operator<< (const std::string &s) = 0; + /// Output a integer. + virtual Logger &operator<< (int i) = 0; + /// Output a double. + virtual Logger &operator<< (double d) = 0; + /// TODO vector + + protected: + /// Private empty constructor. + Logger (void) { } +}; + +#include + +template +Logger &operator<< (Logger &l, const T &v) +{ + std::ostringstream ss; + ss << v; + l << ss.str (); + return l; +} + +#endif // logger_hh diff --git a/i/chuck/src/log/logger_file.cc b/i/chuck/src/log/logger_file.cc new file mode 100644 index 0000000..011a470 --- /dev/null +++ b/i/chuck/src/log/logger_file.cc @@ -0,0 +1,144 @@ +// logger_file.cc +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Dufour Jérémy +// +// Robot APB Team/Efrei 2004. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "logger_file.hh" + +#include +#include +#include + +LoggerFile::t_files_ LoggerFile::files_; + +/// Default constructor. +LoggerFile::LoggerFile (const std::string ¶m) + : filename_ (param) +{ + if (param.empty ()) + throw std::invalid_argument ("Missing filename for file logger"); + file_ = getFile (); +} + +/// Default destructor. +LoggerFile::~LoggerFile (void) +{ + try + { + releaseFile (); + } + catch (std::runtime_error &) + { + } +} + +/// Get a ofstream associated to the filename. +/// This function manage multiple log to the same file by couting the number +/// reference to the file. +std::ofstream * +LoggerFile::getFile (void) +{ + t_files_::iterator i = files_.find (filename_); + // If file does not exist + if (i == files_.end ()) + { + // Create it + std::ofstream *file = new std::ofstream (filename_.c_str ()); + // Add it + files_[filename_] = t_pair_files_ (1, file); + return file; + } + else + { + // Increment number of reference + t_pair_files_ &pair_file = i->second; + pair_file.first++; + return pair_file.second; + } +} + +/// Release the file from the map if needed. Return true if deleted. +bool +LoggerFile::releaseFile (void) +{ + t_files_::iterator i = files_.find (filename_); + // If file does not exist + if (i == files_.end ()) + throw std::runtime_error ("Trying to release an unknown file ?!"); + else + { + t_pair_files_ &pair_file = i->second; + // Decrement number of reference + pair_file.first--; + // Delete it if needed + if (pair_file.first == 0) + { + delete pair_file.second; + files_.erase (i); + return true; + } + } + return false; +} + +/// Called at the begining of a message. +void +LoggerFile::start (const Log &log, const char *msg, Log::Level level) +{ + *file_ << log.getModule () << ':'; + const char *instance = log.getInstance (); + if (instance) + *file_ << ' ' << instance << ':'; + *file_ << " (" << msg << ')'; +} + +/// Output a string or a variable name. +LoggerFile & +LoggerFile::operator<< (const char *s) +{ + *file_ << ' ' << s; + return *this; +} + +/// Output a string or a variable name. +LoggerFile & +LoggerFile::operator<< (const std::string &s) +{ + *file_ << ' ' << s; + return *this; +} + +/// Output a integer. +LoggerFile & +LoggerFile::operator<< (int i) +{ + *file_ << ' ' << i; + return *this; +} + +/// Output a double. +LoggerFile & +LoggerFile::operator<< (double d) +{ + *file_ << ' ' << d; + return *this; +} diff --git a/i/chuck/src/log/logger_file.hh b/i/chuck/src/log/logger_file.hh new file mode 100644 index 0000000..2cfd4d4 --- /dev/null +++ b/i/chuck/src/log/logger_file.hh @@ -0,0 +1,70 @@ +#ifndef logger_file_hh +#define logger_file_hh +// logger_file.hh +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Dufour Jérémy +// +// Robot APB Team/Efrei 2004. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} + +#include "logger.hh" + +#include +#include +#include + +/// Logger to a file. +class LoggerFile : public Logger +{ + /// The pair contains the number of log reference to the file. + typedef std::pair t_pair_files_; + /// Map of opened file, to manage multiple module access to the same file. + typedef std::map t_files_; + static t_files_ files_; + /// Local file used by this instance of the logger file. + std::ofstream *file_; + /// Local file name. + std::string filename_; + public: + /// Default constructor. + LoggerFile (const std::string ¶m); + /// Default destructor. + ~LoggerFile (void); + /// Called at the begining of a message. + void start (const Log &log, const char *msg, Log::Level level); + /// Called at the end of a message. + void stop (void) { *file_ << std::endl; } + /// Output a string or a variable name. + LoggerFile &operator<< (const char *s); + /// Output a string or a variable name. + LoggerFile &operator<< (const std::string &s); + /// Output a integer. + LoggerFile &operator<< (int i); + /// Output a double. + LoggerFile &operator << (double d); + private: + /// Get a ofstream associated to the filename. + std::ofstream *getFile (void); + /// Release the file from the map if needed. Return true if deleted. + bool releaseFile (void); +}; + +#endif // logger_file_hh diff --git a/i/chuck/src/log/logger_null.hh b/i/chuck/src/log/logger_null.hh new file mode 100644 index 0000000..03c71a6 --- /dev/null +++ b/i/chuck/src/log/logger_null.hh @@ -0,0 +1,51 @@ +#ifndef logger_null_hh +#define logger_null_hh +// logger_null.hh +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Dufour Jérémy +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: %WEB% +// Email: +// }}} + +#include "logger.hh" + +/// Null logger to prevent losing time. +class LoggerNull : public Logger +{ + public: + /// Default empty constructor. + LoggerNull (void) { } + /// Default empty destructor. + ~LoggerNull (void) { } + /// Empty start. + void start (const Log &, const char *, Log::Level) { } + /// Empty stop. + void stop (void) { } + /// Empty << string or variable name. + LoggerNull &operator<< (const char *) { return *this; } + /// Empty << string or variable name. + LoggerNull &operator<< (const std::string &) { return *this; } + /// Empty << integer. + LoggerNull &operator<< (int) { return *this; } + /// Empty << double. + LoggerNull &operator << (double) { return *this; } +}; + +#endif // logger_null_hh diff --git a/i/chuck/src/log/logger_ram.cc b/i/chuck/src/log/logger_ram.cc new file mode 100644 index 0000000..720d0e8 --- /dev/null +++ b/i/chuck/src/log/logger_ram.cc @@ -0,0 +1,98 @@ +// logger_ram.cc +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Dufour Jérémy +// +// Robot APB Team/Efrei 2004. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "logger_ram.hh" + +#include +#include // Convertion from num to string + +/// Default constructor. +LoggerRam::LoggerRam (void) + : buffer_ (bufferFactory_.getDataCircularBuffer ()) +{ +} + +/// Called at the begining of a message. +void +LoggerRam::start (const Log &log, const char *msg, Log::Level level) +{ + strTmp_ = log.getModule (); + strTmp_.append (":"); + + const char *instance = log.getInstance (); + if (instance) + { + strTmp_.append (" "); + strTmp_.append (instance); + strTmp_.append (":"); + } + strTmp_.append (" ("); + strTmp_.append (msg); + strTmp_.append (")"); + + buffer_.write (reinterpret_cast (strTmp_.data ()), strTmp_.size ()); +} + +/// Output a string or a variable name. +LoggerRam & +LoggerRam::operator<< (const char *s) +{ + strTmp_ = " "; + strTmp_.append (s); + buffer_.write (reinterpret_cast (strTmp_.data ()), strTmp_.size ()); + return *this; +} + +/// Output a string or a variable name. +LoggerRam & +LoggerRam::operator<< (const std::string &s) +{ + strTmp_ = " " + s; + buffer_.write (reinterpret_cast (strTmp_.data ()), strTmp_.size ()); + return *this; +} + +/// Output a integer. +LoggerRam & +LoggerRam::operator<< (int i) +{ + strTmp_ = " "; + std::ostringstream oStr; + oStr << i; + strTmp_.append (oStr.str ()); + buffer_.write (reinterpret_cast (strTmp_.data ()), strTmp_.size ()); + return *this; +} + +/// Output a double. +LoggerRam & +LoggerRam::operator<< (double d) +{ + strTmp_ = " "; + std::ostringstream oStr; + oStr << d; + strTmp_.append (oStr.str ()); + buffer_.write (reinterpret_cast (strTmp_.data ()), strTmp_.size ()); + return *this; +} diff --git a/i/chuck/src/log/logger_ram.hh b/i/chuck/src/log/logger_ram.hh new file mode 100644 index 0000000..03838c2 --- /dev/null +++ b/i/chuck/src/log/logger_ram.hh @@ -0,0 +1,63 @@ +#ifndef logger_ram_hh +#define logger_ram_hh +// logger_ram.hh +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Dufour Jérémy +// +// Robot APB Team/Efrei 2004. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} + +#include "logger.hh" +#include "data_circular_buffer_factory.hh" +#include "data/data_circular_buffer.hh" + +#include + +/// Logger into ram (with a data circular buffer). +class LoggerRam : public Logger +{ + /// Factory for creating DataCircularBuffer. + DataCircularBufferFactory bufferFactory_; + /// Reference to the current DataCircularBuffer used. + DataCircularBuffer &buffer_; + /// Temporary string. + std::string strTmp_; + public: + /// Default constructor. + LoggerRam (void); + /// Default destructor. + ~LoggerRam (void) { } + /// Called at the begining of a message. + void start (const Log &log, const char *msg, Log::Level level); + /// Called at the end of a message. + void stop (void) { uint8_t cr = '\n'; buffer_.write (&cr, 1); } + /// Output a string or a variable name. + LoggerRam &operator<< (const char *s); + /// Output a string or a variable name. + LoggerRam &operator<< (const std::string &s); + /// Output a integer. + LoggerRam &operator<< (int i); + /// Output a double. + LoggerRam &operator << (double d); + private: +}; + +#endif // logger_ram_hh diff --git a/i/chuck/src/log/logger_stdout.cc b/i/chuck/src/log/logger_stdout.cc new file mode 100644 index 0000000..5956d67 --- /dev/null +++ b/i/chuck/src/log/logger_stdout.cc @@ -0,0 +1,68 @@ +// logger_stdout.cc +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Dufour Jérémy +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: %WEB% +// Email: +// }}} +#include "logger_stdout.hh" + +/// Called at the begining of a message. +void +LoggerStdout::start (const Log &log, const char *msg, Log::Level level) +{ + std::cout << log.getModule () << ':'; + const char *instance = log.getInstance (); + if (instance) + std::cout << ' ' << instance << ':'; + std::cout << " (" << msg << ')'; + +} + +/// Output a string or a variable name. +LoggerStdout & +LoggerStdout::operator<< (const char *s) +{ + std::cout << ' ' << s; + return *this; +} + +/// Output a string or a variable name. +LoggerStdout & +LoggerStdout::operator<< (const std::string &s) +{ + std::cout << ' ' << s; + return *this; +} + +/// Output a integer. +LoggerStdout & +LoggerStdout::operator<< (int i) +{ + std::cout << ' ' << i; + return *this; +} + +/// Output a double. +LoggerStdout & +LoggerStdout::operator<< (double d) +{ + std::cout << ' ' << d; + return *this; +} diff --git a/i/chuck/src/log/logger_stdout.hh b/i/chuck/src/log/logger_stdout.hh new file mode 100644 index 0000000..eaa706a --- /dev/null +++ b/i/chuck/src/log/logger_stdout.hh @@ -0,0 +1,54 @@ +#ifndef logger_stdout_hh +#define logger_stdout_hh +// logger_stdout.hh +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Dufour Jérémy +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: %WEB% +// Email: +// }}} + +#include "logger.hh" + +#include +#include + +/// Logger to stdout. +class LoggerStdout : public Logger +{ + public: + /// Default empty constructor. + LoggerStdout (void) { } + /// Default empty destructor. + ~LoggerStdout (void) { } + /// Called at the begining of a message. + void start (const Log &log, const char *msg, Log::Level level); + /// Called at the end of a message. + void stop (void) { std::cout << std::endl; } + /// Output a string or a variable name. + LoggerStdout &operator<< (const char *s); + /// Output a string or a variable name. + LoggerStdout &operator<< (const std::string &s); + /// Output a integer. + LoggerStdout &operator<< (int i); + /// Output a double. + LoggerStdout &operator << (double d); +}; + +#endif // logger_stdout_hh diff --git a/i/chuck/src/log/test_log.cc b/i/chuck/src/log/test_log.cc new file mode 100644 index 0000000..64989b5 --- /dev/null +++ b/i/chuck/src/log/test_log.cc @@ -0,0 +1,53 @@ +// test_log.cc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2004 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "log.hh" +#include "data_circular_buffer_factory.hh" + +#include "config/config.hh" + +int +main (int argc, char **argv) +{ + try + { + Config config (argc, argv); + Log log ("main"); + Log log2 ("chier"); + log ("foo") << "[Default] bar" << 4 << "foobar" << 5.6; + log ("bar", Log::error) << "[Error] foo" << 5; + log ("bar", Log::info) << "[Info] Chier" << 3 << "Info" << 2.3; + log ("bar", Log::debug) << "[Debug] Partout" << 3 << "Debug" << 2.3; + log2 ("foo") << "[Default] bar" << 4 << "foobar" << 5.6; + log2 ("bar", Log::error) << "[Error] foo" << 5; + log2 ("bar", Log::info) << "[Info] Chier" << 3 << "Info" << 2.3; + log2 ("bar", Log::debug) << "[Debug] Partout" << 3 << "Debug" << 2.3; + } + catch (const std::exception &e) + { + std::cerr << e.what () << std::endl; + return 1; + } + return 0; +} diff --git a/i/chuck/src/log/test_log_server.cc b/i/chuck/src/log/test_log_server.cc new file mode 100644 index 0000000..70792f6 --- /dev/null +++ b/i/chuck/src/log/test_log_server.cc @@ -0,0 +1,45 @@ +// test_log_server.cc +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Nicolas Haller +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} + +#include "data/data_buffer.hh" +#include "log_server.hh" +#include "socket/address.hh" + +#include + +int main (void) +{ + // On fait un zolie DataBuffer + DataBuffer db_; + // On ecrit des betises dedans + char * betise = "J'aime bien la choucroute traditionnelle.\n"; + db_.write(reinterpret_cast(betise), strlen(betise)); + // On crée le serveur de la mort qui tue + LogServer ls(db_, std::string(), 2042); + // On écoute tranquillement + ls.listen(); + + return 0; +} diff --git a/i/chuck/src/motor/Makefile.defs b/i/chuck/src/motor/Makefile.defs new file mode 100644 index 0000000..ce79e10 --- /dev/null +++ b/i/chuck/src/motor/Makefile.defs @@ -0,0 +1,5 @@ +PROGRAMS += test_motor + +motor_OBJECTS = motor.o $(asserv_OBJECTS) $(log_OBJECTS) + +test_motor_OBJECTS = test_motor.o $(motor_OBJECTS) $(tester_OBJECTS) diff --git a/i/chuck/src/motor/motor.cc b/i/chuck/src/motor/motor.cc new file mode 100644 index 0000000..32d94eb --- /dev/null +++ b/i/chuck/src/motor/motor.cc @@ -0,0 +1,183 @@ +// motor.cc +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "motor.hh" + +#include + +/// Constructor. +Motor::Motor (void) + : asserv_ (*this), seq_ (0), finish_ (true), blocked_ (false), + x_ (0.0), y_ (0.0), a_ (0.0), log_ ("Motor") +{ +} + +/// Reset. +void +Motor::reset (void) +{ + finish_ = true; + blocked_ = false; + asserv_.reset (); +} + +/// Linear and angular move. T(mm) is the linear distance. A(mm) is the +/// angular distance which means the arc length. +void +Motor::move (double t, double a) +{ + nextSeq (); + finish_ = false; + blocked_ = false; + asserv_.speedTo (t, a, seq_); +} + +/// Rotate (rad). +void +Motor::rotate (double a) +{ + nextSeq (); + finish_ = false; + blocked_ = false; + asserv_.speedAngle (a, seq_); +} + +/// Find a hole. +void +Motor::findHole (void) +{ + nextSeq (); + finish_ = false; + blocked_ = false; + asserv_.findHole (seq_); +} + +void Motor::lockGoodHole (void) +{ + ///XXX VERIFIER LES COORDONNEES + const int xGood = 2000; + const int yGood = -1100; + ///XXX VERIFIER LES CALCULS D'AILLEURS... + double rotation = atan2((yGood - y_), (xGood - x_)); + rotate(rotation); +} + +void Motor::lockBadHole (void) +{ + ///XXX VERIFIER LES COORDONNEES + const int xGood = 600; + const int yGood = -1100; + ///XXX VERIFIER LES CALCULS D'AILLEURS... + double rotation = atan2((yGood - y_), (xGood - x_)); + rotate(rotation); +} + +/// Stop now. +void +Motor::stop (void) +{ + finish_ = true; + blocked_ = false; + asserv_.speed (0, 0); +} + +/// get the file descriptor +int +Motor::getFd(void) const +{ + return asserv_.getFd(); +} + +/// get the position of robal +void +Motor::getPosition(double & x, double & y, double & a) const +{ + x = x_; + y = y_; + a = a_; +} + +/// Next seq number. +void +Motor::nextSeq (void) +{ + seq_++; + if (seq_ > 100) + seq_ = 1; +} + +/// Implement Asserv::Receiver callbacks. +void +Motor::receiveAck (int seq) +{ + if ((seq & 0x7f) == seq_) + { + asserv_.ack (seq); + finish_ = true; + if (seq & 0x80) + { + blocked_ = true; + } + } +} + +void +Motor::receiveCounterStat (int l, int r) +{ +} + +void +Motor::receivePos (double x, double y, double a) +{ + x_ = x; + y_ = y; + a_ = a; + log_ ("Pos") << "x " << x << " y " << y << " a " << a / (2 * M_PI) * 360; +} + +void +Motor::receiveSpeedStat (int t, int a) +{ +} + +void +Motor::receivePosStat (int te, int ti, int ae, int ai) +{ +} + +void +Motor::receivePwmStat (int l, int r) +{ +} + +void +Motor::receiveTimerStat (const int *t, int tn) +{ +} + +void +Motor::receiveInPort (unsigned int port) +{ +} + diff --git a/i/chuck/src/motor/motor.hh b/i/chuck/src/motor/motor.hh new file mode 100644 index 0000000..548c7bd --- /dev/null +++ b/i/chuck/src/motor/motor.hh @@ -0,0 +1,86 @@ +#ifndef motor_hh +#define motor_hh +// motor.hh +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "asserv/asserv.hh" +#include "log/log.hh" + +/// Handle movements. +class Motor : public Asserv::Receiver +{ + private: + Asserv asserv_; + int seq_; + bool finish_; + bool blocked_; + double x_, y_, a_; + Log log_; + public: + /// Constructor. + Motor (void); + /// Try to empty emission queue, return true if empty. + bool sync (void) { return asserv_.sync (); } + /// Wait until emission queue is empty or timed out. + bool wait (int timeout = -1) { return asserv_.wait (timeout); } + /// Get asserv reference to change parameters. + Asserv &getAsserv (void) { return asserv_; } + /// True if last long move is finished. + bool finish (void) const { return finish_; } + /// True if blocked. + bool blocked (void) const { return blocked_; } + /// Linear and angular move. T(mm) is the linear distance. A(mm) is the + /// angular distance which means the arc length. + void move (double t, double a); + /// Rotate (rad). + void rotate (double a); + /// Find a hole. + void findHole (void); + /// Lock good hole (approximatively...) + void lockGoodHole(void); + /// Lock ennemy hole (non pas son cul) + void lockBadHole(void); + /// Stop now. + void stop (void); + /// get the file descriptor + int getFd(void) const; + /// Reset. + void reset (void); + /// get the position of robal + void getPosition(double & x, double & y, double & a) const; + private: + /// Next seq number. + inline void nextSeq (void); + /// Implement Asserv::Receiver callbacks. + void receiveAck (int seq); + void receiveCounterStat (int l, int r); + void receivePos (double x, double y, double a); + void receiveSpeedStat (int t, int a); + void receivePosStat (int te, int ti, int ae, int ai); + void receivePwmStat (int l, int r); + void receiveTimerStat (const int *t, int tn); + void receiveInPort (unsigned int port); +}; + +#endif // motor_hh diff --git a/i/chuck/src/motor/test_motor.cc b/i/chuck/src/motor/test_motor.cc new file mode 100644 index 0000000..760dfd6 --- /dev/null +++ b/i/chuck/src/motor/test_motor.cc @@ -0,0 +1,99 @@ +// test_motor.cc +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "motor.hh" +#include "tester/tester.hh" +#include "timer/timer.hh" + +#include +#include +#include + +class TestMotor : public Tester +{ + private: + Motor motor_; + public: + /// Constructor. + TestMotor (int argc, char **argv) + : Tester (argc, argv) + { } + /// Wait. + void wait (int ms) + { + int t, stop; + t = Timer::getProgramTime (); + stop = t + ms; + while (t < stop) + { + motor_.wait (stop - t); + t = Timer::getProgramTime (); + } + } + /// Called after each command called. + void postcall (void) + { + while (!motor_.wait () || !motor_.finish ()) + ; + } + /// Executed before checking/running commands. Good place to add command + /// to the interpreter. + void preRun (void) + { + Interpreter &i = getInterpreter (); + i.add ("wait", Interpreter::memFunc (*this, &TestMotor::wait), + "wait MS\nwait for a delay in millisecond"); + i.add ("move", Interpreter::memFunc (motor_, &Motor::move), + "move T(mm) A(mm)\n" + "linear and angular move"); + i.add ("rotate", Interpreter::memFunc (motor_, &Motor::rotate), + "rotate A(rad)\n" + "rotate round axis center"); + i.add ("findHole", Interpreter::memFunc (motor_, &Motor::findHole), + "findHole\nfind a hole"); + i.add ("stop", Interpreter::memFunc (motor_, &Motor::stop), + "stop\nguess what"); + i.add ("_postcall", + Interpreter::memFunc (*this, &TestMotor::postcall)); + } + /// Executed after running commands. + void postRun (void) + { + motor_.getAsserv ().reset (); + } +}; + +int +main (int argc, char **argv) +{ + try + { + TestMotor tm (argc, argv); + tm.run (); + } + catch (const std::exception &e) + { + std::cerr << e.what () << std::endl; + } +} diff --git a/i/chuck/src/parser/Makefile.defs b/i/chuck/src/parser/Makefile.defs new file mode 100644 index 0000000..61b4b97 --- /dev/null +++ b/i/chuck/src/parser/Makefile.defs @@ -0,0 +1,14 @@ +PROGRAMS += test_parser + +parser_OBJECTS = yylexer.o yyparser.o parser.o + +test_parser_OBJECTS = $(parser_OBJECTS) test_parser.o + +EXTRA_CLEAN += yyparser.hh yyparser.cc yylexer.hh yylexer.cc + +yyparser.hh: yyparser.cc +$(OBJ_DIR)/yylexer.o: yyparser.hh + +yylexer.hh: yylexer.cc +$(OBJ_DIR)/yyparser.o: yylexer.hh +$(OBJ_DIR)/parser.o: yylexer.hh diff --git a/i/chuck/src/parser/parser.cc b/i/chuck/src/parser/parser.cc new file mode 100644 index 0000000..4981474 --- /dev/null +++ b/i/chuck/src/parser/parser.cc @@ -0,0 +1,189 @@ +// parser.cc +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Nicolas Schodet +// +// Robot APB Team/Efrei 2006. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "parser.hh" + +#include "yyparser.hh" +#include "yylexer.hh" + +#include +#include + +int yyparse (void *); + +/// Constructeur. +Parser::Parser (void) +{ +} + +/// Destructeur +Parser::~Parser (void) +{ +} + +/// Lance le parseur sur un fichier. +void +Parser::parseFile (const std::string &file) +{ + FILE *f; + f = fopen (file.c_str (), "r"); + if (!f) + throw std::runtime_error ("can not open file \"" + file + "\""); + try + { + // Crée un scanner, initialise son tampon d'entré, puis parse. + yyscan_t scanner; + YY_BUFFER_STATE buf; + Extra e (*this, true); + yylex_init (&scanner); + yyset_extra (&e, scanner); + buf = yy_create_buffer (f, YY_READ_BUF_SIZE, scanner); + yy_switch_to_buffer (buf, scanner); + int ret = yyparse (scanner); + yy_delete_buffer (buf, scanner); + yylex_destroy (scanner); + if (ret) + { + if (!e.error_.empty ()) + throw std::runtime_error (e.error_); + else + throw std::runtime_error ("parse error"); + } + } + catch (const std::exception &e) + { + fclose (f); + throw std::runtime_error ("in file \"" + file + "\": " + e.what ()); + } + fclose (f); +} + +/// Lance le parseur sur une chaîne. +void +Parser::parseString (const std::string &s) +{ + try + { + // Crée un scanner, initialise son tampon d'entré, puis parse. + yyscan_t scanner; + YY_BUFFER_STATE buf; + Extra e (*this, false); + yylex_init (&scanner); + yyset_extra (&e, scanner); + buf = yy_scan_bytes (s.data (), s.size (), scanner); + int ret = yyparse (scanner); + yy_delete_buffer (buf, scanner); + yylex_destroy (scanner); + if (ret) + { + if (!e.error_.empty ()) + throw std::runtime_error (e.error_); + else + throw std::runtime_error ("parse error"); + } + } + catch (const std::exception &e) + { + throw std::runtime_error ("in string \"" + s + "\": " + e.what ()); + } +} + +/// Fonction appelée lors d'une affectation. VAL peut être modifié, il est +/// détruit suite à l'appel. +void +Parser::assign (const std::string &id, any &val) +{ + throw std::runtime_error ("unexpected assignement"); +} + +/// Fonction appelée lors d'un appel. ARGS peut être modifié, il est +/// détruit suite à l'appel. +void +Parser::call (const std::string &id, AnyList &args) +{ + throw std::runtime_error ("unexpected call"); +} + +/// Constructeur pour initialiser les références. +Parser::Extra::Extra (Parser &parser, bool useLine) + : line (1), parser_ (parser), useLine_ (useLine) +{ +} + +/// Recueille l'erreur de bison. +void +Parser::Extra::error (const std::string &e) +{ + if (error_.empty ()) + { + error_ = e; + if (useLine_) + { + std::stringstream os; + os << line; + error_ += ", line "; + error_ += os.str (); + } + } +} + +/// Fonction appelée lors d'une affectation par bison. +bool +Parser::Extra::assign (const std::string &id, any &val) +{ + try + { + parser_.assign (id, val); + } + catch (const std::exception &e) + { + error (e.what ()); + return false; + } + return true; +} + +/// Fonction appelée lors d'un appel par bison. +bool +Parser::Extra::call (const std::string &id, AnyList &args) +{ + try + { + parser_.call (id, args); + } + catch (const std::exception &e) + { + error (e.what ()); + return false; + } + return true; +} + +/* Shut up warning for this wrongly declared static function. */ +static int +yy_init_globals (yyscan_t yyscanner) +{ + return yy_init_globals (yyscanner); +} + diff --git a/i/chuck/src/parser/parser.hh b/i/chuck/src/parser/parser.hh new file mode 100644 index 0000000..573d5f6 --- /dev/null +++ b/i/chuck/src/parser/parser.hh @@ -0,0 +1,89 @@ +#ifndef parser_hh +#define parser_hh +// parser.hh +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Nicolas Schodet +// +// Robot APB Team/Efrei 2006. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "utils/any.hh" + +#include +#include + +/// Classe de parsing. Pour l'utiliser, dériver une classe et implémenter les +/// méthodes que l'on veut supporter. +class Parser +{ + public: + /// Les types supportés sont bool, char, int, double, std::string, + /// IntList, DoubleList, StringList. + typedef std::list IntList; + typedef std::list DoubleList; + typedef std::list StringList; + typedef std::list AnyList; + /// Cette structure est passée au parser en bison, puis au lexer en flex. + class Extra + { + public: + /// Chaîne temporaire utilisée pendant l'analyse lexicale. + std::string tmp; + /// Ligne courante. + int line; + private: + /// Référence vers l'instance de Parser. + Parser &parser_; + /// Permet de stocker l'erreur de bison. + std::string error_; + /// Utilise ou non le comptage de lignes. + bool useLine_; + public: + /// Constructeur pour initialiser les références. + Extra (Parser &parser, bool useLine); + /// Recueille l'erreur de bison. + void error (const std::string &e); + /// Fonction appelée lors d'une affectation par bison. + bool assign (const std::string &id, any &val); + /// Fonction appelée lors d'un appel par bison. + bool call (const std::string &id, AnyList &args); + /// Accés réservé pour Parser. + friend class Parser; + }; + public: + /// Constructeur. + Parser (void); + /// Destructeur virtuel + virtual ~Parser (void); + /// Lance le parseur sur un fichier. + void parseFile (const std::string &file); + /// Lance le parseur sur une chaîne. + void parseString (const std::string &s); + /// Fonction appelée lors d'une affectation. VAL peut être modifié, il est + /// détruit suite à l'appel. + virtual void assign (const std::string &id, any &val); + /// Fonction appelée lors d'un appel. ARGS peut être modifié, il est + /// détruit suite à l'appel. + virtual void call (const std::string &id, AnyList &args); +}; + +#define YY_EXTRA_TYPE Parser::Extra * + +#endif // parser_hh diff --git a/i/chuck/src/parser/test_parser.cc b/i/chuck/src/parser/test_parser.cc new file mode 100644 index 0000000..dedbd83 --- /dev/null +++ b/i/chuck/src/parser/test_parser.cc @@ -0,0 +1,86 @@ +// test_parser.cc +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Nicolas Schodet +// +// Robot APB Team/Efrei 2006. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "parser.hh" + +#include +#include + +class TestParser : public Parser +{ + public: + /// Fonction appelée lors d'une affectation. VAL peut être modifié, il est + /// détruit suite à l'appel. + virtual void assign (const std::string &id, any &val) + { + std::cout << id << " = " << val << std::endl; + } + /// Fonction appelée lors d'un appel. ARGS peut être modifié, il est + /// détruit suite à l'appel. + virtual void call (const std::string &id, AnyList &args) + { + std::cout << "call " << id << ' ' << args << std::endl; + } +}; + +int +main (int argc, char **argv) +{ + try + { + if (argc <= 1) + { + std::cerr << "test_parser - test le parser.\n" + "Utilisation: test_parser [-f FILE | STRING]\n" + << std::endl; + } + TestParser tp; + for (int i = 1; i < argc; i++) + { + try + { + if (i + 1 < argc && strcmp (argv[i], "-f") == 0) + { + tp.parseFile (argv[++i]); + } + else + { + tp.parseString (argv[i]); + } + } + catch (const std::exception &e) + { + // L'erreur est humaine... heu, normale, elle fait parti du + // test donc pas de cerr. + std::cout << "error: " << e.what () << std::endl; + } + } + } + catch (const std::exception &e) + { + std::cerr << e.what () << std::endl; + return 1; + } + return 0; +} diff --git a/i/chuck/src/parser/yylexer.ll b/i/chuck/src/parser/yylexer.ll new file mode 100644 index 0000000..be8d41c --- /dev/null +++ b/i/chuck/src/parser/yylexer.ll @@ -0,0 +1,148 @@ +%{ +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Nicolas Schodet +// +// Robot APB Team/Efrei 2006. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "parser/parser.hh" +#include "yyparser.hh" +%} + +%option reentrant +%option header-file="yylexer.hh" +%option outfile="yylexer.cc" +%option bison-bridge +%option noyywrap nodefault nounput + +%x strst + +INTDEC [+-]?[0-9]+ +INTHEX "0x"[0-9a-fA-F]+ +INTNUM {INTDEC}|{INTHEX} +DOUBLEEX [eE]{INTDEC} +DOUBLE1 [+-]?\.[0-9]+{DOUBLEEX}? +DOUBLE2 [+-]?[0-9]+\.[0-9]*{DOUBLEEX}? +DOUBLE3 {INTDEC}{DOUBLEEX} +DOUBLENUM {DOUBLE1}|{DOUBLE2}|{DOUBLE3} + +%% + +"true"|"on"|"yes" { + yylval->b = true; + return BOOLEAN; +} + +"false"|"off"|"no" { + yylval->b = false; + return BOOLEAN; +} + +"'"\\n"'" { + yylval->c = '\n'; + return CHAR; +} +"'"\\r"'" { + yylval->c = '\r'; + return CHAR; +} +"'"\\t"'" { + yylval->c = '\t'; + return CHAR; +} +"'"\\."'" { + yylval->c = yytext[1]; + return CHAR; +} +"'"\\\n"'" { + yyextra->line++; + yylval->c = yytext[1]; + return CHAR; +} +"'"."'" { + yylval->c = yytext[1]; + return CHAR; +} + +[a-zA-Z][_a-zA-Z0-9.-]* { + yylval->s = new std::string (yytext); + return ID; +} + +{DOUBLENUM} { + yylval->d = strtod (yytext, 0); + return DOUBLE; +} + +{INTNUM} { + yylval->i = strtol (yytext, 0, 0); + return INT; +} + +\" { + BEGIN(strst); + yyextra->tmp.clear (); +} + +\n { + yyextra->line++; + return SEP; +} + +; { + return SEP; +} + +[=()] return yytext[0]; + +[ \t]+ /* Skip. */ +#.* /* Skip comments. */ + +. { + yyextra->error (std::string ("unexpected character \'") \ + + yytext[0] + '\''); + return UNKNOWN; +} + +\" { + BEGIN (INITIAL); + yylval->s = new std::string (yyextra->tmp); + return STRING; +} + +\\n yyextra->tmp += '\n'; +\\r yyextra->tmp += '\r'; +\\t yyextra->tmp += '\t'; +\\. yyextra->tmp += yytext[1]; +\\\n { + yyextra->line++; + yyextra->tmp += yytext[1]; +} +. yyextra->tmp += yytext[0]; +\n { + yyextra->error ("unexpected end of line inside string"); + yyextra->line++; + return UNKNOWN; +} + +%% + +/* vim:ft=lex: +*/ diff --git a/i/chuck/src/parser/yyparser.yy b/i/chuck/src/parser/yyparser.yy new file mode 100644 index 0000000..86db4a5 --- /dev/null +++ b/i/chuck/src/parser/yyparser.yy @@ -0,0 +1,278 @@ +%{ +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Nicolas Schodet +// +// Robot APB Team/Efrei 2006. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "parser/parser.hh" + +// Fichiers d'en-tête générés. +#include "yyparser.hh" +#include "yylexer.hh" + +#undef yyextra +#define yyextra (yyget_extra (scanner)) + +void yyerror (void *scanner, const char *e); + +%} + +%error-verbose +%pure-parser +%lex-param {void *scanner} +%parse-param {void *scanner} +%defines +%union { + bool b; + char c; + int i; + double d; + std::string *s; + struct { + any *a; + Parser::IntList *il; + } il; + struct { + any *a; + Parser::DoubleList *dl; + } dl; + struct { + any *a; + Parser::StringList *sl; + } sl; + Parser::AnyList *al; +} + +%token SEP + +%token BOOLEAN +%token UNKNOWN +%token CHAR +%token INT +%token DOUBLE +%token ID STRING + +%type int_list int_list_i +%type
double_list double_list_i +%type string_list string_list_i +%type arg_list + +%destructor { delete $$; } ID STRING +%destructor { delete $$.a; } int_list int_list_i +%destructor { delete $$.a; } double_list double_list_i +%destructor { delete $$.a; } string_list string_list_i +%destructor { delete $$; } arg_list + +%% + +input: + /* Nothing. */ + | item + | input SEP item + | input SEP +; + +item: + ID '=' BOOLEAN { + any a ($3); + if (!yyextra->assign (*$1, a)) + YYERROR; + delete $1; + } + | ID '=' CHAR { + any a ($3); + if (!yyextra->assign (*$1, a)) + YYERROR; + delete $1; + } + | ID '=' INT { + any a ($3); + if (!yyextra->assign (*$1, a)) + YYERROR; + delete $1; + } + | ID '=' DOUBLE { + any a ($3); + if (!yyextra->assign (*$1, a)) + YYERROR; + delete $1; + } + | ID '=' STRING { + any a (*$3); + if (!yyextra->assign (*$1, a)) + YYERROR; + delete $1; + delete $3; + } + | ID '=' int_list { + if (!yyextra->assign (*$1, *$3.a)) + YYERROR; + delete $1; + delete $3.a; + } + | ID '=' double_list { + if (!yyextra->assign (*$1, *$3.a)) + YYERROR; + delete $1; + delete $3.a; + } + | ID '=' string_list { + if (!yyextra->assign (*$1, *$3.a)) + YYERROR; + delete $1; + delete $3.a; + } + | ID arg_list { + if (!yyextra->call (*$1, *$2)) + YYERROR; + delete $1; + delete $2; + } +; + +int_list: + '(' int_list_i ')' { + $$ = $2; + } +; + +int_list_i: + INT { + $$.a = new any (Parser::IntList ()); + $$.il = any_cast ($$.a); + $$.il->push_back ($1); + } + | int_list_i INT { + $1.il->push_back ($2); + $$ = $1; + } +; + +double_list: + '(' double_list_i ')' { + $$ = $2; + } +; + +double_list_i: + DOUBLE { + $$.a = new any (Parser::DoubleList ()); + $$.dl = any_cast ($$.a); + $$.dl->push_back ($1); + } + | double_list_i DOUBLE { + $1.dl->push_back ($2); + $$ = $1; + } +; + +string_list: + '(' string_list_i ')' { + $$ = $2; + } +; + +string_list_i: + STRING { + $$.a = new any (Parser::StringList ()); + $$.sl = any_cast ($$.a); + $$.sl->push_back (*$1); + delete $1; + } + | string_list_i STRING { + $1.sl->push_back (*$2); + $$ = $1; + delete $2; + } +; + +arg_list: + /* empty */ { + $$ = new Parser::AnyList; + } + | arg_list BOOLEAN { + any a ($2); + $1->push_back (any ()); + $1->back ().swap (a); + $$ = $1; + } + | arg_list CHAR { + any a ($2); + $1->push_back (any ()); + $1->back ().swap (a); + $$ = $1; + } + | arg_list INT { + any a ($2); + $1->push_back (any ()); + $1->back ().swap (a); + $$ = $1; + } + | arg_list DOUBLE { + any a ($2); + $1->push_back (any ()); + $1->back ().swap (a); + $$ = $1; + } + | arg_list STRING { + any a (*$2); + $1->push_back (any ()); + $1->back ().swap (a); + delete $2; + $$ = $1; + } + | arg_list int_list { + $1->push_back (any ()); + $1->back ().swap (*$2.a); + delete $2.a; + $$ = $1; + } + | arg_list double_list { + $1->push_back (any ()); + $1->back ().swap (*$2.a); + delete $2.a; + $$ = $1; + } + | arg_list string_list { + $1->push_back (any ()); + $1->back ().swap (*$2.a); + delete $2.a; + $$ = $1; + } +; +%% + +/// Traite une erreur de Bison. +void +yyerror (void *scanner, const char *e) +{ + yyextra->error (e); +} + +/* Shut up warning for this wrongly declared static function. */ +static int +yy_init_globals (yyscan_t yyscanner) +{ + return yy_init_globals (yyscanner); +} + +/* vim:ft=yacc: +*/ diff --git a/i/chuck/src/proto/Makefile.defs b/i/chuck/src/proto/Makefile.defs new file mode 100644 index 0000000..b351026 --- /dev/null +++ b/i/chuck/src/proto/Makefile.defs @@ -0,0 +1,5 @@ +PROGRAMS += test_proto + +proto_OBJECTS = proto.o $(serial_OBJECTS) $(log_OBJECTS) $(utils_OBJECTS) $(timer_OBJECTS) + +test_proto_OBJECTS = test_proto.o $(proto_OBJECTS) $(tester_OBJECTS) diff --git a/i/chuck/src/proto/proto.cc b/i/chuck/src/proto/proto.cc new file mode 100644 index 0000000..50e363d --- /dev/null +++ b/i/chuck/src/proto/proto.cc @@ -0,0 +1,457 @@ +// proto.cc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Haller +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} + +#include "timer/timer.hh" +#include "utils/hexa.hh" +#include "proto.hh" + +#include +#include +#include + +/// Constructeur. +Proto::Proto(Receiver &receiver) + : log_ ("proto"), receiver_(receiver), tLastSend_(0), revState_(0) +{ +} + +/// Ouvre le port série. +void +Proto::open(const std::string &ttyname) +{ + serial_.open(ttyname); +} + +/// Ferme le port série +void +Proto::close(void) +{ + serial_.close(); +} + +/// Teste si tout les packets ont été envoyés et aquités, sinon, essaye de +/// le faire. +bool +Proto::sync(void) +{ + // Récupération de la frame + while (getFrame()) + { + log_ ("recv", Log::debug) << "frame" << currentFrame_; + // Si la frame est un aquittement + if(currentFrame_ == frameQueue_.front()) + { + // on vire la commande de la queue + frameQueue_.pop(); + // Et on envoie la suivante si elle existe + if(!frameQueue_.empty()) + sendFrame(frameQueue_.front()); + } + // Si c'est une nouvelle commande, on l'envoie avec receive + else + receiver_.receive(currentFrame_.command, currentFrame_); + } + // On regarde depuis combien de temps on a envoyé une commande + if(!frameQueue_.empty()) + { + // Si on dépasse la milliseconde, on renvoie + if(Timer::getProgramTime() - tLastSend_ >= timeout_) + sendFrame(frameQueue_.front()); + } + return frameQueue_.empty(); +} + +/// Envoie un packet +void +Proto::send (const Frame & frame, bool reliable) +{ + if(reliable) + { + if(frameQueue_.empty()) + tLastSend_ = -timeout_; + frameQueue_.push(frame); + } + else + sendFrame(frame); +} + + +/// Envois un packet. COMMAND est la commande à envoyer, FORMAT, donne le +/// format et le nombre de paramètres ('b' : 8 bits, 'w' : 16 bits, 'd' : +/// 32 bits, majuscule pour signé). +void +Proto::send (char command, const char *format, int a0, int a1, + int a2, int a3, int a4, int a5, bool reliable) +{ + // Constitution de la frame + Proto::Frame frame; + frame.command = command; + + if (format[0] != '\0') + { + newArgFrame(frame, format[0],a0); + if (format[1] != '\0') + { + newArgFrame(frame, format[1],a1); + if (format[2] != '\0') + { + newArgFrame(frame, format[2],a2); + if (format[3] != '\0') + { + newArgFrame(frame, format[3],a3); + if(format[4] != '\0') + { + newArgFrame(frame, format[4],a4); + if(format[5] != '\0') + newArgFrame(frame, format[5],a5); + } + + } + } + } + } + send(frame,reliable); +} + +/// Send a string of size number. +void +Proto::sendStr (char command, const char *str, int size, bool reliable) +{ + Proto::Frame frame; + + frame.command = command; + + for (int compt = 0; compt < size; compt++) + newArgFrame (frame, 'b', str[compt]); + + send (frame,reliable); +} + +/// permet d'envoyer un packet pas fiable +void +Proto::sendUnreliable (char command, const char *format, int a0, int a1, + int a2, int a3, int a4, int a5) +{ + send(command, format, a0, a1, a2, a3, a4, a5, false); +} + +/// Teste si le packet correspond au format et décode les valeurs. Utilise +/// le même format que send. +bool +Proto::decode (const Proto::Frame &frame) +{ + int dummy; + return decode(frame, "", dummy, dummy, dummy, dummy, dummy); +} + +bool +Proto::decode (const Frame &frame, const char *format, int &a0) +{ + int dummy; + return decode(frame, format, a0, dummy, dummy, dummy, dummy); +} + +bool +Proto::decode (const Frame &frame, const char *format, int &a0, int &a1) +{ + int dummy; + return decode(frame, format, a0, a1, dummy, dummy, dummy); +} + +bool +Proto::decode (const Frame &frame, const char *format, int &a0, + int &a1, int &a2) +{ + int dummy; + return decode(frame, format, a0, a1, a2, dummy, dummy); +} + +bool +Proto::decode (const Frame &frame, const char *format, int &a0, + int &a1, int &a2, int &a3) +{ + int dummy; + return decode(frame, format, a0, a1, a2, a3, dummy); +} + +bool +Proto::decode (const Frame &frame, const char *format, int &a0, + int &a1, int &a2, int &a3, int &a4) +{ + // Teste si il y a bien le bon nombre d'argument + if (static_cast(frame.args.size()) != argsFrameSize(format)) + return false; + // On décode et on envoie + decodeArg(frame, format, a0, a1, a2, a3, a4); + + return true; +} + +/// Attend que des caractères soit disponible pendant un temps maximum en +/// milliseconde et les traite. Renvois le résultat de sync (). Attention, +/// fonction bloquante, n'utiliser que pour les tests. +bool +Proto::wait (int timeout/*-1*/) +{ + // On apelle serial_.wait avec un timeout toujours inf ou égal à proto::timeout_ + serial_.wait (timeout < timeout_ && timeout != -1 ? timeout : timeout_); + return sync (); +} + +/// Récupère le File Descriptor +int Proto::getFd(void) const +{ + return serial_.getFd(); +} + +/// Récupère les infos de l'AVR pour construire une frame +bool +Proto::getFrame(void) +{ + int receivedChar, d; + bool erreur = false; + // tant que le tampon n'est pas vide, on teste + while((receivedChar = serial_.getchar()) != -1) + { + // Si on reçoit un bang + if(receivedChar == '!') + { + revState_ = 1; + currentFrame_.command = 0; + currentFrame_.args.clear(); + } + // Si on reçoit le retour chariot et que on reçevait les args + else if(receivedChar == '\r' && revState_ == 2) + { + revState_ = 0; + return true; + } + // Pour les autres charactères + // Si on attend la commande + else + switch(revState_) + { + case 1: + if (!isalpha (receivedChar) || receivedChar == '?') + erreur = true; + else + { + currentFrame_.command = receivedChar; + revState_ = 2; + } + break; + case 2: + d = hex2digit (receivedChar); + if (d == hexInvalid) + erreur = true; + else + { + currentFrame_.args.push_back (static_cast(d) << 4); + revState_ = 3; + } + break; + case 3: + d = hex2digit (receivedChar); + if (d == hexInvalid) + erreur = true; + else + { + currentFrame_.args.back() |= static_cast(d); + revState_ = 2; + break; + } + } + // Si revState == 0 alors on jette + // Si on a reçu une erreur on renvoie + if(erreur) + { + // On renvoie en mettant le compteur à 0, la commande sera + // renvoyer de retour à sync + log_("Erreur de reception", Log::debug) + << "commande inconnue" << ""; + tLastSend_ = 0; + revState_ = 0; + return false; + } + } + return false; +} + +/// Envoie la frame dans l'AVR +void +Proto::sendFrame(const Frame & frame) +{ + log_ ("send", Log::debug) << "frame" << frame; + // envoyer le bang + serial_.putchar('!'); + + // Envoyer la commande + serial_.putchar(frame.command); + + // Envoyer les arguments + for(std::vector::const_iterator it = frame.args.begin(); + it != frame.args.end(); ++it) + { + serial_.putchar(digit2hex(*it >> 4)); + serial_.putchar(digit2hex(*it & 0x0f)); + } + + // Envoyer le retour chariot + serial_.putchar('\r'); + + // actualiser le timer + tLastSend_ = Timer::getProgramTime(); +} + +/// Remplie une frame avec un argument +void +Proto::newArgFrame(Proto::Frame & frame, char format, int arg) +{ + switch(format) + { + case 'b': + case 'B': + frame.args.push_back(static_cast(arg)); + break; + case 'w': + case 'W': + frame.args.push_back(static_cast(arg >> 8)); + frame.args.push_back(static_cast(arg)); + break; + case 'd': + case 'D': + frame.args.push_back(static_cast(arg >> 24)); + frame.args.push_back(static_cast(arg >> 16)); + frame.args.push_back(static_cast(arg >> 8)); + frame.args.push_back(static_cast(arg)); + break; + } +} + +/// Renvoie la taille necessaire du vecteur args pour un format donné +int +Proto::argsFrameSize(const char *format) +{ + int size = 0; + for(; *format != '\0'; format++) + switch(*format) + { + case 'b': + case 'B': + size += 1; + break; + case 'w': + case 'W': + size += 2; + break; + case 'd': + case 'D': + size += 4; + break; + default: + size += 0; + } + return size; +} + +/// Décode un argument +void +Proto::decodeArg(const Frame & frame, const char *format, int &a0, int &a1, int &a2, int &a3, int &a4) +{ + int temp[5]; + int pos = 0; + + for(int i = 0; *format != '\0'; format++,i++) + { + switch(*format) + { + case 'b': + temp[i] = static_cast(frame.args[pos]); + pos++; + break; + case 'B': + { + int8_t t = static_cast(frame.args[pos]); + temp[i] = static_cast(t); + pos++; + break; + } + case 'w': + temp[i] = static_cast(frame.args[pos]) << 8 + |static_cast(frame.args[pos + 1]); + pos += 2; + break; + case 'W': + { + int8_t t = static_cast(frame.args[pos]); + temp[i] = static_cast(t) << 8 + |static_cast(frame.args[pos + 1]); + pos += 2; + break; + } + case 'd': + temp[i] = static_cast(frame.args[pos]) << 24 + |static_cast(frame.args[pos + 1]) << 16 + |static_cast(frame.args[pos + 2]) << 8 + |static_cast(frame.args[pos + 3]); + pos += 4; + break; + + case 'D': + { + int8_t t = static_cast(frame.args[pos]); + temp[i] = static_cast(t) << 24 + |static_cast(frame.args[pos + 1]) << 16 + |static_cast(frame.args[pos + 2]) << 8 + |static_cast(frame.args[pos + 3]); + pos += 4; + break; + } + } + } + a0 = temp[0]; + a1 = temp[1]; + a2 = temp[2]; + a3 = temp[3]; + a4 = temp[4]; +} + +bool +Proto::Frame::operator==(const Frame& frame) +{ + return this->command == frame.command && this->args == frame.args; +} + +/// Affiche une frame. +std::ostream & +operator<< (std::ostream &os, const Proto::Frame &f) +{ + os << '<' << f.command << ' '; + std::copy (f.args.begin (), f.args.end (), + std::ostream_iterator (os, " ")); + os << '>'; + return os; +} + diff --git a/i/chuck/src/proto/proto.hh b/i/chuck/src/proto/proto.hh new file mode 100644 index 0000000..a45db91 --- /dev/null +++ b/i/chuck/src/proto/proto.hh @@ -0,0 +1,140 @@ +#ifndef proto_hh +#define proto_hh +// proto.hh +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} + +#include "utils/non_copyable.hh" +#include "serial/serial.hh" +#include "log/log.hh" + +#include +#include + +/// Classe de dialogue avec une carte électronique par le port série. +class Proto : public NonCopyable +{ + public: + class Receiver; + /// Packet. + struct Frame + { + char command; + std::vector args; + bool operator==(const Frame& frame); + }; + private: + Log log_; + Serial serial_; + Receiver &receiver_; + + /// File d'attente des messages à aquiter. + typedef std::queue FrameQueue; + FrameQueue frameQueue_; + //Date du dernier envoie + int tLastSend_; + //Temps entre les ré-émission + static const int timeout_ = 100; + + /// Frame en cours de réception + Frame currentFrame_; + int revState_; + // Etat de la réception de la frame + // 0 - Rien reçu + // 1 - Bang reçu + // 2 - Commande reçu & nouveau argument + // 3 - char 1 argument reçu + + public: + /// Constructeur. + Proto (Receiver &receiver); + /// Ouvre le port série. + void open (const std::string &ttyname); + /// Ferme le port série. + void close (void); + /// Teste si tout les packets ont été envoyés et aquités, sinon, essaye de + /// le faire. + bool sync (void); + /// Envois un packet. + void send (const Frame &frame, bool reliable = true); + /// Envois un packet. COMMAND est la commande à envoyer, FORMAT, donne le + /// format et le nombre de paramètres ('b' : 8 bits, 'w' : 16 bits, 'd' : + /// 32 bits, majuscule pour signé). + void send (char command, const char *format = "", int a0 = 0, int a1 = 0, + int a2 = 0, int a3 = 0, int a4 = 0, int a5 = 0, bool reliable = true); + /// Send a string of size number. + void sendStr (char command, const char *str, int size, bool reliable = + true); + /// permet d'envoyer un packet robert + void sendUnreliable (char command, const char *format, int a0, + int a1, int a2, int a3, int a4, int a5); + //@{ + /// Teste si le packet correspond au format et décode les valeurs. Utilise + /// le même format que send. + static bool decode (const Frame &frame); + static bool decode (const Frame &frame, const char *format, int &a0); + static bool decode (const Frame &frame, const char *format, int &a0, int + &a1); + static bool decode (const Frame &frame, const char *format, int &a0, int + &a1, int &a2); + static bool decode (const Frame &frame, const char *format, int &a0, int + &a1, int &a2, int &a3); + static bool decode (const Frame &frame, const char *format, int &a0, int + &a1, int &a2, int &a3, int &a4); + //@} + /// Attend que des caractères soit disponible pendant un temps maximum en + /// milliseconde et les traite. Renvois le résultat de sync (). Attention, + /// fonction bloquante, n'utiliser que pour les tests. + bool wait (int timeout = -1); + /// Récupère le File Descriptor + int getFd(void) const; + + public: + /// Les clients de Proto doivent dériver de Receiver. + class Receiver + { + public: + virtual ~Receiver(void) {}; + /// Recoit un packet. + virtual void receive (char command, const Frame &frame) = 0; + }; + private: + /// Récupère les infos de l'AVR pour construire une frame + bool getFrame(void); + /// Envoie la frame dans l'AVR + void sendFrame(const Frame & frame); + /// Remplie une frame avec un argument + void newArgFrame(Proto::Frame & frame, char format, int arg); + /// Renvoie la taille necessaire du vecteur args pour un format donné + static int argsFrameSize(const char *format); + /// Décode un argument + static void decodeArg(const Frame & frame, const char *format, int &a0, + int &a1, int &a2, int &a3, int &a4); +}; + +/// Affiche une frame. +std::ostream & +operator<< (std::ostream &os, const Proto::Frame &f); + +#endif // proto_hh diff --git a/i/chuck/src/proto/test_proto.cc b/i/chuck/src/proto/test_proto.cc new file mode 100644 index 0000000..01cac96 --- /dev/null +++ b/i/chuck/src/proto/test_proto.cc @@ -0,0 +1,96 @@ +// test_proto.cc +// robert - programme du robot 2006. {{{ +// +// Copyright (C) 2005 Nicolas Haller +// +// Robot APB Team/Efrei 2006. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "proto.hh" +#include "timer/timer.hh" +#include "tester/tester.hh" +#include "parser/parser.hh" + +#include +#include + +class TestProto : public Tester, Proto::Receiver +{ + private: + Proto proto_; + public: + // Constructor + TestProto (int argc, char ** argv) + : Tester (argc, argv), proto_(*this){} + void preRun (void) + { + Interpreter &interpreter = getInterpreter (); + // Récupère le tty de config + proto_.open(config_.get("testProto.tty")); + // Add functions. + interpreter.add ("s", Interpreter::memFunc ( *this, &TestProto::send ), + "Fonction send (string commande, string format, " + "int arg...)"); + interpreter.add ("w", Interpreter::memFunc ( proto_, &Proto::wait ), + "Fonction wait ()"); + } + void postRun(void) + { + proto_.close(); + } + void receive (char command, const Proto::Frame &frame) + { + std::cout << "received " << frame << std::endl; + } + void send (const Parser::AnyList & al, bool dryrun) + { + Parser::AnyList::const_iterator it = al.begin(); + // arguments envoyé à la fonctions Proto::send + int arg[6]; + // command avr + char command = any_cast (*it); + // format des arguments + std::string format = any_cast (*++it); + // Récupération des arguments + for (unsigned i = 0; i < 6; ++i) + { + if(i < al.size() - 2) + arg[i] = any_cast (*++it); + else + arg[i] = 0; + } + if (!dryrun) + proto_.send(command, format.c_str(), arg[0], arg[1], arg[2], + arg[3], arg[4], arg[5]); + } +}; + +int +main (int argc, char **argv) +{ + try + { + TestProto tp (argc, argv); + tp.run (); + } + catch (const std::exception &e) + { + std::cerr << e.what () << std::endl; + } +} diff --git a/i/chuck/src/scheduler/Makefile.defs b/i/chuck/src/scheduler/Makefile.defs new file mode 100644 index 0000000..fc6c157 --- /dev/null +++ b/i/chuck/src/scheduler/Makefile.defs @@ -0,0 +1,7 @@ +PROGRAMS += test_scheduler + +scheduler_OBJECTS = scheduler.o schedulable_read_fd.o schedulable_alarm.o + +test_scheduler_OBJECTS = \ + test_scheduler.o scheduler.o schedulable_read_fd.o schedulable_alarm.o \ + $(timer_OBJECTS) diff --git a/i/chuck/src/scheduler/schedulable.hh b/i/chuck/src/scheduler/schedulable.hh new file mode 100644 index 0000000..d8869af --- /dev/null +++ b/i/chuck/src/scheduler/schedulable.hh @@ -0,0 +1,50 @@ +#ifndef schedulable_hh +#define schedulable_hh +// schedulable.hh +// {{{ +// +// Copyright (C) 2004 Nicolas Schodet +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: http://perso.efrei.fr/~schodet/ +// Email: +// }}} + +class FdSet; + +namespace scheduler { + +class Scheduler; + +/// Classe abstraite pour un objet utilisable par le Scheduler. +class Schedulable +{ + public: + /// Destructeur. + virtual ~Schedulable (void) {} + /// Paramètre le Scheduler. + virtual void setup (Scheduler &scheduler, int time, FdSet &readSet, + int &timeout) = 0; + /// Appelé aprés l'attente du Scheduler, renvois true si un événement a + /// été traité. + virtual bool run (Scheduler &scheduler, int time, + const FdSet &readSet) = 0; +}; + +} // namespace scheduler + +#endif // schedulable_hh diff --git a/i/chuck/src/scheduler/schedulable_alarm.cc b/i/chuck/src/scheduler/schedulable_alarm.cc new file mode 100644 index 0000000..b890350 --- /dev/null +++ b/i/chuck/src/scheduler/schedulable_alarm.cc @@ -0,0 +1,56 @@ +// schedulable_alarm.cc +// {{{ +// +// Copyright (C) 2004 Nicolas Schodet +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: http://perso.efrei.fr/~schodet/ +// Email: +// }}} +#include "schedulable_alarm.hh" + +namespace scheduler { + +/// Paramètre le Scheduler. +void +SchedulableAlarm::setup (Scheduler &scheduler, int time, FdSet &readSet, int + &timeout) +{ + if (start_ != -1) + { + int to = start_ + step_ - time; + timeout = to > 0 ? to : 0; + } +} + +/// Appelé aprés l'attente du Scheduler, renvois true si un événement a +/// été traité. +bool +SchedulableAlarm::run (Scheduler &scheduler, int time, const FdSet &readSet) +{ + if (time >= start_ + step_) + { + start_ = periodic_ ? start_ + step_ : -1; + callback_ (); + return true; + } + else + return false; +} + +} // namespace scheduler + diff --git a/i/chuck/src/scheduler/schedulable_alarm.hh b/i/chuck/src/scheduler/schedulable_alarm.hh new file mode 100644 index 0000000..1e008b6 --- /dev/null +++ b/i/chuck/src/scheduler/schedulable_alarm.hh @@ -0,0 +1,60 @@ +#ifndef schedulable_alarm_hh +#define schedulable_alarm_hh +// schedulable_alarm.hh +// {{{ +// +// Copyright (C) 2004 Nicolas Schodet +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: http://perso.efrei.fr/~schodet/ +// Email: +// }}} +#include "schedulable.hh" +#include "utils/callback.hh" +#include "timer/timer.hh" + +namespace scheduler { + +/// Execute un callback à un instant donné. +class SchedulableAlarm : public Schedulable +{ + Callback callback_; + int start_, step_; + bool periodic_; + public: + /// Construit une alarm dans step milliseconde, périodique si periodic est + /// vrai (vrai par defaut), à partir de start si donné, ou de maintenant + /// sinon. + template + SchedulableAlarm (T callback, int step, bool periodic = true, + int start = -1) + : callback_ (callback), + start_ (start), step_ (step), periodic_ (periodic) + { + if (start_ == -1) + start_ = Timer::getProgramTime (); + } + /// Paramètre le Scheduler. + void setup (Scheduler &scheduler, int time, FdSet &readSet, int &timeout); + /// Appelé aprés l'attente du Scheduler, renvois true si un événement a + /// été traité. + bool run (Scheduler &scheduler, int time, const FdSet &readSet); +}; + +} // namespace scheduler + +#endif // schedulable_alarm_hh diff --git a/i/chuck/src/scheduler/schedulable_read_fd.cc b/i/chuck/src/scheduler/schedulable_read_fd.cc new file mode 100644 index 0000000..3c84c9b --- /dev/null +++ b/i/chuck/src/scheduler/schedulable_read_fd.cc @@ -0,0 +1,51 @@ +// schedulable_read_fd.cc +// {{{ +// +// Copyright (C) 2004 Nicolas Schodet +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: http://perso.efrei.fr/~schodet/ +// Email: +// }}} +#include "schedulable_read_fd.hh" +#include "utils/fd_set.hh" + +namespace scheduler { + +/// Paramètre le Scheduler. +void +SchedulableReadFd::setup (Scheduler &scheduler, int time, FdSet &readSet, int &timeout) +{ + readSet.set (fd_); +} + +/// Appelé aprés l'attente du Scheduler, renvois true si un événement a +/// été traité. +bool +SchedulableReadFd::run (Scheduler &scheduler, int time, const FdSet &readSet) +{ + if (readSet.isSet (fd_)) + { + callback_ (); + return true; + } + else + return false; +} + +} // namespace scheduler + diff --git a/i/chuck/src/scheduler/schedulable_read_fd.hh b/i/chuck/src/scheduler/schedulable_read_fd.hh new file mode 100644 index 0000000..01d7b26 --- /dev/null +++ b/i/chuck/src/scheduler/schedulable_read_fd.hh @@ -0,0 +1,52 @@ +#ifndef schedulable_read_fd_hh +#define schedulable_read_fd_hh +// schedulable_read_fd.hh +// {{{ +// +// Copyright (C) 2004 Nicolas Schodet +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: http://perso.efrei.fr/~schodet/ +// Email: +// }}} +#include "schedulable.hh" +#include "utils/callback.hh" + +namespace scheduler { + +/// Execute un callback sur une lecture possible sur un descripteur de +/// fichier. +class SchedulableReadFd : public Schedulable +{ + Callback callback_; + int fd_; + public: + /// Constructeur. + template + SchedulableReadFd (T callback, int fd) + : callback_ (callback), fd_ (fd) + { } + /// Paramètre le Scheduler. + void setup (Scheduler &scheduler, int time, FdSet &readSet, int &timeout); + /// Appelé aprés l'attente du Scheduler, renvois true si un événement a + /// été traité. + bool run (Scheduler &scheduler, int time, const FdSet &readSet); +}; + +} // namespace scheduler + +#endif // schedulable_read_fd_hh diff --git a/i/chuck/src/scheduler/scheduler.cc b/i/chuck/src/scheduler/scheduler.cc new file mode 100644 index 0000000..4ef3ade --- /dev/null +++ b/i/chuck/src/scheduler/scheduler.cc @@ -0,0 +1,103 @@ +// scheduler.cc +// {{{ +// +// Copyright (C) 2004 Nicolas Schodet +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: http://perso.efrei.fr/~schodet/ +// Email: +// }}} +#include "scheduler.hh" +#include "utils/fd_set.hh" +#include "timer/timer.hh" + +#include +#include + +namespace scheduler { + +/// Destructeur. +Scheduler::~Scheduler (void) +{ + // TODO: Test for schedulables_ empty ? +} + +/// Ajoute un élément schedulable. +void +Scheduler::insert (Schedulable &schedulable) +{ + schedulables_.insert (&schedulable); +} + +/// Enlève un élément schedulable. +void +Scheduler::erase (Schedulable &schedulable) +{ + schedulables_.erase (&schedulable); +} + +/// Lance le scheduler. Si timeout est différent de -1, c'est le temps +/// maximal que prend le scheduler avant de rendre la main. Si +/// returnOnEvent est true, le premier évenement arrète le scheduler. +/// Renvois true si au moins un événement a été traité. +bool +Scheduler::schedule (int timeout/*-1*/, bool returnOnEvent/*false*/) +{ + bool event = false; + int t = Timer::getProgramTime (); + int start = t; + do + { + // Prépare le select. + int to = timeout == -1 ? -1 : start + timeout - t; + FdSet readFds; + for (Schedulables::const_iterator i = schedulables_.begin (); + i != schedulables_.end (); + ++i) + { + int top = -1; + (*i)->setup (*this, t, readFds, top); + // Si le timeout est plus court, retient ce timeout. + if (to == -1 || top != -1 && top < to) + to = top; + } + // Select. + if (to != -1) + { + timeval tv; + tv.tv_sec = to / 1000; + tv.tv_usec = to % 1000 * 1000; + select (FD_SETSIZE, readFds.get (), 0, 0, &tv); + } + else + { + select (FD_SETSIZE, readFds.get (), 0, 0, 0); + } + // Run. + t = Timer::getProgramTime (); + for (Schedulables::const_iterator i = schedulables_.begin (); + i != schedulables_.end (); + ++i) + event = (*i)->run (*this, t, readFds) || event; + t = Timer::getProgramTime (); + } while (!(returnOnEvent && event) + && (timeout == -1 || start + timeout > t)); + return event; +} + +} // namespace scheduler + diff --git a/i/chuck/src/scheduler/scheduler.hh b/i/chuck/src/scheduler/scheduler.hh new file mode 100644 index 0000000..3bd885b --- /dev/null +++ b/i/chuck/src/scheduler/scheduler.hh @@ -0,0 +1,53 @@ +#ifndef scheduler_hh +#define scheduler_hh +// scheduler.hh +// {{{ +// +// Copyright (C) 2004 Nicolas Schodet +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: http://perso.efrei.fr/~schodet/ +// Email: +// }}} +#include "schedulable.hh" + +#include + +namespace scheduler { + +/// Scheduler, répartie le travail en fonction des événements. +class Scheduler +{ + typedef std::set Schedulables; + Schedulables schedulables_; + public: + /// Destructeur. + ~Scheduler (void); + /// Ajoute un élément schedulable. + void insert (Schedulable &schedulable); + /// Enlève un élément schedulable. + void erase (Schedulable &schedulable); + /// Lance le scheduler. Si timeout est différent de -1, c'est le temps + /// maximal que prend le scheduler avant de rendre la main. Si + /// returnOnEvent est true, le premier évenement arrète le scheduler. + /// Renvois true si au moins un événement a été traité. + bool schedule (int timeout = -1, bool returnOnEvent = false); +}; + +} // namespace scheduler + +#endif // scheduler_hh diff --git a/i/chuck/src/scheduler/test_scheduler.cc b/i/chuck/src/scheduler/test_scheduler.cc new file mode 100644 index 0000000..6cb88c0 --- /dev/null +++ b/i/chuck/src/scheduler/test_scheduler.cc @@ -0,0 +1,68 @@ +// test_scheduler.cc +// {{{ +// +// Copyright (C) 2004 Nicolas Schodet +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: http://perso.efrei.fr/~schodet/ +// Email: +// }}} +#include "scheduler.hh" +#include "schedulable_read_fd.hh" +#include "schedulable_alarm.hh" +#include "utils/bind.hh" +#include "timer/timer.hh" + +#include +#include + +void +ev (void) +{ + std::cout << "event received" << std::endl; + char buf[1024]; + read (0, buf, 1024); +} + +void +to (const char *msg) +{ + std::cout << "timeout received \"" << msg << "\" at " + << Timer::getProgramTime () << std::endl; +} + +int +main (void) +{ + using namespace scheduler; + try + { + Scheduler s; + SchedulableReadFd srf (ev, 0); + s.insert (srf); + std::cout << "start at " << Timer::getProgramTime () << std::endl; + SchedulableAlarm sa1 (bind (to, "1s"), 1000); + s.insert (sa1); + s.schedule (10000); + } + catch (const std::exception &e) + { + std::cerr << e.what () << std::endl; + return 1; + } + return 0; +} diff --git a/i/chuck/src/serial/Makefile.defs b/i/chuck/src/serial/Makefile.defs new file mode 100644 index 0000000..fcf71f9 --- /dev/null +++ b/i/chuck/src/serial/Makefile.defs @@ -0,0 +1,5 @@ +PROGRAMS += test_serial + +serial_OBJECTS = serial.o serial_base.o serial_dev.o serial_stdio.o + +test_serial_OBJECTS = test_serial.o $(serial_OBJECTS) $(utils_OBJECTS) diff --git a/i/chuck/src/serial/serial.cc b/i/chuck/src/serial/serial.cc new file mode 100644 index 0000000..db2a6d2 --- /dev/null +++ b/i/chuck/src/serial/serial.cc @@ -0,0 +1,66 @@ +// serial.cc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "serial.hh" +#include "serial_dev.hh" +#include "serial_stdio.hh" + +/// Constructeur. +Serial::Serial (bool blocking) + : blocking_ (blocking), sb_ (0) +{ +} + +/// Destructeur. +Serial::~Serial (void) +{ + close (); +} + +/// Ouvre et paramètre le port série. \a ttyname peut être un device +/// ("/dev/tty00,115200", voir SerialDev), un programme précédé d'un tube +/// ("|simul_asserv", voir SerialPipe) ou l'entrée/sortie standard ("-"). +void +Serial::open (const std::string &ttyname) +{ + close (); + if (ttyname == "-") + sb_ = new SerialStdio (blocking_); + else if (ttyname[0] == '|') + { + // TODO + } + else + sb_ = new SerialDev (blocking_); + sb_->open (ttyname); +} + +/// Ferme le port série, appellé automatiquement dans le destructeur. +void +Serial::close (void) +{ + delete sb_; + sb_ = 0; +} + diff --git a/i/chuck/src/serial/serial.hh b/i/chuck/src/serial/serial.hh new file mode 100644 index 0000000..d66971e --- /dev/null +++ b/i/chuck/src/serial/serial.hh @@ -0,0 +1,64 @@ +#ifndef serial_hh +#define serial_hh +// serial.hh +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "serial_base.hh" + +/// Classe générique qui utilise la sous-classe apropriée de SerialBase en +/// fonction du paramètre de Serial::open(). +class Serial +{ + bool blocking_; + SerialBase *sb_; + public: + /// Constructeur. + Serial (bool blocking = false); + /// Destructeur. + ~Serial (void); + /// Ouvre et paramètre le port série. \a ttyname peut être un device + /// ("/dev/tty00,115200", voir SerialDev), un programme précédé d'un tube + /// ("|simul_asserv", voir SerialPipe) ou l'entrée/sortie standard ("-"). + void open (const std::string &ttyname); + /// Ferme le port série, appellé automatiquement dans le destructeur. + void close (void); + /// Lit un bloc, retourne le nombre d'octets lus ou <= 0 en cas d'erreur + /// ou si aucun caractère n'est disponible. Pour le robot, préferer en + /// général getchar() pour du non-bloquant. + ssize_t read (void *buf, size_t size) { return sb_->read (buf, size); } + /// Lit un caractère, ou -1 en cas d'erreur ou si aucun caractère n'est + /// disponible. + int getchar (void) { return sb_->getchar (); } + /// Ecrit un bloc. + void write (const void *buf, size_t size) { sb_->write (buf, size); } + /// Ecrit un caractère. + void putchar (int c) { sb_->putchar (c); } + /// Attend que des caractères soient disponibles pendant un delay en + /// millisecondes. + bool wait (int timeout = -1) { return sb_->wait (timeout); } + /// Récupère le descripteur. + int getFd (void) const { return sb_->getFd (); } +}; + +#endif // serial_hh diff --git a/i/chuck/src/serial/serial_base.cc b/i/chuck/src/serial/serial_base.cc new file mode 100644 index 0000000..b92a6b0 --- /dev/null +++ b/i/chuck/src/serial/serial_base.cc @@ -0,0 +1,84 @@ +// serial_base.cc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "serial_base.hh" +#include "utils/fd_set.hh" + +/// Constructeur. +SerialBase::SerialBase (void) + : fdIn_ (-1), fdOut_ (-1) +{ +} + +/// Destructeur. +SerialBase::~SerialBase (void) +{ +} + +/// Lit un bloc, retourne le nombre d'octets lus ou <= 0 en cas d'erreur +/// ou si aucun caractère n'est disponible. Pour le robot, préferer en +/// général getchar() pour du non-bloquant. +ssize_t +SerialBase::read (void *buf, size_t size) +{ + return ::read (fdIn_, buf, size); +} + +/// Lit un caractère, ou -1 en cas d'erreur ou si aucun caractère n'est +/// disponible. +int +SerialBase::getchar (void) +{ + char c; + if (read (&c, 1) == 1) + return c & 0xff; + else + return -1; +} + +/// Ecrit un bloc. +void +SerialBase::write (const void *buf, size_t size) +{ + ::write (fdOut_, buf, size); +} + +/// Ecrit un caractère. +void +SerialBase::putchar (int c) +{ + char cc = c; + write (&cc, 1); +} + +/// Attend que des caractères soient disponibles pendant un delay en +/// millisecondes. +bool +SerialBase::wait (int timeout/*-1*/) +{ + FdSet fds; + fds.set (fdIn_); + return fds.wait (timeout); +} + diff --git a/i/chuck/src/serial/serial_base.hh b/i/chuck/src/serial/serial_base.hh new file mode 100644 index 0000000..9caf27d --- /dev/null +++ b/i/chuck/src/serial/serial_base.hh @@ -0,0 +1,68 @@ +#ifndef serial_base_hh +#define serial_base_hh +// serial_base.hh +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} + +#include +#include + +/// Classe de base pour un port série. +class SerialBase +{ + protected: + /// Descripteur de fichier utilisé par les fonctions de lecture. + int fdIn_; + /// Descripteur de fichier utilisé par les fonctions d'écriture. + int fdOut_; + public: + /// Constructeur. + SerialBase (void); + /// Destructeur. + virtual ~SerialBase (void); + /// Ouvre et paramètre le port série. \a ttyname peut être un device + /// ("/dev/tty00,115200", voir SerialDev), un programme précédé d'un tube + /// ("|simul_asserv", voir SerialPipe) ou l'entrée/sortie standard ("-"). + virtual void open (const std::string &ttyname) = 0; + /// Ferme le port série, appellé automatiquement dans le destructeur. + virtual void close (void) = 0; + /// Lit un bloc, retourne le nombre d'octets lus ou <= 0 en cas d'erreur + /// ou si aucun caractère n'est disponible. Pour le robot, préferer en + /// général getchar() pour du non-bloquant. + ssize_t read (void *buf, size_t size); + /// Lit un caractère, ou -1 en cas d'erreur ou si aucun caractère n'est + /// disponible. + int getchar (void); + /// Ecrit un bloc. + void write (const void *buf, size_t size); + /// Ecrit un caractère. + void putchar (int c); + /// Attend que des caractères soient disponibles pendant un delay en + /// millisecondes. + bool wait (int timeout = -1); + /// Récupère le descripteur. + int getFd (void) { return fdIn_; } +}; + +#endif // serial_base_hh diff --git a/i/chuck/src/serial/serial_dev.cc b/i/chuck/src/serial/serial_dev.cc new file mode 100644 index 0000000..a1824a2 --- /dev/null +++ b/i/chuck/src/serial/serial_dev.cc @@ -0,0 +1,168 @@ +// serial_dev.cc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "serial_dev.hh" +#include "utils/errno_exception.hh" + +#include +#include +#include + +/// Constructeur. +SerialDev::SerialDev (bool blocking/*false*/) + : blocking_ (blocking) +{ +} + +/// Destructeur. +SerialDev::~SerialDev (void) +{ + close (); +} + +/// Ouvre et paramètre le port série, accepte plusieurs paramètres séparés par +/// des virgules : tty, vitesse, parité (none, odd, even). Par exemple : +/// "/dev/ttyS00,115200,even" (par defaut). +void +SerialDev::open (const std::string &ttyname) +{ + struct termios tios; + std::string tty; + int speed = 115200; + char par = 'e'; + // Décode le ttyname. + decode (ttyname, tty, speed, par); + // Ouvre le port série. + fdIn_ = ::open (tty.c_str (), O_RDWR | O_NOCTTY | O_NONBLOCK); + if (fdIn_ < 0) + throw errno_exception (ttyname, errno); + // Rendre le port série asynchrone. + //fcntl (fd_, F_SETFL, FASYNC); + // Sauver la configuration courante du port série. + tcgetattr (fdIn_, &old_); + tcgetattr (fdIn_, &tios); + // Paramètrer les options du port série. + // Vérification de la parité en entrée, remplace toute erreur de + // transmission par un caractère nul. Pas de Xon Xoff. Entrée crue. + tios.c_iflag &= ~(IGNPAR | PARMRK | ISTRIP | BRKINT | IGNCR | ICRNL | + INLCR | IXON | IXOFF | IXANY | IMAXBEL); + tios.c_iflag |= INPCK | IGNBRK; + // Sortie crue. + tios.c_oflag &= ~(OPOST); + // Pas de status line, 1 bit de stop, 8 bits de données, règle la parité. + tios.c_cflag &= ~(HUPCL | CSTOPB | PARENB | PARODD | CSIZE | CRTSCTS); + tios.c_cflag |= CS8 | CLOCAL | CREAD; + if (par != 'n') tios.c_cflag |= PARENB; + if (par == 'o') tios.c_cflag |= PARODD; + // Cru. + tios.c_lflag &= ~(ICANON | ECHO | ISIG | NOFLSH | TOSTOP); + // On n'attend jamais si on est en non-block. On attend sinon. + tios.c_cc[VTIME] = 0; + if (blocking_) + tios.c_cc[VMIN] = 1; + else + tios.c_cc[VMIN] = 0; + switch (speed) + { + case 1200: + cfsetspeed (&tios, B1200); + break; + case 9600: + cfsetspeed (&tios, B9600); + break; + case 19200: + cfsetspeed (&tios, B19200); + break; + case 38400: + cfsetspeed (&tios, B38400); + break; + case 57600: + cfsetspeed (&tios, B57600); + break; + case 115200: + cfsetspeed (&tios, B115200); + break; + case 230400: + cfsetspeed (&tios, B230400); + break; + case 460800: + cfsetspeed (&tios, B460800); + break; + default: + throw std::runtime_error ("Vitesse de port série non supportée\n"); + } + // Vider et configurer le port série. + tcflush (fdIn_, TCIFLUSH); + tcsetattr (fdIn_, TCSANOW, &tios); + fdOut_ = fdIn_; +} + +/// Ferme le port série, appellé automatiquement dans le destructeur de la +/// classe SerialBase. +void +SerialDev::close (void) +{ + if (fdIn_ != -1) + { + tcsetattr (fdIn_, TCSANOW, &old_); + ::close (fdIn_); + fdIn_ = -1; + fdOut_ = -1; + } +} + +/// Décode le ttyname, voir open. +void +SerialDev::decode (const std::string &ttyname, std::string &tty, int &speed, + char &par) const +{ + std::string::size_type a, b, d; + int i; + a = 0; + b = ttyname.find (','); + while (a != std::string::npos) + { + d = b == std::string::npos ? std::string::npos : b - a; + std::string s (ttyname, a, d); + i = atoi (s.c_str ()); + if (i) + speed = i; + else + { + if (s == "e" || s == "even") + par = 'e'; + else if (s == "o" || s == "odd") + par = 'o'; + else if (s == "n" || s == "none") + par = 'n'; + else if (tty.empty ()) + tty = s; + else + throw std::runtime_error ("error in ttyname: " + s); + } + a = b == std::string::npos ? b : b + 1; + b = ttyname.find (',', a); + } +} + diff --git a/i/chuck/src/serial/serial_dev.hh b/i/chuck/src/serial/serial_dev.hh new file mode 100644 index 0000000..31e98b6 --- /dev/null +++ b/i/chuck/src/serial/serial_dev.hh @@ -0,0 +1,54 @@ +#ifndef serial_dev_hh +#define serial_dev_hh +// serial_dev.hh +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "serial_base.hh" + +#include + +/// Classe de contrôle du port serie /dev/tty*. +class SerialDev : public SerialBase +{ + bool blocking_; + struct termios old_; + public: + /// Constructeur. + SerialDev (bool blocking = false); + /// Destructeur. + ~SerialDev (void); + /// Ouvre et paramètre le port série, accepte plusieurs paramètres séparés + /// par des virgules : tty, vitesse, parité (none, odd, even). Par + /// exemple : "/dev/ttyS00,115200,even" (par defaut). + void open (const std::string &ttyname); + /// Ferme le port série, appellé automatiquement dans le destructeur de la + /// classe SerialBase. + void close (void); + private: + /// Décode le ttyname, voir open. + void decode (const std::string &ttyname, std::string &tty, int &speed, + char &par) const; +}; + +#endif // serial_dev_hh diff --git a/i/chuck/src/serial/serial_stdio.cc b/i/chuck/src/serial/serial_stdio.cc new file mode 100644 index 0000000..ff652a2 --- /dev/null +++ b/i/chuck/src/serial/serial_stdio.cc @@ -0,0 +1,81 @@ +// serial_stdio.cc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "serial_stdio.hh" +#include "utils/errno_exception.hh" + +#include + +/// Constructeur. +SerialStdio::SerialStdio (bool blocking/*false*/) + : blocking_ (blocking) +{ +} + +/// Destructeur. +SerialStdio::~SerialStdio (void) +{ + close (); +} + +/// Ouvre et paramètre le port série. +void +SerialStdio::open (const std::string &ttyname) +{ + struct termios tios; + fdIn_ = 0; + fdOut_ = 1; + // Sauver la configuration courante du port série. + tcgetattr (fdIn_, &old_); + // Paramètrer les options du port série. + // Attention, affecter des valeurs directement est une mauvaise pratique, + // regarder SerialDev pour un bon exemple. + tios.c_cflag = CS8 | CLOCAL | CREAD; + tios.c_iflag = IGNBRK | IGNPAR; + tios.c_oflag = 0; + tios.c_lflag = 0; + // On n'attend jamais si on est en non-block. On attend sinon. + tios.c_cc[VTIME] = 0; + if (blocking_) + tios.c_cc[VMIN] = 1; + else + tios.c_cc[VMIN] = 0; + // Vider et configurer le port série. + tcflush (fdIn_, TCIFLUSH); + tcsetattr (fdIn_, TCSANOW, &tios); +} + +/// Ferme le port série, appellé automatiquement dans le destructeur de la +/// classe SerialBase. +void +SerialStdio::close (void) +{ + if (fdIn_ != -1) + { + tcsetattr (fdIn_, TCSANOW, &old_); + fdIn_ = -1; + fdOut_ = -1; + } +} + diff --git a/i/chuck/src/serial/serial_stdio.hh b/i/chuck/src/serial/serial_stdio.hh new file mode 100644 index 0000000..ea10eff --- /dev/null +++ b/i/chuck/src/serial/serial_stdio.hh @@ -0,0 +1,48 @@ +#ifndef serial_stdio_hh +#define serial_stdio_hh +// serial_stdio.hh +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "serial_base.hh" + +#include + +/// Classe de contrôle du port serie factice sur l'entrée/sortie standart. +class SerialStdio : public SerialBase +{ + bool blocking_; + struct termios old_; + public: + /// Constructeur. + SerialStdio (bool blocking = false); + /// Destructeur. + ~SerialStdio (void); + /// Ouvre et paramètre le port série. + void open (const std::string &ttyname); + /// Ferme le port série, appellé automatiquement dans le destructeur de la + /// classe SerialBase. + void close (void); +}; + +#endif // serial_stdio_hh diff --git a/i/chuck/src/serial/test_serial.cc b/i/chuck/src/serial/test_serial.cc new file mode 100644 index 0000000..6c0b771 --- /dev/null +++ b/i/chuck/src/serial/test_serial.cc @@ -0,0 +1,88 @@ +// test_serial.cc - Programme de test pour le port série. +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "serial.hh" +//#include "date/date.hh" + +#include + +void +syntax (void) +{ + std::cout << "test_serial ttyname commandes... - Test la classe Serial.\n" + " a carte d'asservissement.\n" + " e échèle de 0 à 255 puis 0...\n" + " envois une valeur." << std::endl; +} +int +main (int argc, char **argv) +{ + try + { + if (argc < 3) + { + syntax (); + return 1; + } + Serial s; + s.open (argv[1]); + switch (argv[2][0]) + { + case 'a': + s.write ("!g1\r", 3); + //Date::getInstance ().wait (1000); + s.write ("!v0303\r", 7); + //Date::getInstance ().wait (5000); + s.write ("!s\r", 3); + break; + case 'e': + while (1) + { + for (int i = 0; i < 256; ++i) + { + std::cout << i << std::endl; + s.putchar (i); + //Date::getInstance ().wait (100); + } + for (int i = 255; i >= 0; --i) + { + std::cout << i << std::endl; + s.putchar (i); + //Date::getInstance ().wait (100); + } + } + break; + default: + int i = atoi (argv[2]); + std::cout << i << std::endl; + s.putchar (i); + break; + } + } + catch (const std::exception &e) + { + std::cerr << e.what () << std::endl; + return 1; + } +} diff --git a/i/chuck/src/socket/Makefile.defs b/i/chuck/src/socket/Makefile.defs new file mode 100644 index 0000000..1ff9efc --- /dev/null +++ b/i/chuck/src/socket/Makefile.defs @@ -0,0 +1,12 @@ +PROGRAMS += test_socket test_socket_databuffer #test_server + +socket_basic_OBJECTS = address.o socket_server.o socket_client.o +socket_databuffer_OBJECTS = socket_databuffer.o $(socket_basic_OBJECTS) \ + $(data_OBJECTS) + +test_socket_OBJECTS = test_socket.o $(socket_basic_OBJECTS) $(data_OBJECTS) +test_socket_databuffer_OBJECTS = test_socket_databuffer.o \ + $(socket_databuffer_OBJECTS) $(data_OBJECTS) \ + $(socket_basic_OBJECTS) +#test_server_OBJECTS = test_server.o $(net_OBJECTS) $(data_OBJECTS) \ + $(image_OBJECTS) diff --git a/i/chuck/src/socket/address.cc b/i/chuck/src/socket/address.cc new file mode 100644 index 0000000..4567e2e --- /dev/null +++ b/i/chuck/src/socket/address.cc @@ -0,0 +1,93 @@ +// address.cc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Dufour Jérémy +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: %WEB% +// Email: +// }}} +#include "address.hh" + +#include +#include + +/// Constructeur par défaut. +Address::Address (void) + : port_ (0) +{ + resolv (); +} + +/// Constructeur avec le port (serveur) +Address::Address (const int port) + : port_ (port) +{ + resolv (); +} +/// Constructeur avec hôte et port. +Address::Address (const std::string &host, const int port) + : host_ (host), port_ (port) +{ + resolv (); +} + +/// Constructeur à partir de la strcuture d'adresse. +Address::Address (const sockaddr *sa, socklen_t sl) +{ + // On vérifie que c'est vraiment un struct sockaddr_in + if (sl != sizeof (sockaddr_in)) + throw std::invalid_argument ("Invalide Adresse"); + sa_ = * reinterpret_cast (sa); +} + +/// Résolution de la structure d'adresse depuis l'hôte/port +void +Address::resolv (void) +{ + // Cas du serveur, pas d'hôte + if (host_.empty ()) + sa_.sin_addr.s_addr = htonl (INADDR_ANY); + else + { + // Convertion de l'hôte en structure adresse + if (!inet_pton (AF_INET, host_.c_str (), &sa_.sin_addr)) + { + hostent *host_info = gethostbyname (host_.c_str ()); + if (!host_info) + throw std::runtime_error (host_ + " : Hôte inconnue"); + } + } + sa_.sin_family = AF_INET; + // Convertion pour le passage sur le réseau + sa_.sin_port = htons (port_); +} + +/// Résolution de l'hôte/port depuis la structure d'adresse +void +Address::unresolv (void) +{ + hostent *host_info; + // Recherche de l'hôte + host_info = gethostbyaddr (reinterpret_cast (&(sa_.sin_addr)), sizeof sa_.sin_addr, AF_INET); + if (!host_info) + host_ = inet_ntoa (sa_.sin_addr); + else + host_ = host_info->h_name; + // Recherche du port + port_ = ntohs (sa_.sin_port); +} diff --git a/i/chuck/src/socket/address.hh b/i/chuck/src/socket/address.hh new file mode 100644 index 0000000..53fca07 --- /dev/null +++ b/i/chuck/src/socket/address.hh @@ -0,0 +1,76 @@ +#ifndef address_hh +#define address_hh +// address.hh +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Dufour Jérémy +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: %WEB% +// Email: +// }}} + +#include +#include +#include +#include + +#include +#include + +/// S'occupe de gérer les adresses. +class Address { + /// La structure sockaddr_in de type réseau/AF_INET. + sockaddr_in sa_; + /// Le nom d'hôte de l'adresse. + std::string host_; + /// Le numéro de port de l'adresse. + int port_; + + public: + /// Constructeur par défaut. + Address (void); + /// Constructeur pour le serveur. (port seulement) + Address (const int port); + /// Constructeur avec hôte et port. + Address (const std::string &host, const int port); + /// Constructeur à partir de la structure d'adresse. + Address (const sockaddr *sa, socklen_t sl); + /// Geter sockaddr. + const sockaddr *getSockaddr (void) const { return + reinterpret_cast (&sa_); } + /// Geter hôte. + const std::string &getHost (void) const { return host_; } + /// Geter port. + const int getPort (void) const { return port_; } + + private: + /// Résolution adresse vers hôte/port + void resolv (void); + /// Résolution hôte/port vers adresse + void unresolv (void); + +}; + +/// Surcharge de l'opérateur << pour l'affichage. +inline std::ostream & +operator<< (std::ostream &s, const Address &a) +{ + return s << a.getHost () << ':' << a.getPort (); +} + +#endif // address_hh diff --git a/i/chuck/src/socket/server_socket.cc b/i/chuck/src/socket/server_socket.cc new file mode 100644 index 0000000..539b94e --- /dev/null +++ b/i/chuck/src/socket/server_socket.cc @@ -0,0 +1,86 @@ +// server_socket.cc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Dufour Jérémy +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: %WEB% +// Email: +// }}} +#include "server_socket.hh" + +#include "address.hh" + +#include +#include +#include + +/// Constructeur par défaut. +ServerSocket::ServerSocket (int port) +{ + bind (port); +} + +/// Bind le serveur sur un port d'écoute. +void +ServerSocket::bind (int port) +{ + static const int reuse_s = 1; + // Adresse sur un port (pas d'hote, écoutera de partout) + Address a (port); + // Création du socket IPv4 - TCP + socket_ = socket (PF_INET, SOCK_STREAM, 0); + if (socket_ == -1) + throw std::runtime_error ("Erreur de création du socket"); + // Socket réutilisable en cas d'arret "brutale" + if (setsockopt (socket_, SOL_SOCKET, SO_REUSEADDR, + &reuse_s, sizeof (int)) == -1) + throw std::runtime_error ("Erreur setsockopt : reusable"); + // Bindage du socket sur le port et l'adresse + if (::bind (socket_, a.getSockaddr (), sizeof (struct sockaddr_in)) == -1) + throw std::runtime_error ("Erreur de bind du socket"); + // On met le socket en attente de connexion + if (listen (socket_, 0) == -1) + throw std::runtime_error ("Erreur de listen"); +} + +// Accepte une nouvelle connexion. +int +ServerSocket::accept (void) const +{ + int s = ::accept (socket_, 0, 0); + if (s == -1) + throw std::runtime_error ("Erreur d'accept de nouvelles connexions"); + return s; +} + +// Accepte une nouvelle connexion et remplie Address. +int +ServerSocket::accept (Address &a) const +{ + sockaddr_in sa; + socklen_t sl = sizeof sa; + int s = ::accept (socket_, reinterpret_cast (&sa), + &sl); + if (s == -1) + { + throw std::runtime_error ("Erreur d'accept nouvelle connexion"); + } + // Récupération de l'adresse + a = Address (reinterpret_cast (&sa), sl); + return s; +} diff --git a/i/chuck/src/socket/server_socket.hh b/i/chuck/src/socket/server_socket.hh new file mode 100644 index 0000000..159aa65 --- /dev/null +++ b/i/chuck/src/socket/server_socket.hh @@ -0,0 +1,48 @@ +#ifndef server_socket_hh +#define server_socket_hh +// server_socket.hh +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Dufour Jérémy +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: %WEB% +// Email: +// }}} + +#include +class Address; + +/// Créer un server TCP pour le transfert des données. +class ServerSocket { + private: + /// L'identificateur du socket. + int socket_; + public: + /// Constructeur par défaut. + ServerSocket (int port); + /// Destructeur. + ~ServerSocket () { close (socket_); } + /// Accepte une nouvelle connexion et remplie Address. + int accept (Address &a) const; + /// Accepte une nouvelle connexion. + int accept (void) const; + private: + /// Bind le serveur sur un port d'écoute. + void bind (int port); +}; +#endif // server_socket_hh diff --git a/i/chuck/src/socket/socket_client.cc b/i/chuck/src/socket/socket_client.cc new file mode 100644 index 0000000..951ea6a --- /dev/null +++ b/i/chuck/src/socket/socket_client.cc @@ -0,0 +1,115 @@ +/* socket_client.cc - Définition de la classe des sockets client */ +/* Simulotron - Programme de simulation de robot {{{ + * + * Copyright (C) 2005 Nicolas Haller + * + * Robot APB Team/Efrei 2005. + * Web: http://assos.efrei.fr/robot/ + * Email: robot AT efrei DOT fr + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * }}} */ +#include "socket/socket_client.hh" +#include "socket/socket_server.hh" +#include "socket/address.hh" +#include "utils/errno_exception.hh" + +#include +#include + +SocketClient::SocketClient (void) +{ + // Crée le file descriptor du socket + socket_ = socket (PF_INET, SOCK_STREAM, 0); + if (socket_ < 0) + throw errno_exception ("Socket: La chaussette n'a pas pu être tricoté", errno); +} + +SocketClient::SocketClient (SocketServer & socketServer) +{ + socket_ = socketServer.accept (); + if (socket_ < 0) + throw errno_exception ("Socket: Problème lors de la construction d'une chaussette cliente par accept", errno); +} + +SocketClient::~SocketClient (void) +{ + if (socket_ >= 0) + ::close (socket_); +} + +void +SocketClient::connect (const Address & address) +{ + if (::connect (socket_, address.getSockaddr (), sizeof (sockaddr_in)) < 0) + throw errno_exception ("Socket: Impossible de mettre la chaussette", errno); +} + +void +SocketClient::connect (const std::string & address, int port) +{ + connect (Address(address, port)); +} + +bool +SocketClient::read (std::string & strReaded, bool bloquant) +{ + int charReaded; + char buffer[BUFFER_SIZE]; + // Vérifie si il y a quelque chose à lire et retourne si non + if (!bloquant) + { + fd_set fds; + timeval tv = {0, 0}; + FD_ZERO(&fds); + FD_SET(socket_, &fds); + if(select(socket_ + 1, &fds, NULL, NULL, &tv) == 0) + return false; + } + strReaded.clear(); + do + { + charReaded = ::read (socket_, buffer, BUFFER_SIZE - 1); + if (charReaded < 0) + throw errno_exception ("SocketClient: problème de lecture", errno); + //buffer[charReaded] = 0; + //str += buffer; + strReaded.append(buffer, charReaded); + }while (charReaded == BUFFER_SIZE - 1); + return true; +} + +void +SocketClient::write (const std::string & str) +{ + write(reinterpret_cast(str.data()), str.size()); +} + +void +SocketClient::write (const uint8_t * buffer, unsigned size) +{ + int retval; + + retval = ::write (socket_, buffer, size); + if (retval < 0) + throw errno_exception ("SocketClient: erreur d'écriture (write()) ", errno); +} + +//int +//SocketClient::getFD(void) +//{ +// return socket_; +//} diff --git a/i/chuck/src/socket/socket_client.hh b/i/chuck/src/socket/socket_client.hh new file mode 100644 index 0000000..ad8d1ea --- /dev/null +++ b/i/chuck/src/socket/socket_client.hh @@ -0,0 +1,63 @@ +#ifndef socket_client_hh +#define socket_client_hh +/* socket_client.hh - Classe des socket client */ +/* Simulotron - Programme de simulation de robot {{{ + * + * Copyright (C) 2005 Nicolas Haller + * + * Robot APB Team/Efrei 2005. + * Web: http://assos.efrei.fr/robot/ + * Email: robot AT efrei DOT fr + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * }}} */ + +#include "utils/non_copyable.hh" + +#include +#include + +class Address; +class SocketServer; + +class SocketClient :public NonCopyable +{ + private: + /// Ze socket + int socket_; + /// constantes + /// Taille max du buffer de lecture/ecriture + static const int BUFFER_SIZE = 256; + public: + /// Constructeur + SocketClient (void); + /// Constructeur accept + SocketClient (SocketServer & socketServer); + /// Destructeur + ~SocketClient (void); + /// Connect le client au serveur + void connect (const Address & address); + /// Connect le client au serveur en se chargeant de créer Address + void connect (const std::string & address, int port); + /// lit du socket + bool read (std::string & strReaded, bool bloquant); + /// écrit dans le socket + void write (const std::string & str); + /// écrit dans le socket + void write (const uint8_t * buffer, unsigned size); +}; + +#endif //socket_client_hh diff --git a/i/chuck/src/socket/socket_databuffer.cc b/i/chuck/src/socket/socket_databuffer.cc new file mode 100644 index 0000000..1b4258c --- /dev/null +++ b/i/chuck/src/socket/socket_databuffer.cc @@ -0,0 +1,97 @@ +// socket_databuffer.cc +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Nicolas Haller +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: http://perso.efrei.fr/~haller/ +// Email: +// }}} +#include "socket_databuffer.hh" + +#include +#include + +// Constructeur +SocketDataBuffer::SocketDataBuffer(void) + :SocketClient(), dbSize_(0) // TODO Ça sert à quelque chose où il le fait implicitement? +{ +} + +// Constructeur accept +SocketDataBuffer::SocketDataBuffer(SocketServer & socketServer) + :SocketClient(socketServer), dbSize_(0) +{ +} + +// Récupère un DataBuffer +// false en valeur de retour avec bloquant = true est un motif de licenciement +bool +SocketDataBuffer::read(DataBuffer & dbReaded, bool bloquant) +{ + std::string strReceive; + do + { + SocketClient::read(strReceive, bloquant); + strBuffer_.append(strReceive); + // On regarde si on a assez de donnée pour regarder si on a une en-tête + if(strBuffer_.size() > sizeof(unsigned)) + { + dbSize_ = 0; + dbSize_ = static_cast(strBuffer_[0]) << 24 + | static_cast(strBuffer_[1]) << 16 + | static_cast(strBuffer_[2]) << 8 + | static_cast(strBuffer_[3]); + // On regarde si on a suffisemment de données pour constituer le DB + if(dbSize_ <= strBuffer_.size() - 4) + { + dbBuffer_.write(reinterpret_cast(strBuffer_.c_str() + 4) + , dbSize_); + dbReaded.swap(dbBuffer_); + dbBuffer_.clear(); + strBuffer_.erase(0, dbSize_ + 4); + return true; + } + } + }while(bloquant); + return false; +} + +// Ecrit un DB dans le socket +void +SocketDataBuffer::write(DataBuffer & db) +{ + // On met une en-tête de 4 octects déterminant la taille de la DB + unsigned dbSize = db.size(); + char entete[4]; + entete[0] = static_cast (dbSize >> 24); + entete[1] = static_cast (dbSize >> 16); + entete[2] = static_cast (dbSize >> 8); + entete[3] = static_cast (dbSize); + + SocketClient::write(std::string(entete,4)); + // On récupère les données de la dataBuffer + uint8_t * donnees = new uint8_t[dbSize]; + db.read(donnees, dbSize); + if (db.size() != 0) + throw std::runtime_error("ERREUR DE CODAGE dans SocketDataBuffer" + "::Write"); + // On envoie le tout et on nettoie l'allocation + SocketClient::write(std::string(reinterpret_cast(donnees), + dbSize)); + delete [] donnees; +} diff --git a/i/chuck/src/socket/socket_databuffer.hh b/i/chuck/src/socket/socket_databuffer.hh new file mode 100644 index 0000000..c385db5 --- /dev/null +++ b/i/chuck/src/socket/socket_databuffer.hh @@ -0,0 +1,52 @@ +#ifndef socket_databuffer_hh +#define socket_databuffer_hh +// socket_databuffer.hh +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Nicolas Haller +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: http://perso.efrei.fr/~haller/ +// Email: +// }}} + +#include "socket_client.hh" +#include "data/data_buffer.hh" + +/// Class s'occupant en particulier de récupérer les DataBuffer via le réseau +/// TCP/IP +class SocketDataBuffer : public SocketClient +{ + private: + /// Taille de la DB à recevoir + unsigned dbSize_; + /// Tampon provisoire + std::string strBuffer_; + /// DataBuffer Provisoire + DataBuffer dbBuffer_; + public: + /// Constructeur + SocketDataBuffer(void); + /// Constructeur accept + SocketDataBuffer(SocketServer & socketServer); + /// Récupère un DataBuffer + bool read (DataBuffer & dbReaded, bool bloquant); + /// Ecrit un DB dans le socket + void write (DataBuffer & db); +}; + +#endif // socket_databuffer_hh diff --git a/i/chuck/src/socket/socket_server.cc b/i/chuck/src/socket/socket_server.cc new file mode 100644 index 0000000..1a9cdb9 --- /dev/null +++ b/i/chuck/src/socket/socket_server.cc @@ -0,0 +1,90 @@ +/* socket_serveur.cc - Définition de la classe des sockets client */ +/* Simulotron - Programme de simulation de robot {{{ + * + * Copyright (C) 2005 Nicolas Haller + * + * Robot APB Team/Efrei 2005. + * Web: http://assos.efrei.fr/robot/ + * Email: robot AT efrei DOT fr + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * }}} */ + +#include "socket_server.hh" +#include "utils/errno_exception.hh" +#include "address.hh" + +#include +#include + +SocketServer::SocketServer (const Address & address) +{ + initSocket(address); +} + +SocketServer::SocketServer (const std::string & address, int port) +{ + if(address.empty()) + initSocket(Address(port)); + else + initSocket(Address(address, port)); +} + +SocketServer::~SocketServer (void) +{ + if (socket_ >= 0) + ::close (socket_); +} + + void +SocketServer::listen (int maxQueue) +{ + if (::listen (socket_, maxQueue) < 0 ) + throw errno_exception ("Socket: Impossible d'écouter la mer dans la chaussette", errno); +} + + int +SocketServer::accept (void) +{ + int socket = ::accept (socket_, 0, 0); + if (socket < 0) + throw errno_exception ("Socket: Chaussette bloqué à la douane", errno); + + return socket; +} + +int +SocketServer::getFD (void) const +{ + return socket_; +} + +void +SocketServer::initSocket(const Address & address) +{ + static const int reuse_s = 1; + // Crée le file descriptor du socket + socket_ = socket (PF_INET, SOCK_STREAM, 0); + if (socket_ < 0) + throw errno_exception ("Socket: La chaussette n'a pas pu être tricoté", errno); + // On règle la réusabilité du socket + if (setsockopt (socket_, SOL_SOCKET, SO_REUSEADDR, + &reuse_s, sizeof (int)) == -1) + throw errno_exception ("Socket: Erreur setsockopt : reusable", errno); + // On bind le socket + if (::bind (socket_, address.getSockaddr (), sizeof (*address.getSockaddr ())) < 0) + throw errno_exception ("Socket: Impossible d'assigner la chausette", errno); +} diff --git a/i/chuck/src/socket/socket_server.hh b/i/chuck/src/socket/socket_server.hh new file mode 100644 index 0000000..f2a022e --- /dev/null +++ b/i/chuck/src/socket/socket_server.hh @@ -0,0 +1,56 @@ +#ifndef socket_server_hh +#define socket_server_hh +/* socket_server.hh - Classe des sockets serveur */ +/* Simulotron - Programme de simulation de robot {{{ + * + * Copyright (C) 2005 Nicolas Haller + * + * Robot APB Team/Efrei 2005. + * Web: http://assos.efrei.fr/robot/ + * Email: robot AT efrei DOT fr + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * }}} */ + +#include "utils/non_copyable.hh" + +#include +class Address; + +class SocketServer : public NonCopyable +{ + private: + /// Ze socket + int socket_; + public: + /// Constructeur + SocketServer (const Address & address); + /// Constructeur s'occupant de Address + SocketServer (const std::string & address, int port); + /// Destructeur + ~SocketServer (void); + /// Ecoute le port + void listen (int maxQueue); + /// accepte une connection et renvoie le fd + int accept (void); + /// récupère le FD du socket + int getFD (void) const; + private: + /// Initialise le socket + void initSocket(const Address & address); +}; + +#endif //socket_server_hh diff --git a/i/chuck/src/socket/socket_text.cc b/i/chuck/src/socket/socket_text.cc new file mode 100644 index 0000000..da8a23b --- /dev/null +++ b/i/chuck/src/socket/socket_text.cc @@ -0,0 +1,236 @@ +// socket_text.cc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Dufour Jérémy +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: %WEB% +// Email: +// }}} + +#include "socket_text.hh" + +#include "server_socket.hh" +#include "address.hh" + +#include +#include +#include +#include + +/// Taille maximum du header +static const unsigned max_header_size = 10; + +/// Constructeur du serveur +SocketText::SocketText (ServerSocket &ss) +: recvBufPos_ (0), numMessageBuffer_ (0) +{ + headBuf_.resize (max_header_size); + socket_ = ss.accept (); +} + +/// Constructeur du serveur avec addresse +SocketText::SocketText (ServerSocket &ss, Address &a) +: recvBufPos_ (0), numMessageBuffer_ (0) +{ + headBuf_.resize (max_header_size); + socket_ = ss.accept (a); +} + +/// Constructeur du client +SocketText::SocketText (const Address &a) +: recvBufPos_ (0), numMessageBuffer_ (0) +{ + headBuf_.resize (max_header_size); + // Création du socket + socket_ = socket (AF_INET, SOCK_STREAM, 0); + if (socket_ == -1) + throw std::runtime_error ("Erreur de création de socket"); + // Connexion au serveur + if (connect (socket_, a.getSockaddr (), sizeof (sockaddr_in)) == -1) + throw std::runtime_error ("Erreur de connexion au serveur"); +} + +/// Envoie d'un buffer de données. +SocketText & +SocketText::operator<< (const DataBuffer &d) +{ + // Copie du buffer + DataBuffer db (d); + // Récupération de la taille du message + unsigned size = db.size (); + // Données du buffer + std::vector data (size); + // On y place les données dedans + db.read ((uint8_t*) &data[0], size); + // Encode les données et le places dans le buffer d'envoie + encode (&data[0], size, db.type ()); + return *this; +} + +/// Reception d'un buffer de données. +SocketText & +SocketText::operator>> (DataBuffer &d) +{ + if (numMessageBuffer_ > 0) + { + // Récupération des informations du message qu'on veut retirer + unsigned int size = messList_.begin ()->size; + d.setType (messList_.begin ()->type); + // Récupération du message depuis le buffer + std::vector v (size); + std::memcpy (&v[0], &recvBuf_[0], size); + // Ecriture des données dans le buffer + d.write ((uint8_t*) &v[0], v.size ()); + // Suppression du message du buffer + recvBuf_.erase (recvBuf_.begin (), recvBuf_.begin () + size); + messList_.erase (messList_.begin ()); + bufferOldSize_ -= size; + bufferCurSize_ -= size; + recvBufPos_ -= size; + numMessageBuffer_--; + } + return *this; +} + +/// Envoie des données du buffer. +int +SocketText::send (void) +{ + int status; + status = ::send (socket_, &sendBuf_[0], sendBuf_.size (), MSG_NOSIGNAL); + if (status == -1 && errno != EWOULDBLOCK) + { + throw std::runtime_error ("Erreur de send de socket"); + } + if (status >= 0) + { + if (status != 0) + sendBuf_.erase (sendBuf_.begin (), sendBuf_.begin () + status); + return status; + } + return -1; +} + +/// Encodage du message (rajout du header) +void +SocketText::encode (const char *data, const int size, + const DataBuffer::dataType_e type) +{ + // Création du header (1H4242H) + std::ostringstream o; + // Rajout du type + if (!(o << type)) + throw std::runtime_error ("Erreur de convertion int -> string"); + o << "H"; + if (!(o << size )) + throw std::runtime_error ("Erreur de convertion int -> string"); + o << "H"; + // Recopie du header dans le buffer + std::string s = o.str (); + std::string::const_iterator sEnd = s.end (); + unsigned int compt = 0; + std::string::const_iterator i = s.begin (); + // Ecriture d'un header de taille fixe + while (compt < max_header_size) + { + if (i != sEnd) + { + sendBuf_.push_back (*i); + i++; + } + else + sendBuf_.push_back ('H'); + compt++; + } + // Rajout des données dans le buffer + for (int i = 0; i < size; i++) + sendBuf_.push_back (data[i]); +} + +/// Décodage du header. +int +SocketText::decode (void) +{ + mess_t header; + header.type = (DataBuffer::dataType_e) std::atoi (&headBuf_[0]); + header.size = std::atoi (&headBuf_[2]); + messList_.push_back (header); + return header.size; +} + +/// Reception de données dans un vecteur. +bool +SocketText::recv () +{ + // FIXME C'est KK + int status; + static unsigned int headerPos = 0; + + // On n'a pas reçu encore de quoi faire un header + if (headerPos < max_header_size) + { + status = ::recv (socket_, &headBuf_[headerPos], + max_header_size - headerPos, MSG_NOSIGNAL); + if (status == -1 && errno != EWOULDBLOCK) + throw std::runtime_error ("Erreur de send de socket"); + if (status > 0) + headerPos += status; + } + // Décodage du header + if (headerPos == max_header_size) + { + bufferOldSize_ = recvBuf_.size (); + bufferCurSize_ = bufferOldSize_ + decode (); + recvBuf_.resize (bufferCurSize_); + headerPos ++; + } + // Récupération du message lui-même + if (headerPos > max_header_size) + { + status = ::recv (socket_, &recvBuf_[recvBufPos_], + bufferCurSize_ - recvBufPos_, MSG_NOSIGNAL); + if (status == -1 && errno != EWOULDBLOCK) + throw std::runtime_error ("Erreur de send de socket"); + if (status > 0) + recvBufPos_ += status; + if (recvBufPos_ == bufferCurSize_) + { + headerPos = 0; + numMessageBuffer_++; + } + } + return numMessageBuffer_ > 0; +} + +/// Changement du bloquant non/bloquant. +void +SocketText::nonblock (bool flag) +{ + // Récupération de l'ancien flag. + int old = fcntl (socket_, F_GETFL, 0); + if (old == -1) + throw std::runtime_error ("Erreur de fcntl"); + // Change le flag. + if (flag) + old |= O_NONBLOCK; + else + old &= ~O_NONBLOCK; + // Ecrit le nouveau flag. + if (fcntl (socket_, F_SETFL, old) == -1) + throw std::runtime_error ("Erreur de fcntl"); +} diff --git a/i/chuck/src/socket/socket_text.hh b/i/chuck/src/socket/socket_text.hh new file mode 100644 index 0000000..b734753 --- /dev/null +++ b/i/chuck/src/socket/socket_text.hh @@ -0,0 +1,80 @@ +#ifndef socket_text_hh +#define socket_text_hh +// socket_text.hh +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Dufour Jérémy +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: %WEB% +// Email: +// }}} + +class ServerSocket; +class Address; +#include "data/data_buffer.hh" + +#include + +class SocketText { + /// Structure pour stocker les informations d'un message. + typedef struct { + unsigned int size; + DataBuffer::dataType_e type; + } mess_t; + std::vector messList_; + /// L'identificateur du socket. + int socket_; + /// Buffer pour le header. + std::vector headBuf_; + /// Buffer de reception de données. + std::vector recvBuf_; + /// Buffer d'émission de données. + std::vector sendBuf_; + /// Taille des buffers d'E/S XXX + unsigned int recvBufPos_; + unsigned int bufferOldSize_; + unsigned int bufferCurSize_; + /// Nombre de message dans le buffer + int numMessageBuffer_; + DataBuffer::dataType_e type_; + /// Encodage du message (rajout du header) + void encode (const char *data, const int size, + const DataBuffer::dataType_e type); + /// Décodage du header. + int decode (void); + + public: + /// Constructeur du serveur. + SocketText (ServerSocket &ss); + /// Constructeur du serveur avec addresse. + SocketText (ServerSocket &ss, Address &a); + /// Constructeur du client. + SocketText (const Address &a); + /// Envoie d'un buffer de données. + SocketText &operator<< (const DataBuffer &d); + /// Reception d'un buffer de données. + SocketText &operator>> (DataBuffer &d); + /// Envoie des données du buffer. + int send (void); + /// Reception de données dans un vecteur. + bool recv (void); + /// Changement du bloquant non/bloquant. + void nonblock (bool flag = true); +}; + +#endif // socket_text_hh diff --git a/i/chuck/src/socket/test_server.cc b/i/chuck/src/socket/test_server.cc new file mode 100644 index 0000000..81399ec --- /dev/null +++ b/i/chuck/src/socket/test_server.cc @@ -0,0 +1,91 @@ +// test_socket.cc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Dufour Jérémy +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: %WEB% +// Email: +// }}} +#include "server_socket.hh" +#include "address.hh" +#include "socket_text.hh" +#include "data/data_input_file.hh" +#include "data/data_buffer.hh" +#include "image/raw_reader.hh" +#include "image/image.hh" + +#include +#include +#include + +int +main (int argc, char **argv) +{ + if (argc == 3) + { + try + { + // Serveur + ServerSocket ss (atoi (argv[1])); + Address a; + SocketText st (ss, a); + st.nonblock (); + // DataBuffer de reception + DataBuffer db; + uint8_t c = 'a'; + DataBuffer dbAskImg (&c, 1, 1, DataBuffer::AskImage); + st << dbAskImg; + st.send (); + // Reception des données + while (!st.recv ()); + st >> db; + if (db.type () != DataBuffer::Image) + throw std::runtime_error ("Echec de la transmission"); + RawReader reader (db, 360, 296, Image::rgb); + Image img (360, 296, Image::rgb); + img.read (reader); + std::ofstream file (argv[2]); + file.write ((char*) img.getBuf (), img.getBufSize ()); + +// // Récupération des données du DataBuffer +// std::vector v (db.size ()); +// db.read ((uint8_t*) &v[0], db.size ()); +// // Ecriture dans le fichier +// std::ofstream file (argv[2]); +// file.write (&v[0], v.size ()); +// DataBuffer db1; +// // Reception des données +// while (!st.recv ()); +// st >> db1; +// std::cout << ">> Reçu " << db1.size () << " bits." << std::endl; +// if (db1.type () != DataBuffer::Image) +// throw std::runtime_error ("Echec de la transmission"); + } + catch (const std::runtime_error &r) + { + std::cerr << argv[0] << ": " << r.what () << std::endl; + return 1; + } + } + else + { + std::cerr << "Syntaxe: " << argv[0] << " port out_file" << std::endl; + return 1; + } + return 0; +} diff --git a/i/chuck/src/socket/test_socket.cc b/i/chuck/src/socket/test_socket.cc new file mode 100644 index 0000000..81b39a0 --- /dev/null +++ b/i/chuck/src/socket/test_socket.cc @@ -0,0 +1,156 @@ +/* test_socket.cc - Programme de test des sockets. */ +/* Simulotron - Programme de simulation de robot {{{ + * + * Copyright (C) 2005 Nicolas Haller + * + * Robot APB Team/Efrei 2005. + * Web: http://assos.efrei.fr/robot/ + * Email: robot AT efrei DOT fr + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * }}} */ +#include "socket_server.hh" +#include "socket_client.hh" +#include "utils/errno_exception.hh" + +#include +#include +#include + +//Chaine et char de test +const std::string strDepart = "J'aime la prog système."; +std::string strDest; +const char a = 'f'; +char b; + +int testSockServ(SocketServer & sockServ); +int testSockClient(int pauseMode); + +int main(void) +{ + pid_t pid; + int resultServer = 0, resultClient; + // Pause mode pour débugger le fork + int pauseMode = 0; + + // Création de la socket serveur; + SocketServer sockServ("",4242); + // Mise en écoute du socket serveur + sockServ.listen(12); + + // on fork pour traiter le client et le serveur + pid = fork(); + if(pid == 0) //Processus fils + testSockClient(pauseMode); + else //Processus parent + resultServer = testSockServ(sockServ); + + // On analyse les résultats + wait(&resultClient); + if (!(WIFEXITED(resultClient) && WEXITSTATUS(resultClient) == 0)) + { + std::cerr << "ECHEC: Problème coté client" << std::endl; + exit (-1); + } + if (resultServer != 0) + { + std::cerr << "ECHEC: Problème coté serveur" << std::endl; + exit (-1); + } + + return 0; +} + +int testSockServ(SocketServer & sockServ) +{ + try + { + // Acceptation d'une connection + SocketClient sockFork(sockServ); + // Reception d'un message + sockFork.read(strDest, true); + if(strDepart != strDest) + { + std::cout << "CHIER!! Le message d'origine est altéré en ecrivant du client au serveur!!" << std::endl; + std::cout << "Le message d'origine: " << strDepart << std::endl; + std::cout << "Message reçu: " << std::endl; + return 1; + } + // Ecriture du serveur au client + sockFork.write(strDepart); + // Reception d'un char + //b = sockFork.getChar(); + //if(a != b) + //{ + // std::cout << "CHIER!! Le char d'origine est altéré en ecrivant du client au serveur!!" << std::endl; + // std::cout << "Le char d'origine: " << a << std::endl; + // std::cout << "Le char d'arrivé: " << b << std::endl; + // return 1; + //} + // Ecriture du serveur vers le client + //sockFork.putChar(a); + } + catch(errno_exception & chier) + { + std::cout << "CHIER !! Une exception a été lancé coté serveur!!" << std::endl; + std::cout << chier.what() << std::endl; + return 1; + } + return 0; +} + +int testSockClient(int pauseMode) +{ + // Chance pour debbuger le fork + while(pauseMode) + sleep(10); + try + { + // Création de la socket client + SocketClient sockClient; + // Demande de connection + sockClient.connect(std::string("127.0.0.1"), 4242); + // Ecriture du client dans le serveur + sockClient.write(strDepart); + // Reception du message serveur + sockClient.read(strDest, true); + if(strDepart != strDest) + { + std::cout << "CHIER!! Le message d'origine est altéré en ecrivant du serveur au client!!" << std::endl; + std::cout << "Le message d'origine: " << strDepart << std::endl; + std::cout << "Message reçu: " << std::endl; + exit (1); + } + // Ecriture d'un char du client au serveur + //sockClient.putChar(a); + // Reception d'un char + //b = sockClient.getChar(); + //if(a != b) + //{ + // std::cout << "CHIER!! Le char d'origine est altéré en ecrivant du serveur au client!!" << std::endl; + // std::cout << "Le char d'origine: " << a << std::endl; + // std::cout << "Le char d'arrivé: " << b << std::endl; + // exit (1); + //} + } + catch(errno_exception & chier) + { + std::cout << "CHIER !! Une exception a été lancé coté client!!" << std::endl; + std::cout << chier.what() << std::endl; + exit (1); + } + exit (0); +} diff --git a/i/chuck/src/socket/test_socket_databuffer.cc b/i/chuck/src/socket/test_socket_databuffer.cc new file mode 100644 index 0000000..fb220a8 --- /dev/null +++ b/i/chuck/src/socket/test_socket_databuffer.cc @@ -0,0 +1,125 @@ +/* test_socket.cc - Programme de test des sockets. */ +/* Simulotron - Programme de simulation de robot {{{ + * + * Copyright (C) 2005 Nicolas Haller + * + * Robot APB Team/Efrei 2005. + * Web: http://assos.efrei.fr/robot/ + * Email: robot AT efrei DOT fr + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * }}} */ +#include "socket_server.hh" +#include "socket_databuffer.hh" +#include "data/data_buffer.hh" +#include "utils/errno_exception.hh" + +#include +#include + +//Chaine et char de test +const std::string strDepart = "J'aime la prog système."; +const char a = 'f'; +DataBuffer db1, db2; + +int testSockServ(SocketServer & sockServ); +int testSockClient(int pauseMode); + +int main(void) +{ + pid_t pid; + int resultServer = 0, resultClient; + // Pause mode pour débugger le fork + int pauseMode = 0; + + // Création de la socket serveur; + SocketServer sockServ("",4242); + // Mise en écoute du socket serveur + sockServ.listen(12); + + // on fork pour traiter le client et le serveur + pid = fork(); + if(pid == 0) //Processus fils + testSockClient(pauseMode); + else //Processus parent + resultServer = testSockServ(sockServ); + + // On analyse les résultats + wait(&resultClient); + if (!(WIFEXITED(resultClient) && WEXITSTATUS(resultClient) == 0)) + { + std::cerr << "ECHEC: Problème coté client" << std::endl; + exit (-1); + } + if (resultServer != 0) + { + std::cerr << "ECHEC: Problème coté serveur" << std::endl; + exit (-1); + } + + return 0; +} + +int testSockServ(SocketServer & sockServ) +{ + try + { + // On crée le DataBuffer + db1.write(reinterpret_cast(strDepart.c_str()), + strDepart.size()); + db1.write(reinterpret_cast(&a), sizeof(const char)); + // Acceptation d'une connection + SocketDataBuffer sockFork(sockServ); + // On écrit la DataBuffer dans la socket + sockFork.write(db1); + } + catch(errno_exception & chier) + { + std::cout << "CHIER !! Une exception a été lancé coté serveur!!" << std::endl; + std::cout << chier.what() << std::endl; + return 1; + } + return 0; +} + +int testSockClient(int pauseMode) +{ + // Chance pour debbuger le fork + while(pauseMode) + sleep(10); + try + { + // Création de la socket client + SocketDataBuffer sockDataBuffer; + // Demande de connection + sockDataBuffer.connect(std::string("127.0.0.1"), 4242); + // Reception du message serveur + sockDataBuffer.read(db2, true); + // Paye ta comparaison de DataBuffer + if(db1.size() != db2.size()) + { + std::cout << "CHIER!! Les DB ne font pas la même size" << std::endl; + exit (1); + } + } + catch(errno_exception & chier) + { + std::cout << "CHIER !! Une exception a été lancé coté client!!" << std::endl; + std::cout << chier.what() << std::endl; + exit (1); + } + exit (0); +} diff --git a/i/chuck/src/socket/test_socket_old.cc b/i/chuck/src/socket/test_socket_old.cc new file mode 100644 index 0000000..f2beb51 --- /dev/null +++ b/i/chuck/src/socket/test_socket_old.cc @@ -0,0 +1,76 @@ +// test_socket.cc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Dufour Jérémy +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: %WEB% +// Email: +// }}} + +#include "server_socket.hh" +#include "address.hh" +#include "socket_text.hh" +#include "data/data_input_file.hh" +#include "data/data_buffer.hh" + +#include +#include +#include +#include +#include + +int +main (int argc, char **argv) +{ + if (argc == 4) + { + try + { + // Récupération des données du fichier + DataInputFile df (argv[3]); + std::vector img (319680); + df.read (&img[0], 319680); + // Ecriture des données du fichier dans le buffer + DataBuffer db (&img[0], img.size (), img.size (), + DataBuffer::Image); + DataBuffer dbAnswer; + // Création du socket + char *h = argv[1]; + SocketText st (Address (h, atoi (argv[2]))); + st.nonblock (); + st >> dbAnswer; + if (dbAnswer.type () == DataBuffer::AskImage) + { + // Envoie des données + st << db; + while (st.send () != 0); + } + } + catch (const std::runtime_error &r) + { + std::cerr << argv[0] << ": " << r.what () << std::endl; + return 1; + } + } + else + { + std::cerr << "Syntaxe: " << argv[0] << " host port in_file" << + std::endl; + return 1; + } +} diff --git a/i/chuck/src/tester/Makefile.defs b/i/chuck/src/tester/Makefile.defs new file mode 100644 index 0000000..eeff4ab --- /dev/null +++ b/i/chuck/src/tester/Makefile.defs @@ -0,0 +1,5 @@ +PROGRAMS += test_tester + +tester_OBJECTS = tester.o $(config_OBJECTS) $(interpreter_OBJECTS) $(log_OBJECTS) + +test_tester_OBJECTS = test_tester.o $(tester_OBJECTS) diff --git a/i/chuck/src/tester/test_tester.cc b/i/chuck/src/tester/test_tester.cc new file mode 100644 index 0000000..d292c7f --- /dev/null +++ b/i/chuck/src/tester/test_tester.cc @@ -0,0 +1,78 @@ +// test_tester.cc +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Nicolas Schodet +// +// Robot APB Team/Efrei 2006. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "tester.hh" + +class TestTester : public Tester +{ + public: + // Constructor + TestTester (int argc, char ** argv) + : Tester (argc, argv) { } + void funcA (const Interpreter::Args &a, bool dryrun) + { + if (!dryrun) + std::cout << " a " << a << std::endl; + } + void funcB (void) + { + std::cout << " b ( )" << std::endl; + } + void funcC (int i) + { + std::cout << " c ( " << i << " )" << std::endl; + } + void funcD (const std::string &s) + { + std::cout << " d ( " << s << " )" << std::endl; + } + void funcE (int i, const std::string &s, double d) + { + std::cout << " e ( " << i << ' ' << s << ' ' << d << " )" << std::endl; + } + void preRun (void) + { + Interpreter &interpreter = getInterpreter (); + // Add functions. + interpreter.add ("a", Interpreter::memFunc (*this, &TestTester::funcA), "Function a (any)"); + interpreter.add ("b", Interpreter::memFunc (*this, &TestTester::funcB), "Function b ()"); + interpreter.add ("c", Interpreter::memFunc (*this, &TestTester::funcC), "Function c (int)"); + interpreter.add ("d", Interpreter::memFunc (*this, &TestTester::funcD), "Function d (string)"); + interpreter.add ("e", Interpreter::memFunc (*this, &TestTester::funcE), "Function e (int, string, double)"); + } +}; + +int +main (int argc, char **argv) +{ + try + { + TestTester tt (argc, argv); + tt.run (); + } + catch (const std::exception &e) + { + std::cerr << e.what () << std::endl; + } +} diff --git a/i/chuck/src/tester/tester.cc b/i/chuck/src/tester/tester.cc new file mode 100644 index 0000000..61f577e --- /dev/null +++ b/i/chuck/src/tester/tester.cc @@ -0,0 +1,141 @@ +// tester.cc +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Nicolas Schodet +// +// Robot APB Team/Efrei 2006. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "tester.hh" + +#include // getopt +#include // std::exception +#include // std::exit +#include // std::ostringstream + +/// Constructor. +Tester::Tester (int argc, char **argv, const std::string &description) + : program_(argv[0]), description_ (description), + showCmd_ (false), config_ (argc, argv) +{ + // Parse command line + getOpt (argc, argv); +} + +/// Getopt command line. +/// Supported arguemnts : +/// - -c 'commands list' +/// - -f +/// - -h : help +/// - -l : list commands suppoted +void +Tester::getOpt (int argc, char **argv) +{ + char *optstring = "hlc:f:"; + int option; + std::string strTmp; + + // Check number of args + if (argc < 2) + { + std::cerr << "Argument missing." << std::endl; + usage (); + std::exit (1); + } + + // Automatic error message + opterr = 1; + + while ((option = getopt (argc, argv, optstring)) != EOF) + { + switch (option) + { + case 'c': + // Check commands + commands_ += optarg; + break; + case 'f': + commands_ += ";include \""; + commands_ += optarg; + commands_ += "\";"; + break; + case 'h': + usage (); + std::exit (0); + break; + case 'l': + showCmd_ = true; + break; + case '?': + default: + usage (); + std::exit (2); + break; + } + } + if (commands_.empty () && !showCmd_) + { + usage (); + std::exit (2); + } +} + +/// Print usage to stdout. +void +Tester::usage (void) const +{ + std::cout << "Usage: " << program_ + << " [-c ]" + << " [-f ]" + << std::endl; + if (!description_.empty ()) + std::cout << description_ << std::endl; + std::cout << " -c Commands to run" << std::endl; + std::cout << " -f File with commands" << std::endl; + std::cout << " -l List all known commands by " + << program_ << std::endl; +} + +/// Print all knwon function and role to stdout. +void +Tester::listCmd (void) const +{ + std::cout << "Commands known by " << program_ << " :" << std::endl; + std::cout << interpreter_.help (); +} + +/// Run commands. +void +Tester::run (void) +{ + // Pre-run + preRun (); + if (showCmd_) + { + listCmd (); + std::exit (0); + } + // Check + interpreter_.interpretString (commands_, true); + // Run ! + interpreter_.interpretString (commands_, false); + // Post-run + postRun (); +} + diff --git a/i/chuck/src/tester/tester.hh b/i/chuck/src/tester/tester.hh new file mode 100644 index 0000000..b9aa312 --- /dev/null +++ b/i/chuck/src/tester/tester.hh @@ -0,0 +1,77 @@ +#ifndef tester_hh +#define tester_hh +// tester.hh +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Nicolas Schodet +// +// Robot APB Team/Efrei 2006. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "config/config.hh" +#include "interpreter/interpreter.hh" +#include "log/data_circular_buffer_factory.hh" + +#include +#include +#include + +class Tester +{ + private: + /// DataCircularBufferFactory for beeing destruct at the end of the program. + /// Note : it must stay at the begining of the class ! + DataCircularBufferFactory dbc; + /// The interperter. + Interpreter interpreter_; + /// Program name. + std::string program_; + /// Description of the program. + std::string description_; + /// Commands to run. + std::string commands_; + /// Getopt command line. + void getOpt (int argc, char **argv); + /// Print usage to stdout. + void usage (void) const; + /// Print all knwon function and role to stdout. + void listCmd (void) const; + /// Show commands instead of run them. + bool showCmd_; + protected: + /// The config. + Config config_; + public: + /// Constructor. + Tester (int argc, char ** argv, const std::string &description = ""); + /// Destructor. + virtual ~Tester (void) { } + /// Get a reference to the interpreter. + Interpreter &getInterpreter (void) { return interpreter_; } + /// Run commands. + /// Call preRun, check command, run them, call postRun. + void run (void); + /// Executed before checking/running commands. Good place to add command + /// to the interpreter. + virtual void preRun (void) { } + /// Executed after running commands. + virtual void postRun (void) { } +}; + +#endif // tester_hh diff --git a/i/chuck/src/timer/Makefile.defs b/i/chuck/src/timer/Makefile.defs new file mode 100644 index 0000000..81a57e2 --- /dev/null +++ b/i/chuck/src/timer/Makefile.defs @@ -0,0 +1,5 @@ +PROGRAMS += test_timer + +timer_OBJECTS = timer.o + +test_timer_OBJECTS = test_timer.o $(timer_OBJECTS) diff --git a/i/chuck/src/timer/test_timer.cc b/i/chuck/src/timer/test_timer.cc new file mode 100644 index 0000000..2e8c502 --- /dev/null +++ b/i/chuck/src/timer/test_timer.cc @@ -0,0 +1,47 @@ +// test_timer.cc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "timer.hh" + +#include +#include + +int +main (void) +{ + using namespace std; + cout << "timer 0 " << Timer::getProgramTime () << ' ' << + Timer::getRoundTime () << endl; + sleep (1); + cout << "timer 1 " << Timer::getProgramTime () << ' ' << + Timer::getRoundTime () << endl; + Timer::startRound (); + sleep (2); + cout << "timer 3 " << Timer::getProgramTime () << ' ' << + Timer::getRoundTime () << endl; + Timer::wait (1500); + cout << "timer 4.5 " << Timer::getProgramTime () << ' ' << + Timer::getRoundTime () << endl; + return 0; +} diff --git a/i/chuck/src/timer/timer.cc b/i/chuck/src/timer/timer.cc new file mode 100644 index 0000000..662e6de --- /dev/null +++ b/i/chuck/src/timer/timer.cc @@ -0,0 +1,89 @@ +// timer.cc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "timer.hh" + +#include +#include + +/// Retourne le temps depuis le début du programme en millisecondes. +int +Timer::getProgramTime (void) +{ + Timer &timer = getInstance (); + return getSystemTime () - timer.programStart_; +} + +/// Retourne le temps depuis le début du match en millisecondes. +int +Timer::getRoundTime (void) +{ + Timer &timer = getInstance (); + return timer.roundStart_ != -1 ? getSystemTime () - timer.roundStart_ : 0; +} + +/// Démare le match et enregistre le temps de départ. +void +Timer::startRound (void) +{ + Timer &timer = getInstance (); + timer.roundStart_ = getSystemTime (); +} + +/// Attend un nombre de millisecondes. Attention, le robot ne fait absolument +/// rien pendant cette periode ! +void +Timer::wait (int t) +{ + timespec ts, r; + ts.tv_sec = t / 1000; + ts.tv_nsec = (t % 1000) * 1000000; + nanosleep (&ts, &r); +} + +/// Retourne une référence vers l'instance unique. +Timer & +Timer::getInstance (void) +{ + static Timer instance; + return instance; +} + +/// Retourne la date système. +long long +Timer::getSystemTime (void) +{ + timeval tv; + gettimeofday (&tv, 0); + return ((long long) tv.tv_sec % 1000000) * 1000 + + (long long) tv.tv_usec / 1000; +} + +/// Constructeur. +Timer::Timer (void) +{ + programStart_ = getSystemTime (); + roundStart_ = -1; +} + diff --git a/i/chuck/src/timer/timer.hh b/i/chuck/src/timer/timer.hh new file mode 100644 index 0000000..341f1da --- /dev/null +++ b/i/chuck/src/timer/timer.hh @@ -0,0 +1,51 @@ +#ifndef timer_hh +#define timer_hh +// timer.hh +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} + +/// Classe de chronométrage. +class Timer +{ + long long programStart_, roundStart_; + public: + /// Retourne le temps depuis le début du programme en millisecondes. + static int getProgramTime (void); + /// Retourne le temps depuis le début du match en millisecondes. + static int getRoundTime (void); + /// Démare le match et enregistre le temps de départ. + static void startRound (void); + /// Attend un nombre de millisecondes. Attention, le robot ne fait + /// absolument rien pendant cette periode ! + static void wait (int t); + private: + /// Retourne une référence vers l'instance unique. + static Timer &getInstance (void); + /// Retourne la date système. + static long long getSystemTime (void); + /// Constructeur. + Timer (void); +}; + +#endif // timer_hh diff --git a/i/chuck/src/utils/Makefile.defs b/i/chuck/src/utils/Makefile.defs new file mode 100644 index 0000000..8eb0711 --- /dev/null +++ b/i/chuck/src/utils/Makefile.defs @@ -0,0 +1,11 @@ +PROGRAMS += test_any test_callback test_bind test_signalhandler + +utils_OBJECTS = fd_set.o hexa.o + +test_any_OBJECTS = test_any.o + +test_callback_OBJECTS = test_callback.o + +test_bind_OBJECTS = test_bind.o + +test_signalhandler_OBJECTS = test_signalhandler.o diff --git a/i/chuck/src/utils/any.hh b/i/chuck/src/utils/any.hh new file mode 100644 index 0000000..dc6204e --- /dev/null +++ b/i/chuck/src/utils/any.hh @@ -0,0 +1,125 @@ +#ifndef any_hh +#define any_hh +// any.hh +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2003-2006 Nicolas Schodet +// +// Robot APB Team/Efrei 2006. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} + +#include +#include +#include + +/// This class can contain a data of almost any type. This very type must be +/// CopyConstructible and OutputStreamable. The OutputStreamable restriction +/// could be removed, but it is so convenient to output an any... +class any +{ + class AbstractHolder; + AbstractHolder *holder_; + public: + /// Default constructor. + any (void); + /// Constructor. + template + any (const T &value); + /// Copy constructor. + any (const any &other); + /// Destructor. + ~any (void); + /// Swap content between two any objects. + any &swap (any &other); + /// Copy another any object. + any &operator= (const any &other); + /// Copy another object into this any. + template + any &operator= (const T &value); + /// Test if the any object is empty. + bool empty (void) const; + /// Return the std::type_info of the contained object. + const std::type_info &type (void) const; + private: + template + friend T *any_cast (any *rhs); + friend std::ostream &operator<< (std::ostream &os, const any &rhs); + /// Abstract holder class. + class AbstractHolder + { + public: + /// Destructor. + virtual ~AbstractHolder (void); + virtual const std::type_info &type (void) const = 0; + virtual AbstractHolder *clone (void) const = 0; + virtual std::ostream &print (std::ostream &os) const = 0; + }; + /// Holder class, templated. + template + class Holder : public AbstractHolder + { + public: + T value_; + public: + Holder (const T &value); + virtual const std::type_info &type (void) const; + virtual AbstractHolder *clone (void) const; + virtual std::ostream &print (std::ostream &os) const; + }; +}; + +/// Return a pointer to the contained object or 0 on faillure. +template +T * +any_cast (any *rhs); + +/// Return a const pointer to the contained object or 0 on faillure. +template +const T * +any_cast (const any *rhs); + +/// Return a const reference to the contained object or throw a bad_any_cast +/// on faillure. +template +const T & +any_cast (const any &rhs); + +/// Object throw if a any_cast returning a reference fail. +class bad_any_cast : public std::bad_cast +{ + std::string what_; + public: + /// Constructor. + bad_any_cast (const std::type_info &to, const std::type_info &from); + /// Destructor which should throw nothing. + virtual ~bad_any_cast() throw() + { } + /// Get the error text. + virtual const char *what() const throw() + { return what_.c_str (); } +}; + +/// Print the contained object. +std::ostream & +operator<< (std::ostream &os, const any &rhs); + +#include "any.tcc" + +#endif // any_hh diff --git a/i/chuck/src/utils/any.tcc b/i/chuck/src/utils/any.tcc new file mode 100644 index 0000000..70d1084 --- /dev/null +++ b/i/chuck/src/utils/any.tcc @@ -0,0 +1,185 @@ +#ifndef any_tcc +#define any_tcc +// any.tcc +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2003-2006 Nicolas Schodet +// +// Robot APB Team/Efrei 2006. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "list_ostream_output.hh" + +#include + +/// Default constructor. +inline +any::any (void) + : holder_ (0) +{ +} + +/// Constructor. +template +any::any (const T &value) + : holder_ (new Holder (value)) +{ +} + +/// Copy constructor. +inline +any::any (const any &other) + : holder_ (other.holder_ ? other.holder_->clone () : 0) +{ +} + +/// Destructor. +inline +any::~any (void) +{ + delete holder_; +} + +/// Swap content between two any objects. +inline +any & +any::swap (any &other) +{ + std::swap (holder_, other.holder_); + return *this; +} + +/// Copy another any object. +inline +any & +any::operator= (const any &other) +{ + any (other).swap (*this); + return *this; +} + +/// Copy another object into this any. +template +any & +any::operator= (const T &value) +{ + any (value).swap (*this); + return *this; +} + +/// Test if the any object is empty. +inline +bool +any::empty (void) const +{ + return !holder_; +} + +/// Return the std::type_info of the contained object. +inline +const std::type_info & +any::type (void) const +{ + return holder_ ? holder_->type () : typeid (void); +} + +/// Destructor. +inline +any::AbstractHolder::~AbstractHolder (void) +{ +} + +template +any::Holder::Holder (const T &value) + : value_ (value) +{ +} + +template +const std::type_info & +any::Holder::type (void) const +{ + return typeid (T); +} + +template +any::AbstractHolder * +any::Holder::clone (void) const +{ + return new Holder (value_); +} + +template +std::ostream & +any::Holder::print (std::ostream &os) const +{ + return os << value_; +} + +/// Return a pointer to the contained object or 0 on faillure. +template +T * +any_cast (any *rhs) +{ + return rhs && rhs->type () == typeid (T) + ? &static_cast *> (rhs->holder_)->value_ + : 0; +} + +/// Return a const pointer to the contained object or 0 on faillure. +template +const T * +any_cast (const any *rhs) +{ + return any_cast (const_cast (rhs)); +} + +/// Return a const reference to the contained object or throw a bad_any_cast +/// on faillure. +template +const T & +any_cast (const any &rhs) +{ + const T *value = any_cast (&rhs); + if (!value) + throw bad_any_cast (typeid (T), rhs.type ()); + return *value; +} + +/// Constructor. +inline +bad_any_cast::bad_any_cast (const std::type_info &to, + const std::type_info &from) +{ + what_ = "illegal conversion from \'"; + what_ += from.name (); + what_ += "\' to \'"; + what_ += to.name (); + what_ += "\'"; +} + +/// Print the contained object. +inline +std::ostream & +operator<< (std::ostream &os, const any &rhs) +{ + return rhs.holder_->print (os); +} + +#endif // any_tcc diff --git a/i/chuck/src/utils/bind.hh b/i/chuck/src/utils/bind.hh new file mode 100644 index 0000000..a5630fe --- /dev/null +++ b/i/chuck/src/utils/bind.hh @@ -0,0 +1,91 @@ +#ifndef bind_hh +#define bind_hh +// bind.hh +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2004 Nicolas Schodet +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: http://perso.efrei.fr/~schodet/ +// Email: +// }}} + +/// Class used to bind a function taking an argument to a functor taking no +/// argument. This is not supposed to be used directly, but using the bind +/// template function. +template +class ArgBinder +{ + /// Original function. + F func_; + /// Stored argument reference. + const A &arg_; + public: + /// Return value. + typedef R result_type; + public: + ArgBinder (F func, const A &arg) + : func_ (func), arg_ (arg) + { } + result_type operator () (void) + { + return func_ (arg_); + } +}; + +/// Bind a function taking an argument to a functor taking no argument. +/// Return value must be specified, other template arguments can be implied. +template +ArgBinder +bind (F func, const A &arg) +{ + return ArgBinder (func, arg); +} + +/// Class used to bind a member function to a functor taking no argument. +/// This is not supposed to be used directly, but using the bind template +/// function. +template +class ObjBinder +{ + /// Original member function. + R (C::*func_) (void); + /// Object pointer stored. + C *obj_; + public: + /// Return value. + typedef R result_type; + public: + ObjBinder (R (C::*func) (void), C *obj) + : func_ (func), obj_ (obj) + { } + result_type operator () (void) + { + (obj_->*func_) (); + } +}; + +/// Bind a member function to a functor taking no argument. All template +/// parameters must be specified. +template +ObjBinder +bind (R (C::*func) (void), C *obj) +{ + return ObjBinder (func, obj); +} + +#endif // bind_hh diff --git a/i/chuck/src/utils/callback.hh b/i/chuck/src/utils/callback.hh new file mode 100644 index 0000000..ab1311c --- /dev/null +++ b/i/chuck/src/utils/callback.hh @@ -0,0 +1,96 @@ +#ifndef callback_hh +#define callback_hh +// callback.hh +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2003-2006 Nicolas Schodet +// +// Robot APB Team/Efrei 2006. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} + +#include + +/// Class to store a callback. This callback can be of any type (function or +/// fonctor). +template +class Callback +{ + class AbstractHolder; + AbstractHolder *holder_; + public: + /// Return value. + typedef R result_type; + public: + /// Default constructor. Make an empty callback. + Callback (void); + /// Constructor. + template + Callback (T callback); + /// Copy constructor. + Callback (const Callback &other); + /// Destructor. + ~Callback (void); + /// Assignement operator. + Callback &operator= (const Callback &rhs); + /// Call the contained callback. + R operator () (void); + /// Swap the callback content with another callback. + void swap (Callback &rhs); + /// Change the contained callback. + template + Callback &operator= (T rhs); + /// Test if empty. + bool empty (void) const; + /// Test if not empty. + operator bool (void) const; + private: + /// Abstract container. + class AbstractHolder + { + public: + virtual ~AbstractHolder (void); + virtual R operator () (void) = 0; + virtual AbstractHolder *clone (void) = 0; + }; + /// Templated container. + template + class Holder : public AbstractHolder + { + private: + T callback_; + public: + Holder (T callback); + virtual R operator () (void); + virtual AbstractHolder *clone (void); + }; +}; + +/// Exception thrown on call of an empty callback. +class bad_callback : public std::runtime_error +{ + public: + bad_callback (void) : std::runtime_error ("bad_callback: empty callback call") + { + } +}; + +#include "callback.tcc" + +#endif // callback_hh diff --git a/i/chuck/src/utils/callback.tcc b/i/chuck/src/utils/callback.tcc new file mode 100644 index 0000000..4e8bdd4 --- /dev/null +++ b/i/chuck/src/utils/callback.tcc @@ -0,0 +1,140 @@ +#ifndef callback_tcc +#define callback_tcc +// callback.tcc +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2003-2006 Nicolas Schodet +// +// Robot APB Team/Efrei 2006. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} + +#include + +/// Default constructor. Make an empty callback. +template +Callback::Callback (void) + : holder_ (0) +{ +} + +/// Constructor. +template +template +Callback::Callback (T callback) + : holder_ (new Holder (callback)) +{ +} + +/// Copy constructor. +template +Callback::Callback (const Callback &other) + : holder_ (other.holder_ ? other.holder_->clone () : 0) +{ +} + +/// Destructor. +template +Callback::~Callback (void) +{ + delete holder_; +} + +/// Assignement operator. +template +Callback & +Callback::operator= (const Callback &rhs) +{ + Callback (rhs).swap (*this); + return *this; +} + +/// Call the contained callback. +template +R +Callback::operator () (void) +{ + if (!holder_) + throw bad_callback (); + else + return (*holder_) (); +} + +/// Swap the callback content with another callback. +template +void +Callback::swap (Callback &rhs) +{ + std::swap (holder_, rhs.holder_); +} + +/// Change the contained callback. +template +template +Callback & +Callback::operator= (T rhs) +{ + Callback (rhs).swap (*this); + return *this; +} + +/// Test if empty. +template +bool +Callback::empty (void) const +{ + return !holder_; +} + +/// Test if not empty. +template +Callback::operator bool (void) const +{ + return !empty (); +} + +template +Callback::AbstractHolder::~AbstractHolder (void) +{ +} + +template +template +Callback::Holder::Holder (T callback) + : callback_ (callback) +{ +} + +template +template +R +Callback::Holder::operator () (void) +{ + return callback_ (); +} + +template +template +typename Callback::AbstractHolder * +Callback::Holder::clone (void) +{ + return new Holder (callback_); +} + +#endif // callback_tcc diff --git a/i/chuck/src/utils/errno_exception.hh b/i/chuck/src/utils/errno_exception.hh new file mode 100644 index 0000000..58a636e --- /dev/null +++ b/i/chuck/src/utils/errno_exception.hh @@ -0,0 +1,48 @@ +#ifndef errno_exception_hh +#define errno_exception_hh +// errno_exception.hh +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} + +#include +#include +#include +#include + +/// Exception lancé lorsqu'une erreur est retournée par la libc. +class errno_exception : public std::exception +{ + int errno_; + std::string what_; + public: + errno_exception (const std::string &desc, int errno__) + : errno_ (errno__), what_ (desc + ": " + strerror (errno__)) { } + errno_exception (int errno__) + : errno_ (errno__), what_ (strerror (errno__)) { } + ~errno_exception (void) throw () { } + virtual const char* what () const throw () { return what_.c_str (); } + int getErrno (void) const { return errno_; } +}; + +#endif // errno_exception_hh diff --git a/i/chuck/src/utils/fd_set.cc b/i/chuck/src/utils/fd_set.cc new file mode 100644 index 0000000..998f3f5 --- /dev/null +++ b/i/chuck/src/utils/fd_set.cc @@ -0,0 +1,53 @@ +// fd_set.cc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "fd_set.hh" +#include "utils/errno_exception.hh" + +/// Wait for an read event or timeout in milliseconds, return true on read +/// event. +bool +FdSet::wait (int timeout/*-1*/) +{ + int r; + if (timeout == -1) + { + // Without timeout. + r = select (FD_SETSIZE, get (), 0, 0, 0); + } + else + { + // With timeout. + struct timeval tv; + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + r = select (FD_SETSIZE, get (), 0, 0, &tv); + } + if (r == -1) + // Error. + throw errno_exception (errno); + else + return r != 0; +} + diff --git a/i/chuck/src/utils/fd_set.hh b/i/chuck/src/utils/fd_set.hh new file mode 100644 index 0000000..3d6d44c --- /dev/null +++ b/i/chuck/src/utils/fd_set.hh @@ -0,0 +1,54 @@ +#ifndef fd_set_hh +#define fd_set_hh +// fd_set.hh +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2004 Nicolas Schodet +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: http://perso.efrei.fr/~schodet/ +// Email: +// }}} + +#include + +/// Wrapper over libc fd_set. +class FdSet +{ + fd_set set_; + public: + /// Default constructor. + FdSet (void) + { FD_ZERO (&set_); } + /// Set a fd. + void set (int fd) + { FD_SET (fd, &set_); } + /// Clear a fd. + void clear (int fd) + { FD_CLR (fd, &set_); } + /// Test if a fd is set. + bool isSet (int fd) const + { return FD_ISSET (fd, &set_); } + /// Get pointer to internal fd_set. + fd_set *get (void) + { return &set_; } + /// Wait for an read event or timeout in milliseconds, return true on read + /// event. + bool wait (int timeout = -1); +}; + +#endif // fd_set_hh diff --git a/i/chuck/src/utils/hexa.cc b/i/chuck/src/utils/hexa.cc new file mode 100644 index 0000000..102458e --- /dev/null +++ b/i/chuck/src/utils/hexa.cc @@ -0,0 +1,113 @@ +// hexa.cc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "hexa.hh" + +// Table de conversion en hexa. +static const char *digit2hexTbl_ = "0123456789abcdef"; + +// Table de conversion depuis l'hexa. +#define hI hexInvalid +static const int hex2digitTbl_[] = +{ + hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI, /* 0-15 */ + hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI, /* 16-31 */ + hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI, /* 32-47 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,hI,hI,hI,hI,hI,hI, /* 48-63 */ + hI,10,11,12,13,14,15,hI,hI,hI,hI,hI,hI,hI,hI,hI, /* 64-79 */ + hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI, /* 80-95 */ + hI,10,11,12,13,14,15,hI,hI,hI,hI,hI,hI,hI,hI,hI, /* 96-111 */ + hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI, /* 112-127 */ + hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI, /* 128-143 */ + hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI, /* 144-159 */ + hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI, /* 160-175 */ + hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI, /* 176-191 */ + hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI, /* 192-207 */ + hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI, /* 208-223 */ + hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI, /* 224-239 */ + hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI,hI, /* 240-255 */ +}; + +/// Converti un caractère hexa (0-9a-f) en chiffre (0-15). +int +hex2digit (char c) +{ + return hex2digitTbl_[static_cast (c)]; +} + +/// Converti un chiffre (0-15) en hexa (0-9a-f). +char +digit2hex (int d) +{ + return digit2hexTbl_[d]; +} + +/// Décode un mot non-signé (1 octets). +unsigned int +hexUnsignedChar2int (const char *s) +{ + int h1 = hex2digit (s[0]); + int h0 = hex2digit (s[1]); + if (h1 == hexInvalid || h0 == hexInvalid) + return hexInvalid; + return (unsigned char) (h1 << 4 | h0); +} + +/// Décode un mot signé (1 octets). +int +hexSignedChar2int (const char *s) +{ + int h1 = hex2digit (s[0]); + int h0 = hex2digit (s[1]); + if (h1 == hexInvalid || h0 == hexInvalid) + return hexInvalid; + return (signed char) (h1 << 4 | h0); +} + +/// Décode un mot non-signé (2 octets). +int +hexUnsignedShort2int (const char *s) +{ + int h3 = hex2digit (s[0]); + int h2 = hex2digit (s[1]); + int h1 = hex2digit (s[2]); + int h0 = hex2digit (s[3]); + if (h3 == hexInvalid || h2 == hexInvalid || h1 == hexInvalid || h0 == hexInvalid) + return hexInvalid; + return (unsigned short) (h3 << 12 | h2 << 8 | h1 << 4 | h0); +} + +/// Décode un mot signé (2 octets). +int +hexSignedShort2int (const char *s) +{ + int h3 = hex2digit (s[0]); + int h2 = hex2digit (s[1]); + int h1 = hex2digit (s[2]); + int h0 = hex2digit (s[3]); + if (h3 == hexInvalid || h2 == hexInvalid || h1 == hexInvalid || h0 == hexInvalid) + return hexInvalid; + return (short) (h3 << 12 | h2 << 8 | h1 << 4 | h0); +} + diff --git a/i/chuck/src/utils/hexa.hh b/i/chuck/src/utils/hexa.hh new file mode 100644 index 0000000..f7d3399 --- /dev/null +++ b/i/chuck/src/utils/hexa.hh @@ -0,0 +1,49 @@ +#ifndef hexa_hh +#define hexa_hh +// hexa.hh +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} + +/// Constante retournée pour une valeur invalide. +const int hexInvalid = 1 << 24; + +/// Converti un caractère hexa (0-9a-f) en chiffre (0-15). +int hex2digit (char c); + +/// Converti un chiffre (0-15) en hexa (0-9a-f). +char digit2hex (int d); + +/// Décode un mot non-signé (1 octets). +unsigned int hexUnsignedChar2int (const char *s); + +/// Décode un mot signé (1 octets). +int hexSignedChar2int (const char *s); + +/// Décode un mot non-signé (2 octets). +int hexUnsignedShort2int (const char *s); + +/// Décode un mot signé (2 octets). +int hexSignedShort2int (const char *s); + +#endif // hexa_hh diff --git a/i/chuck/src/utils/list_ostream_output.hh b/i/chuck/src/utils/list_ostream_output.hh new file mode 100644 index 0000000..3863a39 --- /dev/null +++ b/i/chuck/src/utils/list_ostream_output.hh @@ -0,0 +1,62 @@ +#ifndef list_ostream_output_hh +#define list_ostream_output_hh +// list_ostream_output.hh +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} + +#include +#include +#include +#include +#include + +/// Output any list. +template +std::ostream & +output_list (std::ostream &os, const T &list) +{ + os << "( "; + std::copy (list.begin (), list.end (), + std::ostream_iterator (os, " ")); + os << ')'; + return os; +} + +/// Output a list. +template +std::ostream & +operator<< (std::ostream &os, const std::list &list) +{ + return output_list (os, list); +} + +/// Output a vector. +template +std::ostream & +operator<< (std::ostream &os, const std::vector &list) +{ + return output_list (os, list); +} + +#endif // list_ostream_output_hh diff --git a/i/chuck/src/utils/mathutil.hh b/i/chuck/src/utils/mathutil.hh new file mode 100644 index 0000000..d58cec3 --- /dev/null +++ b/i/chuck/src/utils/mathutil.hh @@ -0,0 +1,57 @@ +#ifndef mathutil_hh +#define mathutil_hh +// mathutil.hh +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include + +/// Normalise l'angle entre -pi et +pi. +double +angleNorm (double a); + +/// Converti en coordonnées polaires. +void +toPolar (double x, double y, double &r, double &a); + +/// Normalise l'angle en [-pi..+pi). +inline double +angleNorm (double a) +{ + while (a >= M_PI) + a -= 2.0 * M_PI; + while (a < -M_PI) + a += 2.0 * M_PI; + return a; +} + +/// Converti en coordonnées polaires. +inline void +toPolar (double x, double y, double &r, double &a) +{ + // Rayon. + r = sqrt (x * x + y * y); + a = y > 0 ? acos (x / r) : -acos (x / r); +} + +#endif // mathutil_hh diff --git a/i/chuck/src/utils/meta/Makefile.defs b/i/chuck/src/utils/meta/Makefile.defs new file mode 100644 index 0000000..8fa3a10 --- /dev/null +++ b/i/chuck/src/utils/meta/Makefile.defs @@ -0,0 +1,3 @@ +PROGRAMS += test_meta + +test_meta_OBJECTS = test_meta.o diff --git a/i/chuck/src/utils/meta/is_equal.hh b/i/chuck/src/utils/meta/is_equal.hh new file mode 100644 index 0000000..a67e8a6 --- /dev/null +++ b/i/chuck/src/utils/meta/is_equal.hh @@ -0,0 +1,44 @@ +#ifndef is_equal_hh +#define is_equal_hh +// is_equal.hh - test if two types equals. +// {{{ +// +// Copyright (C) 2006 Nicolas Schodet +// +// Robot APB Team/Efrei 2006. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} + +namespace meta { + +template +struct isEqual +{ + static const bool value = false; +}; + +template +struct isEqual +{ + static const bool value = true; +}; + +} // namespace meta + +#endif // is_equal_hh diff --git a/i/chuck/src/utils/meta/is_string.hh b/i/chuck/src/utils/meta/is_string.hh new file mode 100644 index 0000000..99782d2 --- /dev/null +++ b/i/chuck/src/utils/meta/is_string.hh @@ -0,0 +1,45 @@ +#ifndef is_string_hh +#define is_string_hh +// is_string.hh +// {{{ +// +// Copyright (C) 2004 Nicolas Schodet +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: http://perso.efrei.fr/~schodet/ +// Email: +// }}} + +#include + +namespace meta { + +template +struct isString +{ + static const bool value = false; +}; + +template<> +struct isString +{ + static const bool value = true; +}; + +} // namespace meta + +#endif // is_string_hh diff --git a/i/chuck/src/utils/meta/remove_reference.hh b/i/chuck/src/utils/meta/remove_reference.hh new file mode 100644 index 0000000..f12422d --- /dev/null +++ b/i/chuck/src/utils/meta/remove_reference.hh @@ -0,0 +1,44 @@ +#ifndef remove_reference_hh +#define remove_reference_hh +// remove_reference.hh - Remove reference from a type. +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2006 Nicolas Schodet +// +// Robot APB Team/Efrei 2006. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} + +namespace meta { + +template +struct removeReference +{ + typedef T type; +}; + +template +struct removeReference +{ + typedef T type; +}; + +} // namespace meta + +#endif // remove_reference_hh diff --git a/i/chuck/src/utils/meta/test_meta.cc b/i/chuck/src/utils/meta/test_meta.cc new file mode 100644 index 0000000..7c973d2 --- /dev/null +++ b/i/chuck/src/utils/meta/test_meta.cc @@ -0,0 +1,57 @@ +// test_meta.cc +// marvin - programme du robot 2006. {{{ +// +// Copyright (C) 2003-2006 Nicolas Schodet +// +// Robot APB Team/Efrei 2006. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "is_string.hh" +#include "is_equal.hh" +#include "remove_reference.hh" + +#include + +int +main (void) +{ + // Test isString. + std::cout << "isString" << std::endl; + std::cout << " std::string " << meta::isString::value << std::endl; + std::cout << " int " << meta::isString::value << std::endl; + std::cout << " char* " << meta::isString::value << std::endl; + // Test isEqual. + std::cout << "isEqual" << std::endl; + std::cout << " int int " << meta::isEqual::value << std::endl; + std::cout << " int& int " << meta::isEqual::value << std::endl; + std::cout << " int& int& " << meta::isEqual::value << std::endl; + std::cout << " int double " << meta::isEqual::value << std::endl; + // Test removeReference. + std::cout << "removeReference" << std::endl; + std::cout << " int " + << meta::isEqual::type>::value + << std::endl; + std::cout << " int& " + << meta::isEqual::type>::value + << std::endl; + std::cout << " const int& " + << meta::isEqual::type>::value + << std::endl; + return 0; +} diff --git a/i/chuck/src/utils/non_copyable.hh b/i/chuck/src/utils/non_copyable.hh new file mode 100644 index 0000000..e788365 --- /dev/null +++ b/i/chuck/src/utils/non_copyable.hh @@ -0,0 +1,41 @@ +#ifndef non_copyable_hh +#define non_copyable_hh +// non_copyable.hh +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} + +/// Toute classe qui hérite de NonCopyable ne peut pas être copiée. Cela est +/// assuré par le fait que l'operator= et le constructeur de recopie sont +/// privé. +/// Idée originale : Boost.org. +class NonCopyable +{ + public: + NonCopyable (void) { } + private: + NonCopyable (const NonCopyable &); + const NonCopyable &operator= (const NonCopyable &); +}; + +#endif // non_copyable_hh diff --git a/i/chuck/src/utils/signalhandler.hh b/i/chuck/src/utils/signalhandler.hh new file mode 100644 index 0000000..43e0f89 --- /dev/null +++ b/i/chuck/src/utils/signalhandler.hh @@ -0,0 +1,52 @@ +#ifndef signalhandler_hh +#define signalhandler_hh +// signalhandler.hh +// // marvin - programme du robot 2006. {{{ +// // +// // Copyright (C) 2003-2006 Sebastien beaufour +// // +// // Robot APB Team/Efrei 2006. +// // Web: http://assos.efrei.fr/robot/ +// // Email: robot AT efrei DOT fr +// // +// // This program is free software; you can redistribute it and/or modify +// // it under the terms of the GNU General Public License as published by +// // the Free Software Foundation; either version 2 of the License, or +// // (at your option) any later version. +// // +// // This program is distributed in the hope that it will be useful, +// // but WITHOUT ANY WARRANTY; without even the implied warranty of +// // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// // GNU General Public License for more details. +// // +// // You should have received a copy of the GNU General Public License +// // along with this program; if not, write to the Free Software +// // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// // +// // }}} +// +// + +#include +#include +#include +#include "callback.hh" + +template +class SignalHandler +{ + private: + struct sigaction action; + struct sigaction old; + static Callback reset; + static void DefaultReset(); + public: + static void trapsigint(int a); + void bind(Callback r); + SignalHandler(); + ~SignalHandler(); +}; +#include "signalhandler.tcc" + +#endif // end of signalhandler_hh + diff --git a/i/chuck/src/utils/signalhandler.tcc b/i/chuck/src/utils/signalhandler.tcc new file mode 100644 index 0000000..04a1660 --- /dev/null +++ b/i/chuck/src/utils/signalhandler.tcc @@ -0,0 +1,66 @@ +// signalhandler.cc +// // // marvin - programme du robot 2006. {{{ +// // // +// // // Copyright (C) 2003-2006 Sebastien Beaufour +// // // +// // // Robot APB Team/Efrei 2006. +// // // Web: http://assos.efrei.fr/robot/ +// // // Email: robot AT efrei DOT fr +// // // +// // // This program is free software; you can redistribute it and/or modify +// // // it under the terms of the GNU General Public License as published by +// // // the Free Software Foundation; either version 2 of the License, or +// // // (at your option) any later version. +// // // +// // // This program is distributed in the hope that it will be useful, +// // // but WITHOUT ANY WARRANTY; without even the implied warranty of +// // // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// // // GNU General Public License for more details. +// // // +// // // You should have received a copy of the GNU General Public License +// // // along with this program; if not, write to the Free Software +// // // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// // // +// // // }}} +// // +// // +// + +#include "signalhandler.hh" + +/// reset NEED a default reset, so here is a default reset with nothing inside +template void SignalHandler::DefaultReset (void) +{ + // Nothing +} + +// Now we can set the default value to reset +template Callback SignalHandler::reset=SignalHandler::DefaultReset; + +///Static member which will be use by sigaction +template void SignalHandler::trapsigint(int a) +{ + std::cout << "Trap du crtl+c "<< std::endl; + reset(); +} + +///Function to bind to the function to be called when signal il caught +template void SignalHandler::bind(Callback r) +{ + reset=r; + action.sa_handler = trapsigint; + action.sa_flags = SA_ONESHOT; + sigaction(sig,&action,NULL); +} + +/// Constructor, nothing to do +template SignalHandler::SignalHandler() +{ + //nada +} + +///Destructor, put the old sig handler back +template SignalHandler::~SignalHandler() +{ + sigaction(sig,&old,NULL); +} diff --git a/i/chuck/src/utils/test_any.cc b/i/chuck/src/utils/test_any.cc new file mode 100644 index 0000000..85d2319 --- /dev/null +++ b/i/chuck/src/utils/test_any.cc @@ -0,0 +1,50 @@ +// test_any.cc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2004 Nicolas Schodet +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: http://perso.efrei.fr/~schodet/ +// Email: +// }}} +#include "any.hh" + +#include +#include +#include + +int +main (int argc, char **argv) +{ + any a (45), b (std::string ("toto")), c (5.4), d (std::string ("5")); + try + { + // Direct call to output operator. + std::cout << a << ' ' << b << ' ' << c << ' ' << d << std::endl; + // Here, it tries to extract the contained data. + std::cout << any_cast (a) << std::endl; + std::cout << any_cast (b) << std::endl; + std::cout << any_cast (c) << std::endl; + std::cout << any_cast (d) << std::endl; + } + catch (const std::exception &e) + { + std::cout << e.what () << std::endl; + return 1; + } + return 0; +} diff --git a/i/chuck/src/utils/test_bind.cc b/i/chuck/src/utils/test_bind.cc new file mode 100644 index 0000000..b883cbe --- /dev/null +++ b/i/chuck/src/utils/test_bind.cc @@ -0,0 +1,57 @@ +// test_bind.cc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2004 Nicolas Schodet +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: http://perso.efrei.fr/~schodet/ +// Email: +// }}} +#include "bind.hh" + +#include + +void +f (int i) +{ + std::cout << "f " << i << std::endl; +} + +void +g (const char *s) +{ + std::cout << "g " << s << std::endl; +} + +class H +{ + public: + void f (void) + { + std::cout << "h" << std::endl; + } +}; + +int +main (void) +{ + // Create the callback and execute it. + bind (&f, 42) (); + bind (&g, "hello world !") (); + H h; + bind (&H::f, &h) (); +} diff --git a/i/chuck/src/utils/test_callback.cc b/i/chuck/src/utils/test_callback.cc new file mode 100644 index 0000000..2a5b6f0 --- /dev/null +++ b/i/chuck/src/utils/test_callback.cc @@ -0,0 +1,84 @@ +// test_callback.cc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2004 Nicolas Schodet +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: http://perso.efrei.fr/~schodet/ +// Email: +// }}} +#include "callback.hh" + +#include + +void +f (void) +{ + std::cout << " f ()" << std::endl; +} + +int +i (void) +{ + static int v = 42; + std::cout << " i () = " << v << std::endl; + return v++; +} + +struct G +{ + void operator () (void) + { + std::cout << " g ()" << std::endl; + } +}; + +int +main (void) +{ + G g; + Callback cf (f); + Callback cg (g); + Callback ch; + Callback ci (i); + try + { + std::cout << "cf" << std::endl; + cf (); + std::cout << "cg" << std::endl; + cg (); + cf = cg; + cg = f; + std::cout << "cf" << std::endl; + cf (); + std::cout << "cg" << std::endl; + cg (); + std::cout << "cf " << (cf ? "not " : "") << "empty" << std::endl; + std::cout << "ch " << (ch ? "not " : "") << "empty" << std::endl; + std::cout << "ci" << std::endl; + int r = ci (); + std::cout << "ci = " << r << std::endl; + std::cout << "ch" << std::endl; + ch (); + } + catch (const std::exception &e) + { + std::cout << e.what () << std::endl; + return 1; + } + return 0; +} diff --git a/i/chuck/src/utils/test_signalhandler.cc b/i/chuck/src/utils/test_signalhandler.cc new file mode 100644 index 0000000..e25b1d2 --- /dev/null +++ b/i/chuck/src/utils/test_signalhandler.cc @@ -0,0 +1,15 @@ +#include +#include "signalhandler.hh" + +void res() +{ + std::cout << "RESET" << std::endl; +} + +int main() +{ + SignalHandler test; + test.bind(res); + while(1); + return 0; +} -- cgit v1.2.3