summaryrefslogtreecommitdiff
path: root/digital
diff options
context:
space:
mode:
authorNicolas Schodet2012-03-21 00:46:03 +0100
committerNicolas Schodet2012-03-21 18:56:51 +0100
commit1e7c8a8a9811c45091e6c471482086113f059f40 (patch)
treed7faa80dd162799c394ec23925cc53b6dbff008e /digital
parent0feb542a8cf7630a5d442387727414f5251aad83 (diff)
parentdcb79f383269440ec2c5a54b6d7792fbb0110d5a (diff)
Merge branch 'master' into efrei-robotique
Conflicts: digital/mimot/src/dirty/aux.c digital/mimot/src/dirty/aux.h digital/mimot/src/dirty/contacts.h digital/mimot/src/dirty/main.c digital/mimot/src/dirty/models.host.c digital/mimot/src/dirty/twi_proto.c digital/mimot/tools/mimot/init.py
Diffstat (limited to 'digital')
-rw-r--r--digital/ai/src/common/defs.h11
-rw-r--r--digital/ai/src/fsm/fsm.host.c56
-rw-r--r--digital/ai/src/fsm/init.c185
-rw-r--r--digital/ai/src/move/radar.c (renamed from digital/io/src/radar.c)87
-rw-r--r--digital/ai/src/move/radar.h (renamed from digital/io/src/radar.h)28
-rw-r--r--digital/ai/src/twi_master/asserv.c28
-rw-r--r--digital/ai/src/twi_master/asserv.h14
-rw-r--r--digital/ai/src/twi_master/mimot.c82
-rw-r--r--digital/ai/src/twi_master/mimot.h30
-rw-r--r--digital/ai/src/utils/chrono.c7
-rw-r--r--digital/ai/src/utils/chrono.h8
-rw-r--r--digital/ai/tools/marcel.py58
-rw-r--r--digital/ai/tools/robospierre.py60
-rw-r--r--digital/ai/tools/test_simu.py81
-rw-r--r--digital/ai/tools/test_simu_control_marcel.py7
-rw-r--r--digital/ai/tools/test_simu_control_robospierre.py63
-rw-r--r--digital/asserv/src/asserv/main.c21
-rw-r--r--digital/asserv/src/asserv/models.host.c65
-rw-r--r--digital/asserv/src/asserv/models.host.h7
-rw-r--r--digital/asserv/src/asserv/simu.host.c107
-rw-r--r--digital/asserv/src/asserv/simu.host.h3
-rw-r--r--digital/asserv/src/asserv/speed.c20
-rw-r--r--digital/asserv/src/asserv/test_motor_model.c6
-rw-r--r--digital/asserv/src/asserv/traj.c57
-rw-r--r--digital/asserv/src/asserv/traj.h4
-rw-r--r--digital/asserv/src/asserv/twi_proto.c18
-rw-r--r--digital/asserv/tools/asserv/asserv.py19
-rw-r--r--digital/asserv/tools/asserv/init.py26
-rw-r--r--digital/asserv/tools/inter_asserv.py2
-rw-r--r--digital/asserv/tools/test_goto.py33
-rw-r--r--digital/avr/doc/fuses.txt60
-rw-r--r--digital/avr/make/Makefile.avr7
-rw-r--r--digital/avr/modules/adc/adc.avr.c6
-rw-r--r--digital/avr/modules/devices/servo/Makefile.module1
-rw-r--r--digital/avr/modules/devices/servo/README23
-rw-r--r--digital/avr/modules/devices/servo/avrconfig.h33
-rw-r--r--digital/avr/modules/devices/servo/servo.avr.c (renamed from digital/io/src/servo.avr.c)51
-rw-r--r--digital/avr/modules/devices/servo/servo.h (renamed from digital/io/src/servo.h)20
-rw-r--r--digital/avr/modules/devices/servo/servo_pos.c (renamed from digital/io/src/servo_pos.c)4
-rw-r--r--digital/avr/modules/devices/servo/servo_pos.h (renamed from digital/io/src/servo_pos.h)4
-rw-r--r--digital/avr/modules/devices/servo/test/Makefile12
-rw-r--r--digital/avr/modules/devices/servo/test/avrconfig.h91
-rw-r--r--digital/avr/modules/devices/servo/test/test_servo.c86
-rw-r--r--digital/avr/modules/devices/usdist/Makefile.module1
-rw-r--r--digital/avr/modules/devices/usdist/README23
-rw-r--r--digital/avr/modules/devices/usdist/avrconfig.h40
-rw-r--r--digital/avr/modules/devices/usdist/usdist.c (renamed from digital/io/src/usdist.c)19
-rw-r--r--digital/avr/modules/devices/usdist/usdist.h (renamed from digital/io/src/usdist.h)17
-rw-r--r--digital/avr/modules/twi/twi_hard.avr.c1
-rw-r--r--digital/avr/modules/uart/uart.avr.c1
-rw-r--r--digital/beacon/simu/Makefile12
-rw-r--r--digital/beacon/simu/avrconfig.h39
-rw-r--r--digital/beacon/simu/beacon.c106
-rw-r--r--digital/beacon/simu/position.c103
-rw-r--r--digital/beacon/simu/position.h59
-rw-r--r--digital/beacon/simu/simulator.py322
-rw-r--r--digital/cms-intro/pcb/orders/eurocircuits_2011-05-11/cms_intro.GBL2556
-rw-r--r--digital/cms-intro/pcb/orders/eurocircuits_2011-05-11/cms_intro.GBO2103
-rw-r--r--digital/cms-intro/pcb/orders/eurocircuits_2011-05-11/cms_intro.GBS66
-rw-r--r--digital/cms-intro/pcb/orders/eurocircuits_2011-05-11/cms_intro.GTL3546
-rw-r--r--digital/cms-intro/pcb/orders/eurocircuits_2011-05-11/cms_intro.GTO244
-rw-r--r--digital/cms-intro/pcb/orders/eurocircuits_2011-05-11/cms_intro.GTS137
-rw-r--r--digital/cms-intro/pcb/orders/eurocircuits_2011-05-11/cms_intro.TXT76
-rw-r--r--digital/cms-intro/pcb/orders/eurocircuits_2011-05-11/cms_intro.brdbin0 -> 39187 bytes
-rw-r--r--digital/cms-intro/pcb/orders/eurocircuits_2011-05-11/cms_intro.schbin0 -> 127669 bytes
-rw-r--r--digital/dev2/src/usb_gpio/avrconfig.h1
-rw-r--r--digital/dev2/src/usb_serial_isp/avrconfig.h1
-rw-r--r--digital/dev2/src/usb_twi/avrconfig.h1
-rw-r--r--digital/io-hub/src/common/contact.avr.c2
-rw-r--r--digital/io-hub/src/common/contact.host.c2
-rw-r--r--digital/io-hub/src/robospierre/Makefile16
-rw-r--r--digital/io-hub/src/robospierre/avrconfig.h26
-rw-r--r--digital/io-hub/src/robospierre/bot.h147
-rw-r--r--digital/io-hub/src/robospierre/clamp.c876
-rw-r--r--digital/io-hub/src/robospierre/clamp.h50
-rw-r--r--digital/io-hub/src/robospierre/codebar.avr.c64
-rw-r--r--digital/io-hub/src/robospierre/codebar.h36
-rw-r--r--digital/io-hub/src/robospierre/codebar.host.c56
-rw-r--r--digital/io-hub/src/robospierre/contact_defs.h24
-rw-r--r--digital/io-hub/src/robospierre/element.c828
-rw-r--r--digital/io-hub/src/robospierre/element.h213
-rw-r--r--digital/io-hub/src/robospierre/init_defs.h50
-rw-r--r--digital/io-hub/src/robospierre/logistic.c622
-rw-r--r--digital/io-hub/src/robospierre/logistic.h143
-rw-r--r--digital/io-hub/src/robospierre/main.c173
-rw-r--r--digital/io-hub/src/robospierre/main.h31
-rw-r--r--digital/io-hub/src/robospierre/move.c541
-rw-r--r--digital/io-hub/src/robospierre/move.h63
-rw-r--r--digital/io-hub/src/robospierre/path.c621
-rw-r--r--digital/io-hub/src/robospierre/path.h78
-rw-r--r--digital/io-hub/src/robospierre/pawn_sensor.c222
-rw-r--r--digital/io-hub/src/robospierre/pawn_sensor.h45
-rw-r--r--digital/io-hub/src/robospierre/playground_2011.h33
-rw-r--r--digital/io-hub/src/robospierre/radar_defs.c46
-rw-r--r--digital/io-hub/src/robospierre/radar_defs.h41
-rw-r--r--digital/io-hub/src/robospierre/simu.host.c45
-rw-r--r--digital/io-hub/src/robospierre/simu.host.h12
-rw-r--r--digital/io-hub/src/robospierre/test_element.c376
-rw-r--r--digital/io-hub/src/robospierre/top.c476
-rw-r--r--digital/io-hub/tools/io_hub/io_hub.py22
-rw-r--r--digital/io-hub/tools/io_hub/mex.py106
-rw-r--r--digital/io-serial/src/codebar/Makefile16
-rw-r--r--digital/io-serial/src/codebar/avrconfig.h100
-rw-r--r--digital/io-serial/src/codebar/codebar.c159
-rw-r--r--digital/io/src/Makefile9
-rw-r--r--digital/io/src/avrconfig.h17
-rw-r--r--digital/io/src/eeprom.avr.c4
-rw-r--r--digital/io/src/main.c6
-rw-r--r--digital/io/src/move.c6
-rw-r--r--digital/io/src/radar_defs.c54
-rw-r--r--digital/io/src/radar_defs.h41
-rw-r--r--digital/io/src/simu.host.c26
-rw-r--r--digital/mimot/src/dirty/pwm.h5
-rw-r--r--digital/mimot/src/dirty/pwm_ocr.avr.c8
-rw-r--r--digital/mimot/src/dirty/speed.c20
115 files changed, 17187 insertions, 435 deletions
diff --git a/digital/ai/src/common/defs.h b/digital/ai/src/common/defs.h
index f16e9e52..12c47584 100644
--- a/digital/ai/src/common/defs.h
+++ b/digital/ai/src/common/defs.h
@@ -43,11 +43,18 @@ typedef struct position_t position_t;
/** Convert degrees to an angle usable in position_t. */
#define POSITION_A_DEG(a) G_ANGLE_UF016_DEG (a)
+/** No particular direction. */
+#define DIRECTION_NONE 0
+/** Forward direction, along the robot X axis. */
+#define DIRECTION_FORWARD 1
+/** Backward, opposite the robot X axis. */
+#define DIRECTION_BACKWARD 2
+
/** Team color, determine the start zone side. */
enum team_color_e
{
- TEAM_COLOR_LEFT = 0,
- TEAM_COLOR_RIGHT = 1
+ TEAM_COLOR_RIGHT = 0,
+ TEAM_COLOR_LEFT = 1
};
/** Current team color, to be read at start up. */
diff --git a/digital/ai/src/fsm/fsm.host.c b/digital/ai/src/fsm/fsm.host.c
index bf8b761d..50336722 100644
--- a/digital/ai/src/fsm/fsm.host.c
+++ b/digital/ai/src/fsm/fsm.host.c
@@ -1056,11 +1056,18 @@ fsm_build_gen_avr_h (fsm_build_t *fsm, uint embedded_strings)
/* Gen function table. */
fprintf (f, "typedef fsm_%s_branch_t (*fsm_%s_func_t)(void);\n", fsm->name,
fsm->name);
- fprintf (f, "extern const fsm_%s_func_t PROGMEM fsm_%s_trans_table[%u][%u];\n\n",
+ fprintf (f, "extern const fsm_%s_func_t PROGMEM fsm_%s_trans_table[%u][%u];\n",
fsm->name,
fsm->name,
fsm->event_nb,
fsm->state_nb);
+ /* Gen read function for trans table. */
+ fprintf (f, "fsm_%s_func_t fsm_%s_read_trans (fsm_%s_event_t event, "
+ "fsm_%s_state_t state);\n\n",
+ fsm->name,
+ fsm->name,
+ fsm->name,
+ fsm->name);
/* Gen active states array. */
fprintf (f, "extern fsm_%s_state_t fsm_%s_active_states[%u];\n\n",
@@ -1137,6 +1144,7 @@ fsm_build_gen_avr_c (fsm_build_t *fsm, uint embedded_strings)
/* Introduction. */
fprintf (f, "/* This file has been generated, do not edit. */\n\n");
fprintf (f, "#include \"fsm_%s_gen.h\"\n\n", fsm->name);
+ fprintf (f, "#include \"modules/proto/proto.h\"\n\n");
/* Gen state strings. */
if (embedded_strings)
@@ -1280,6 +1288,19 @@ fsm_build_gen_avr_c (fsm_build_t *fsm, uint embedded_strings)
}
fprintf (f, "};\n\n");
+ /* Gen read function for trans table. */
+ fprintf (f, "fsm_%s_func_t fsm_%s_read_trans (fsm_%s_event_t event, "
+ "fsm_%s_state_t state)\n{\n",
+ fsm->name,
+ fsm->name,
+ fsm->name,
+ fsm->name);
+ fprintf (f, "\treturn (fsm_%s_func_t) pgm_read_word "
+ "(&fsm_%s_trans_table[event][state]);\n",
+ fsm->name,
+ fsm->name);
+ fprintf (f, "}\n\n");
+
/* Gen active states array. */
fprintf (f, "fsm_%s_state_t fsm_%s_active_states[%u];\n\n",
fsm->name,
@@ -1324,19 +1345,23 @@ fsm_build_gen_avr_c (fsm_build_t *fsm, uint embedded_strings)
fprintf (f, "\tint handled = 0;\n");
fprintf (f, "\tfor (i = 0; i < fsm_%s_max_active_states; i++)\n\t{\n",
fsm->name);
- fprintf (f, "\t\tif (fsm_%s_trans_table[e][fsm_%s_active_states[i]])\n",
+ fprintf (f, "\t\tif (fsm_%s_read_trans (e, fsm_%s_active_states[i]))\n",
fsm->name,
fsm->name);
fprintf (f, "\t\t{\n");
- fprintf (f, "\t\t\tfsm_%s_active_states[i] = \
- fsm_%s_trans_table[e][fsm_%s_active_states[i]]();\n",
- fsm->name,
- fsm->name,
+ fprintf (f, "\t\t\tproto_send2b ('F', fsm_%s_active_states[i], e);\n",
fsm->name);
+ fprintf (f, "\t\t\tfsm_%s_active_states[i] = fsm_%s_read_trans (e, "
+ "fsm_%s_active_states[i])();\n",
+ fsm->name,
+ fsm->name,
+ fsm->name);
fprintf (f, "\t\t\thandled = 1;\n");
if (fsm->timeouts != NULL)
{
- fprintf (f, "\t\t\tfsm_%s_timeout_counters[i] = fsm_%s_timeout_values[e];\n",
+ fprintf (f, "\t\t\tfsm_%s_timeout_counters[i] = "
+ "fsm_%s_timeout_values[fsm_%s_active_states[i]];\n",
+ fsm->name,
fsm->name,
fsm->name);
}
@@ -1352,9 +1377,9 @@ fsm_build_gen_avr_c (fsm_build_t *fsm, uint embedded_strings)
fprintf (f, "\tuint16_t i;\n");
fprintf (f, "\tfor (i = 0; i < fsm_%s_max_active_states; i++)\n",
fsm->name);
- fprintf (f, "\t\tif (fsm_%s_trans_table[e][fsm_%s_active_states[i]])\n",
- fsm->name,
- fsm->name);
+ fprintf (f, "\t\tif (fsm_%s_read_trans (e, fsm_%s_active_states[i]))\n",
+ fsm->name,
+ fsm->name);
fprintf (f, "\t\t\treturn 1;\n");
fprintf (f, "\treturn 0;\n");
fprintf (f, "}\n\n");
@@ -1431,18 +1456,19 @@ fsm_build_gen_avr_c (fsm_build_t *fsm, uint embedded_strings)
fprintf (f, "\tint out = 0;\n");
fprintf (f, "\tfor (i = 0; i < fsm_%s_max_active_states; i++)\n\t{\n",
fsm->name);
- fprintf (f, "\t\tif (fsm_%s_timeout_counters[i] > 0)\n",
+ fprintf (f, "\t\tif (fsm_%s_timeout_counters[i] > 0)\n\t\t{\n",
fsm->name);
fprintf (f, "\t\t\tfsm_%s_timeout_counters[i]--;\n",
fsm->name);
- fprintf (f, "\t\tif (fsm_%s_timeout_counters[i] == 0)\n\t\t{\n",
+ fprintf (f, "\t\t\tif (fsm_%s_timeout_counters[i] == 0)\n\t\t\t{\n",
fsm->name);
- fprintf (f, "\t\t\tfsm_%s_handle (fsm_%s_timeout_events[fsm_%s_active_states[i]]);\n",
+ fprintf (f, "\t\t\t\tfsm_%s_handle (fsm_%s_timeout_events[fsm_%s_active_states[i]]);\n",
fsm->name,
fsm->name,
fsm->name);
- fprintf (f, "\t\t\tout = 1;\n");
- fprintf (f, "\t\t}\n\n");
+ fprintf (f, "\t\t\t\tout = 1;\n");
+ fprintf (f, "\t\t\t}\n");
+ fprintf (f, "\t\t}\n");
fprintf (f, "\t}\n");
fprintf (f, "\treturn out;\n");
fprintf (f, "}\n\n");
diff --git a/digital/ai/src/fsm/init.c b/digital/ai/src/fsm/init.c
new file mode 100644
index 00000000..51ba31ab
--- /dev/null
+++ b/digital/ai/src/fsm/init.c
@@ -0,0 +1,185 @@
+/* init.c */
+/* robospierre - Eurobot 2011 AI. {{{
+ *
+ * Copyright (C) 2011 Nicolas Schodet
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * 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 "common.h"
+
+#include "asserv.h"
+#include "contact.h"
+#include "chrono.h"
+
+#define FSM_NAME AI
+#include "fsm.h"
+#include "fsm_queue.h"
+
+#include "bot.h"
+#include "init_defs.h"
+
+/*
+ * Initialise robot position with a calibration procedure.
+ */
+
+FSM_STATES (
+ /* Initial state, waiting for jack. */
+ INIT_START,
+ /* After first jack insertion, waiting for removal to initialise actuators. */
+ INIT_WAITING_FIRST_JACK_OUT,
+ /* Initialising actuators, then waiting for second jack insertion. */
+ INIT_INITIALISING_ACTUATORS,
+ /* After second jack insertion, waiting the operator remove its
+ * hand. */
+ INIT_WAITING_HANDS_OUT,
+ /* Finding the first wall. */
+ INIT_FINDING_FIRST_WALL,
+ /* Going away from the wall. */
+ INIT_GOING_AWAY_FIRST_WALL,
+ /* Turning to face the other wall. */
+ INIT_FACING_SECOND_WALL,
+ /* Waiting after rotation for robot to stabilize. */
+ INIT_WAITING_AFTER_FACING_SECOND_WALL,
+ /* Finding the second wall. */
+ INIT_FINDING_SECOND_WALL,
+ /* Going away from the wall. */
+ INIT_GOING_AWAY_SECOND_WALL,
+#ifdef INIT_START_POSITION_ANGLE
+ /* Facing the start position. */
+ INIT_FACING_START_POSITION,
+#endif
+ /* Going to start position. */
+ INIT_GOING_TO_START_POSITION,
+ /* Waiting for the round start (waiting for the jack). */
+ INIT_WAITING_SECOND_JACK_OUT,
+ /* Initialisation finished, nothing else to do. */
+ INIT_FINISHED)
+
+FSM_EVENTS (
+ /* Jack is inserted. */
+ jack_inserted,
+ /* Jack is removed. */
+ jack_removed,
+ /* Sent to initialise actuators. */
+ init_actuators,
+ /* Sent to start round. */
+ init_start_round)
+
+FSM_START_WITH (INIT_START)
+
+FSM_TRANS (INIT_START, jack_inserted, INIT_WAITING_FIRST_JACK_OUT)
+{
+ return FSM_NEXT (INIT_START, jack_inserted);
+}
+
+FSM_TRANS (INIT_WAITING_FIRST_JACK_OUT, jack_removed,
+ INIT_INITIALISING_ACTUATORS)
+{
+ fsm_queue_post_event (FSM_EVENT (AI, init_actuators));
+ return FSM_NEXT (INIT_WAITING_FIRST_JACK_OUT, jack_removed);
+}
+
+FSM_TRANS (INIT_INITIALISING_ACTUATORS, jack_inserted, INIT_WAITING_HANDS_OUT)
+{
+ team_color = contact_get_color ();
+ return FSM_NEXT (INIT_INITIALISING_ACTUATORS, jack_inserted);
+}
+
+FSM_TRANS_TIMEOUT (INIT_WAITING_HANDS_OUT, 225, INIT_FINDING_FIRST_WALL)
+{
+ asserv_set_speed (BOT_SPEED_INIT);
+ asserv_push_the_wall (INIT_FIRST_WALL_PUSH);
+ return FSM_NEXT_TIMEOUT (INIT_WAITING_HANDS_OUT);
+}
+
+FSM_TRANS (INIT_FINDING_FIRST_WALL, robot_move_success,
+ INIT_GOING_AWAY_FIRST_WALL)
+{
+ asserv_move_linearly (INIT_FIRST_WALL_AWAY);
+ return FSM_NEXT (INIT_FINDING_FIRST_WALL, robot_move_success);
+}
+
+FSM_TRANS (INIT_GOING_AWAY_FIRST_WALL, robot_move_success,
+ INIT_FACING_SECOND_WALL)
+{
+ asserv_goto_angle (INIT_SECOND_WALL_ANGLE);
+ return FSM_NEXT (INIT_GOING_AWAY_FIRST_WALL, robot_move_success);
+}
+
+FSM_TRANS (INIT_FACING_SECOND_WALL, robot_move_success,
+ INIT_WAITING_AFTER_FACING_SECOND_WALL)
+{
+ return FSM_NEXT (INIT_FACING_SECOND_WALL, robot_move_success);
+}
+
+FSM_TRANS_TIMEOUT (INIT_WAITING_AFTER_FACING_SECOND_WALL, 225 / 2,
+ INIT_FINDING_SECOND_WALL)
+{
+ asserv_push_the_wall (INIT_SECOND_WALL_PUSH);
+ return FSM_NEXT_TIMEOUT (INIT_WAITING_AFTER_FACING_SECOND_WALL);
+}
+
+FSM_TRANS (INIT_FINDING_SECOND_WALL, robot_move_success,
+ INIT_GOING_AWAY_SECOND_WALL)
+{
+ asserv_move_linearly (INIT_SECOND_WALL_AWAY);
+ return FSM_NEXT (INIT_FINDING_SECOND_WALL, robot_move_success);
+}
+
+#ifdef INIT_START_POSITION_ANGLE
+FSM_TRANS (INIT_GOING_AWAY_SECOND_WALL, robot_move_success,
+ INIT_FACING_START_POSITION)
+{
+ asserv_goto_angle (INIT_START_POSITION_ANGLE);
+ return FSM_NEXT (INIT_GOING_AWAY_SECOND_WALL, robot_move_success);
+}
+
+FSM_TRANS (INIT_FACING_START_POSITION, robot_move_success,
+ INIT_GOING_TO_START_POSITION)
+{
+ asserv_goto_xya (INIT_START_POSITION);
+ return FSM_NEXT (INIT_FACING_START_POSITION, robot_move_success);
+}
+
+#else
+
+FSM_TRANS (INIT_GOING_AWAY_SECOND_WALL, robot_move_success,
+ INIT_GOING_TO_START_POSITION)
+{
+ asserv_goto_xya (INIT_START_POSITION);
+ return FSM_NEXT (INIT_GOING_AWAY_SECOND_WALL, robot_move_success);
+}
+
+#endif
+
+FSM_TRANS (INIT_GOING_TO_START_POSITION, robot_move_success,
+ INIT_WAITING_SECOND_JACK_OUT)
+{
+ asserv_set_speed (BOT_SPEED_NORMAL);
+ return FSM_NEXT (INIT_GOING_TO_START_POSITION, robot_move_success);
+}
+
+FSM_TRANS (INIT_WAITING_SECOND_JACK_OUT, jack_removed, INIT_FINISHED)
+{
+ chrono_init ();
+ fsm_queue_post_event (FSM_EVENT (AI, init_start_round));
+ return FSM_NEXT (INIT_WAITING_SECOND_JACK_OUT, jack_removed);
+}
+
diff --git a/digital/io/src/radar.c b/digital/ai/src/move/radar.c
index 1ac982c7..a572afba 100644
--- a/digital/io/src/radar.c
+++ b/digital/ai/src/move/radar.c
@@ -25,55 +25,47 @@
#include "common.h"
#include "radar.h"
-#include "playground_2010.h"
#include "bot.h"
-#include "usdist.h"
#include "modules/math/geometry/geometry.h"
#include "modules/math/geometry/distance.h"
#include "modules/utils/utils.h"
-/** Margin to be considered inside the playground. An obstacle can not be
- * exactly at the playground edge. */
-#define RADAR_MARGIN_MM 150
-
/** Maximum distance for a sensor reading to be ignored if another sensor is
* nearer. */
#define RADAR_FAR_MM 250
-/** Describe a radar sensor. */
-struct radar_sensor_t
-{
- /** Distance updated by another module. */
- uint16_t *dist_mm;
- /** Position relative to the robot center. */
- vect_t pos;
- /** Angle relative to the robot X axis. */
- uint16_t a;
-};
-
/** Define radar configuration. */
-struct radar_sensor_t radar_sensors[] = {
-#define RADAR_SENSOR_FRONT 0
- { &usdist_mm[0], { 30 - 20, 0 }, G_ANGLE_UF016_DEG (0) },
-#define RADAR_SENSOR_LEFT 1
- { &usdist_mm[1], { 20 - 20, 20 }, G_ANGLE_UF016_DEG (30) },
-#define RADAR_SENSOR_RIGHT 2
- { &usdist_mm[2], { 20 - 20, -20 }, G_ANGLE_UF016_DEG (-30) },
-#define RADAR_SENSOR_BACK 3
- { &usdist_mm[3], { -30 - 20, 0 }, G_ANGLE_UF016_DEG (180) },
-};
+extern struct radar_sensor_t radar_sensors[RADAR_SENSOR_NB];
-/** Define exclusion area (considered as invalid point). */
+uint8_t
+radar_valid (vect_t p);
+
+/** Compute the center position from several radars sensors, return 1 if
+ * any. */
static uint8_t
-radar_valid (vect_t p)
+radar_hit_center (uint8_t valid[], vect_t hit[], uint8_t sensor_nb,
+ vect_t *obs_pos)
{
- return p.x >= RADAR_MARGIN_MM && p.x < PG_WIDTH - RADAR_MARGIN_MM
- && p.y >= RADAR_MARGIN_MM && p.y < PG_LENGTH - RADAR_MARGIN_MM
- /* Ignore points on slope, no margin for the slope start. */
- && (p.x < PG_WIDTH / 2 - PG_SLOPE_WIDTH / 2
- || p.x >= PG_WIDTH / 2 + PG_SLOPE_WIDTH / 2
- || p.y < PG_LENGTH - PG_SLOPE_LENGTH - RADAR_MARGIN_MM / 2);
+ uint8_t i, hit_nb = 0;
+ vect_t hit_center = { 0, 0 };
+ for (i = 0; i < sensor_nb; i++)
+ {
+ if (valid[i])
+ {
+ vect_add (&hit_center, &hit[i]);
+ hit_nb++;
+ }
+ }
+ if (hit_nb > 1)
+ vect_scale_f824 (&hit_center, 0x1000000l / hit_nb);
+ if (hit_nb)
+ {
+ *obs_pos = hit_center;
+ return 1;
+ }
+ else
+ return 0;
}
uint8_t
@@ -82,8 +74,6 @@ radar_update (const position_t *robot_pos, vect_t *obs_pos)
uint8_t i, j;
vect_t ray;
uint8_t obs_nb = 0;
- uint8_t front_nb;
- vect_t front_center;
/* Compute hit points for each sensor and eliminate invalid ones. */
vect_t hit[UTILS_COUNT (radar_sensors)];
uint8_t valid[UTILS_COUNT (radar_sensors)];
@@ -122,23 +112,12 @@ radar_update (const position_t *robot_pos, vect_t *obs_pos)
}
}
/* Specific treatment about sensor topology. */
- if (valid[RADAR_SENSOR_BACK])
- obs_pos[obs_nb++] = hit[RADAR_SENSOR_BACK];
- front_nb = 0;
- front_center.x = 0; front_center.y = 0;
- for (i = RADAR_SENSOR_FRONT; i < RADAR_SENSOR_BACK; i++)
- {
- if (valid[i])
- {
- vect_add (&front_center, &hit[i]);
- front_nb++;
- }
- }
- if (front_nb)
- {
- vect_scale_f824 (&front_center, 0x1000000l / front_nb);
- obs_pos[obs_nb++] = front_center;
- }
+ obs_nb += radar_hit_center (valid + RADAR_SENSOR_FRONT_FIRST,
+ hit + RADAR_SENSOR_FRONT_FIRST,
+ RADAR_SENSOR_FRONT_NB, &obs_pos[obs_nb]);
+ obs_nb += radar_hit_center (valid + RADAR_SENSOR_BACK_FIRST,
+ hit + RADAR_SENSOR_BACK_FIRST,
+ RADAR_SENSOR_BACK_NB, &obs_pos[obs_nb]);
/* Done. */
return obs_nb;
}
diff --git a/digital/io/src/radar.h b/digital/ai/src/move/radar.h
index b4611ec7..2e37d11d 100644
--- a/digital/io/src/radar.h
+++ b/digital/ai/src/move/radar.h
@@ -37,15 +37,15 @@
/** Estimated obstacle edge radius. As the sensors detect obstacle edge, this is
* added to position obstacle center. */
-#define RADAR_OBSTACLE_EDGE_RADIUS_MM 40
+#undef RADAR_OBSTACLE_EDGE_RADIUS_MM
/** Estimated obstacle radius. The obstacle may be larger than at the
* detected edge. */
-#define RADAR_OBSTACLE_RADIUS_MM 150
+#undef RADAR_OBSTACLE_RADIUS_MM
/** Stop distance. Distance under which an obstacle is considered harmful when
* moving. */
-#define RADAR_STOP_MM 350
+#undef RADAR_STOP_MM
/** Clearance distance. Distance over which an obstacle should be to the side
* when moving.
@@ -59,10 +59,28 @@
* this reduce the rectangle length.
*
* If the destination is really near (< RADAR_EPSILON_MM), ignore all this. */
-#define RADAR_CLEARANCE_MM 100
+#undef RADAR_CLEARANCE_MM
/** Destination distance near enough so that obstacles could be ignored. */
-#define RADAR_EPSILON_MM 70
+#undef RADAR_EPSILON_MM
+
+/* All this in another file. */
+#include "radar_defs.h"
+
+/** Margin to be considered inside the playground. An obstacle can not be
+ * exactly at the playground edge. */
+#define RADAR_MARGIN_MM 150
+
+/** Describe a radar sensor. */
+struct radar_sensor_t
+{
+ /** Distance updated by another module. */
+ uint16_t *dist_mm;
+ /** Position relative to the robot center. */
+ vect_t pos;
+ /** Angle relative to the robot X axis. */
+ uint16_t a;
+};
/** Update radar view. Return the number of obstacles found. Obstacles
* positions are returned in obs_pos. */
diff --git a/digital/ai/src/twi_master/asserv.c b/digital/ai/src/twi_master/asserv.c
index d066737b..839b1d23 100644
--- a/digital/ai/src/twi_master/asserv.c
+++ b/digital/ai/src/twi_master/asserv.c
@@ -202,12 +202,12 @@ asserv_get_moving_direction (void)
{
/* Foward move? */
if (asserv_status.status & _BV (asserv_status_flag_move_forward))
- return 1;
+ return DIRECTION_FORWARD;
/* Backward move? */
if (asserv_status.status & _BV (asserv_status_flag_move_backward))
- return 2;
+ return DIRECTION_BACKWARD;
/* Not moving */
- return 0;
+ return DIRECTION_NONE;
}
uint8_t
@@ -301,6 +301,28 @@ asserv_go_to_the_wall (uint8_t backward)
}
void
+asserv_push_the_wall (uint8_t backward, uint32_t init_x, uint32_t init_y,
+ uint16_t init_a)
+{
+ if (init_x != (uint32_t) -1)
+ init_x = fixed_mul_f824 (init_x, asserv_scale_inv);
+ if (init_y != (uint32_t) -1)
+ init_y = fixed_mul_f824 (init_y, asserv_scale_inv);
+ uint8_t *buffer = twi_master_get_buffer (ASSERV_SLAVE);
+ buffer[0] = 'G';
+ buffer[1] = backward;
+ buffer[2] = v32_to_v8 (init_x, 2);
+ buffer[3] = v32_to_v8 (init_x, 1);
+ buffer[4] = v32_to_v8 (init_x, 0);
+ buffer[5] = v32_to_v8 (init_y, 2);
+ buffer[6] = v32_to_v8 (init_y, 1);
+ buffer[7] = v32_to_v8 (init_y, 0);
+ buffer[8] = v16_to_v8 (init_a, 1);
+ buffer[9] = v16_to_v8 (init_a, 0);
+ twi_master_send_buffer (10);
+}
+
+void
asserv_move_motor0_absolute (uint16_t position, uint8_t speed)
{
uint8_t *buffer = twi_master_get_buffer (ASSERV_SLAVE);
diff --git a/digital/ai/src/twi_master/asserv.h b/digital/ai/src/twi_master/asserv.h
index 0d29ba96..c9a52a11 100644
--- a/digital/ai/src/twi_master/asserv.h
+++ b/digital/ai/src/twi_master/asserv.h
@@ -121,16 +121,16 @@ asserv_get_motor1_position (void);
/**
* Are we moving forward/backward?
* @return
- * - 0 we are not moving;
- * - 1 we are moving forward;
- * - 2 we are moving backward.
+ * - DIRECTION_NONE we are not moving;
+ * - DIRECTION_FORWARD we are moving forward;
+ * - DIRECTION_BACKWARD we are moving backward.
*/
uint8_t
asserv_get_moving_direction (void);
/**
* Get the last moving direction of the bot.
- * @return 1 is forward, 2 is backward.
+ * @return DIRECTION_FORWARD or DIRECTION_BACKWARD.
*/
uint8_t
asserv_get_last_moving_direction (void);
@@ -198,6 +198,12 @@ asserv_goto_xya (uint32_t x, uint32_t y, int16_t a, uint8_t backward);
void
asserv_go_to_the_wall (uint8_t backward);
+/** Push the wall and initialise position. Use -1 for coordinates to keep
+ * unchanged. */
+void
+asserv_push_the_wall (uint8_t backward, uint32_t init_x, uint32_t init_y,
+ uint16_t init_a);
+
/**
* Move the motor0.
* Motor0 class command.
diff --git a/digital/ai/src/twi_master/mimot.c b/digital/ai/src/twi_master/mimot.c
index af6ff5f9..8df84538 100644
--- a/digital/ai/src/twi_master/mimot.c
+++ b/digital/ai/src/twi_master/mimot.c
@@ -97,6 +97,12 @@ mimot_motor1_cmd_status (void)
return none;
}
+uint8_t
+mimot_get_input (void)
+{
+ return mimot_status.input_port;
+}
+
uint16_t
mimot_get_motor0_position (void)
{
@@ -118,6 +124,30 @@ mimot_reset (void)
}
void
+mimot_set_motor0_position (uint16_t position)
+{
+ uint8_t *buffer = twi_master_get_buffer (MIMOT_SLAVE);
+ buffer[0] = 'p';
+ buffer[1] = 'Y';
+ buffer[2] = 0;
+ buffer[3] = v16_to_v8 (position, 1);
+ buffer[4] = v16_to_v8 (position, 0);
+ twi_master_send_buffer (5);
+}
+
+void
+mimot_set_motor1_position (uint16_t position)
+{
+ uint8_t *buffer = twi_master_get_buffer (MIMOT_SLAVE);
+ buffer[0] = 'p';
+ buffer[1] = 'Y';
+ buffer[2] = 1;
+ buffer[3] = v16_to_v8 (position, 1);
+ buffer[4] = v16_to_v8 (position, 0);
+ twi_master_send_buffer (5);
+}
+
+void
mimot_move_motor0_absolute (uint16_t position, uint8_t speed)
{
uint8_t *buffer = twi_master_get_buffer (MIMOT_SLAVE);
@@ -142,19 +172,41 @@ mimot_move_motor1_absolute (uint16_t position, uint8_t speed)
void
mimot_motor0_zero_position (int8_t speed)
{
+ mimot_motor0_find_zero (speed, 0, 0);
+}
+
+void
+mimot_motor1_zero_position (int8_t speed)
+{
+ mimot_motor1_find_zero (speed, 0, 0);
+}
+
+void
+mimot_motor0_find_zero (int8_t speed, uint8_t use_switch,
+ uint16_t reset_position)
+{
uint8_t *buffer = twi_master_get_buffer (MIMOT_SLAVE);
buffer[0] = 'B';
- buffer[1] = speed;
- twi_master_send_buffer (2);
+ buffer[1] = 0;
+ buffer[2] = speed;
+ buffer[3] = use_switch;
+ buffer[4] = v16_to_v8 (reset_position, 1);
+ buffer[5] = v16_to_v8 (reset_position, 0);
+ twi_master_send_buffer (6);
}
void
-mimot_motor1_zero_position (int8_t speed)
+mimot_motor1_find_zero (int8_t speed, uint8_t use_switch,
+ uint16_t reset_position)
{
uint8_t *buffer = twi_master_get_buffer (MIMOT_SLAVE);
- buffer[0] = 'C';
- buffer[1] = speed;
- twi_master_send_buffer (2);
+ buffer[0] = 'B';
+ buffer[1] = 1;
+ buffer[2] = speed;
+ buffer[3] = use_switch;
+ buffer[4] = v16_to_v8 (reset_position, 1);
+ buffer[5] = v16_to_v8 (reset_position, 0);
+ twi_master_send_buffer (6);
}
void
@@ -181,3 +233,21 @@ mimot_motor1_clamp (int8_t speed, int16_t pwm)
twi_master_send_buffer (5);
}
+void
+mimot_motor0_free (void)
+{
+ uint8_t *buffer = twi_master_get_buffer (MIMOT_SLAVE);
+ buffer[0] = 'w';
+ buffer[1] = 0;
+ twi_master_send_buffer (2);
+}
+
+void
+mimot_motor1_free (void)
+{
+ uint8_t *buffer = twi_master_get_buffer (MIMOT_SLAVE);
+ buffer[0] = 'w';
+ buffer[1] = 1;
+ twi_master_send_buffer (2);
+}
+
diff --git a/digital/ai/src/twi_master/mimot.h b/digital/ai/src/twi_master/mimot.h
index 60811c10..c9de7090 100644
--- a/digital/ai/src/twi_master/mimot.h
+++ b/digital/ai/src/twi_master/mimot.h
@@ -56,6 +56,10 @@ mimot_motor0_cmd_status (void);
asserv_status_e
mimot_motor1_cmd_status (void);
+/** Return input port state. */
+uint8_t
+mimot_get_input (void);
+
/** Get motor0 position in steps. */
uint16_t
mimot_get_motor0_position (void);
@@ -68,6 +72,14 @@ mimot_get_motor1_position (void);
void
mimot_reset (void);
+/** Set motor0 position in steps. */
+void
+mimot_set_motor0_position (uint16_t position);
+
+/** Set motor1 position in steps. */
+void
+mimot_set_motor1_position (uint16_t position);
+
/** Move motor0 to absolute position in steps. */
void
mimot_move_motor0_absolute (uint16_t position, uint8_t speed);
@@ -84,6 +96,16 @@ mimot_motor0_zero_position (int8_t speed);
void
mimot_motor1_zero_position (int8_t speed);
+/** Find zero position. */
+void
+mimot_motor0_find_zero (int8_t speed, uint8_t use_switch,
+ uint16_t reset_position);
+
+/** Find zero position. */
+void
+mimot_motor1_find_zero (int8_t speed, uint8_t use_switch,
+ uint16_t reset_position);
+
/** Clamp motor0. */
void
mimot_motor0_clamp (int8_t speed, int16_t pwm);
@@ -92,4 +114,12 @@ mimot_motor0_clamp (int8_t speed, int16_t pwm);
void
mimot_motor1_clamp (int8_t speed, int16_t pwm);
+/** Free motor0. */
+void
+mimot_motor0_free (void);
+
+/** Free motor1. */
+void
+mimot_motor1_free (void);
+
#endif /* mimot_h */
diff --git a/digital/ai/src/utils/chrono.c b/digital/ai/src/utils/chrono.c
index a1212e19..85851547 100644
--- a/digital/ai/src/utils/chrono.c
+++ b/digital/ai/src/utils/chrono.c
@@ -148,3 +148,10 @@ chrono_end_match (uint8_t block)
;
#endif
}
+
+void
+chrono_set_timer (uint32_t elapsed_time)
+{
+ if (chrono_enabled_)
+ chrono_ov_count_ = elapsed_time / TIMER_PERIOD_MS;
+}
diff --git a/digital/ai/src/utils/chrono.h b/digital/ai/src/utils/chrono.h
index 38bf3d61..580529cf 100644
--- a/digital/ai/src/utils/chrono.h
+++ b/digital/ai/src/utils/chrono.h
@@ -96,4 +96,12 @@ chrono_remaining_time (void);
void
chrono_end_match (uint8_t block);
+/**
+ * Set timer at desired value.
+ * This function should be used for tests purpose only.
+ * @param elapsed_time elapsed time since beginning.
+ */
+void
+chrono_set_timer (uint32_t elapsed_time);
+
#endif /* chrono_h */
diff --git a/digital/ai/tools/marcel.py b/digital/ai/tools/marcel.py
index 08314ca3..001eca5e 100644
--- a/digital/ai/tools/marcel.py
+++ b/digital/ai/tools/marcel.py
@@ -1,10 +1,3 @@
-import simu.model.table_eurobot2010
-import simu.view.table_eurobot2010
-
-import simu.robots.marcel.link.bag
-import simu.robots.marcel.model.bag
-import simu.robots.marcel.view.bag
-
import asserv
import asserv.init
import mimot
@@ -16,24 +9,37 @@ from proto.popen_io import PopenIO
import math
class Robot:
+ """Marcel robot instance."""
+
+ import simu.model.table_eurobot2010 as table_model
+ import simu.view.table_eurobot2010 as table_view
+
+ import simu.robots.marcel.link.bag as robot_link
+ import simu.robots.marcel.model.bag as robot_model
+ import simu.robots.marcel.view.bag as robot_view
+
+ robot_start_pos = {
+ False: (300, 2100 - 305, math.radians (-270)),
+ True: (3000 - 300, 2100 - 305, math.radians (-270))
+ }
+
+ client_nb = 3
- def __init__ (self, proto_time):
- self.table_model = simu.model.table_eurobot2010
- self.table_view = simu.view.table_eurobot2010
- self.robot_link = simu.robots.marcel.link.bag
- self.robot_model = simu.robots.marcel.model.bag
- self.robot_view = simu.robots.marcel.view.bag
- asserv_cmd = ('../../asserv/src/asserv/asserv.host', '-m9', 'marcel')
- mimot_cmd = ('../../mimot/src/dirty/dirty.host', '-m9', 'marcel')
- io_cmd = ('../../io/src/io.host')
- self.asserv = asserv.Proto (PopenIO (asserv_cmd), proto_time,
- **asserv.init.host['marcel'])
- self.mimot = mimot.Proto (PopenIO (mimot_cmd), proto_time,
- **mimot.init.host['marcel'])
- self.io = io.Proto (PopenIO (io_cmd), proto_time,
- **io.init.host['marcel'])
- self.robot_start_pos = {
- False: (300, 2100 - 305, math.radians (-270)),
- True: (3000 - 300, 2100 - 305, math.radians (-270))
- }
+ def __init__ (self, proto_time, instance = 'robot0'):
+ self.instance = instance
+ def proto (proto_class, cmd, init):
+ cmd = [ s.format (instance = instance) for s in cmd ]
+ return proto_class (PopenIO (cmd), proto_time, **init)
+ asserv_cmd = ('../../asserv/src/asserv/asserv.host',
+ '-i{instance}:asserv0', '-m9', 'marcel')
+ mimot_cmd = ('../../mimot/src/dirty/dirty.host',
+ '-i{instance}:mimot0', '-m9', 'marcel')
+ io_cmd = ('../../io/src/io.host', '-i{instance}:io0')
+ self.asserv = proto (asserv.Proto, asserv_cmd,
+ asserv.init.host['marcel'])
+ self.mimot = proto (mimot.Proto, mimot_cmd,
+ mimot.init.host['marcel'])
+ self.io = proto (io.Proto, io_cmd,
+ io.init.host['marcel'])
+ self.protos = (self.asserv, self.mimot, self.io)
diff --git a/digital/ai/tools/robospierre.py b/digital/ai/tools/robospierre.py
index 09be4bea..0d258b34 100644
--- a/digital/ai/tools/robospierre.py
+++ b/digital/ai/tools/robospierre.py
@@ -1,10 +1,3 @@
-import simu.model.table_eurobot2011
-import simu.view.table_eurobot2011
-
-import simu.robots.robospierre.link.bag
-import simu.robots.robospierre.model.bag
-import simu.robots.robospierre.view.bag
-
import asserv
import asserv.init
import mimot
@@ -16,24 +9,39 @@ from proto.popen_io import PopenIO
import math
class Robot:
+ """Robospierre robot instance."""
+
+ import simu.model.table_eurobot2011 as table_model
+ import simu.view.table_eurobot2011 as table_view
+
+ import simu.robots.robospierre.link.bag as robot_link
+ import simu.robots.robospierre.model.bag as robot_model
+ import simu.robots.robospierre.view.bag as robot_view
+
+ robot_start_pos = {
+ # In real life, better place the robot in green zone.
+ False: (300, 2100 - 200, math.radians (180)),
+ True: (3000 - 300, 2100 - 200, math.radians (0))
+ }
+
+ client_nb = 3
- def __init__ (self, proto_time):
- self.table_model = simu.model.table_eurobot2011
- self.table_view = simu.view.table_eurobot2011
- self.robot_link = simu.robots.robospierre.link.bag
- self.robot_model = simu.robots.robospierre.model.bag
- self.robot_view = simu.robots.robospierre.view.bag
- asserv_cmd = ('../../asserv/src/asserv/asserv.host', '-m9', 'marcel')
- mimot_cmd = ('../../mimot/src/dirty/dirty.host', '-m9', 'marcel')
- io_hub_cmd = ('../../io-hub/src/robospierre/io_hub.host')
- self.asserv = asserv.Proto (PopenIO (asserv_cmd), proto_time,
- **asserv.init.host['robospierre'])
- self.mimot = mimot.Proto (PopenIO (mimot_cmd), proto_time,
- **mimot.init.host['robospierre'])
- self.io = io_hub.Proto (PopenIO (io_hub_cmd), proto_time,
- **io_hub.init.host['robospierre'])
- self.robot_start_pos = {
- False: (700, 2100 - 250, math.radians (-270)),
- True: (3000 - 700, 2100 - 250, math.radians (-270))
- }
+ def __init__ (self, proto_time, instance = 'robot0'):
+ self.instance = instance
+ def proto (proto_class, cmd, init):
+ cmd = [ s.format (instance = instance) for s in cmd ]
+ return proto_class (PopenIO (cmd), proto_time, **init)
+ asserv_cmd = ('../../asserv/src/asserv/asserv.host',
+ '-i{instance}:asserv0', '-m9', 'robospierre')
+ mimot_cmd = ('../../mimot/src/dirty/dirty.host',
+ '-i{instance}:mimot0', '-m9', 'robospierre')
+ io_hub_cmd = ('../../io-hub/src/robospierre/io_hub.host',
+ '-i{instance}:io0')
+ self.asserv = proto (asserv.Proto, asserv_cmd,
+ asserv.init.host['robospierre'])
+ self.mimot = proto (mimot.Proto, mimot_cmd,
+ mimot.init.host['robospierre'])
+ self.io = proto (io_hub.Proto, io_hub_cmd,
+ io_hub.init.host['robospierre'])
+ self.protos = (self.asserv, self.mimot, self.io)
diff --git a/digital/ai/tools/test_simu.py b/digital/ai/tools/test_simu.py
index 80008bb9..1b804e22 100644
--- a/digital/ai/tools/test_simu.py
+++ b/digital/ai/tools/test_simu.py
@@ -49,32 +49,29 @@ class ObstacleWithBeacon (obstacle_view.RoundObstacle):
class TestSimu (InterNode):
"""Interface, with simulated programs."""
- def __init__ (self, robot_class):
+ def __init__ (self, robot_class, robot_nb = 1, color_switch = True):
# Hub.
- self.hub = mex.hub.Hub (min_clients = 4)
+ self.hub = mex.hub.Hub (min_clients = 1 + robot_class.client_nb
+ * robot_nb)
self.forked_hub = utils.forked.Forked (self.hub.wait)
# InterNode.
InterNode.__init__ (self)
def proto_time ():
return self.node.date / self.node.tick
- # Robot parameters.
- robot = robot_class (proto_time)
- self.robot = robot
- # Asserv.
- self.asserv = robot.asserv
- self.asserv.async = True
- self.tk.createfilehandler (self.asserv, READABLE, self.asserv_read)
- # Mimot.
- self.mimot = robot.mimot
- self.mimot.async = True
- self.tk.createfilehandler (self.mimot, READABLE, self.mimot_read)
- # Io.
- self.io = robot.io
- self.io.async = True
- self.tk.createfilehandler (self.io, READABLE, self.io_read)
+ # Robot instances.
+ self.robots = [ robot_class (proto_time, 'robot%d' % i)
+ for i in xrange (robot_nb) ]
+ for r in self.robots:
+ for prog in r.protos:
+ prog.async = True
+ def prog_read (f, mask, prog = prog):
+ prog.proto.read ()
+ prog.proto.sync ()
+ self.tk.createfilehandler (prog, READABLE, prog_read)
# Add table.
- self.table_model = robot.table_model.Table ()
- self.table = robot.table_view.Table (self.table_view, self.table_model)
+ self.table_model = robot_class.table_model.Table ()
+ self.table = robot_class.table_view.Table (self.table_view,
+ self.table_model)
self.obstacle = obstacle_model.RoundObstacle (150)
self.table_model.obstacles.append (self.obstacle)
self.obstacle_beacon = obstacle_model.RoundObstacle (40, 2)
@@ -82,43 +79,31 @@ class TestSimu (InterNode):
self.obstacle_view = ObstacleWithBeacon (self.table, self.obstacle,
self.obstacle_beacon)
self.table_view.bind ('<2>', self.place_obstacle)
- # Add robot.
- self.robot_link = robot.robot_link.Bag (self.node)
- self.robot_model = robot.robot_model.Bag (self.node, self.table_model,
- self.robot_link)
- self.robot_view = robot.robot_view.Bag (self.table,
- self.actuator_view, self.sensor_frame, self.robot_model)
- # Color switch.
- self.robot_model.color_switch.register (self.change_color)
+ # Add robots.
+ for r in self.robots:
+ r.link = r.robot_link.Bag (self.node, r.instance)
+ r.model = r.robot_model.Bag (self.node, self.table_model, r.link)
+ r.view = r.robot_view.Bag (self.table, self.actuator_view,
+ self.sensor_frame, r.model)
+ # Color switch.
+ if color_switch:
+ def change_color (r = r):
+ i = r.model.color_switch.state
+ r.asserv.set_simu_pos (*r.robot_start_pos[i])
+ r.model.color_switch.register (change_color)
def close (self):
self.forked_hub.kill ()
import time
time.sleep (1)
- def asserv_read (self, file, mask):
- self.asserv.proto.read ()
- self.asserv.proto.sync ()
-
- def mimot_read (self, file, mask):
- self.mimot.proto.read ()
- self.mimot.proto.sync ()
-
- def io_read (self, file, mask):
- self.io.proto.read ()
- self.io.proto.sync ()
-
def step (self):
"""Overide step to handle retransmissions, could be made cleaner using
simulated time."""
InterNode.step (self)
- self.asserv.proto.sync ()
- self.mimot.proto.sync ()
- self.io.proto.sync ()
-
- def change_color (self, *dummy):
- i = self.robot_model.color_switch.state
- self.asserv.set_simu_pos (*self.robot.robot_start_pos[i]);
+ for r in self.robots:
+ for prog in r.protos:
+ prog.proto.sync ()
def place_obstacle (self, ev):
pos = self.table_view.screen_coord ((ev.x, ev.y))
@@ -132,6 +117,8 @@ def run (default_robot, test_class = TestSimu):
parser = optparse.OptionParser ()
parser.add_option ('-r', '--robot', help = "use specified robot",
metavar = 'NAME', default = default_robot)
+ parser.add_option ('-n', '--robot-nb', help = "number of robots",
+ type = 'int', metavar = 'NB', default = 1)
(options, args) = parser.parse_args ()
if args:
parser.error ("too many arguments")
@@ -143,7 +130,7 @@ def run (default_robot, test_class = TestSimu):
robot = robospierre.Robot
else:
parser.error ("unknown robot")
- app = test_class (robot)
+ app = test_class (robot, options.robot_nb)
app.mainloop ()
app.close ()
diff --git a/digital/ai/tools/test_simu_control_marcel.py b/digital/ai/tools/test_simu_control_marcel.py
index 2a43b7bb..1d5563e0 100644
--- a/digital/ai/tools/test_simu_control_marcel.py
+++ b/digital/ai/tools/test_simu_control_marcel.py
@@ -28,8 +28,11 @@ import math
class TestSimuControl (TestSimu):
"""Interface with extra control."""
- def __init__ (self, robot_class):
- TestSimu.__init__ (self, robot_class)
+ def __init__ (self, robot_class, *args):
+ TestSimu.__init__ (self, robot_class, *args, color_switch = False)
+ self.io = self.robots[0].io
+ self.asserv = self.robots[0].asserv
+ self.mimot = self.robots[0].mimot
def create_widgets (self):
TestSimu.create_widgets (self)
diff --git a/digital/ai/tools/test_simu_control_robospierre.py b/digital/ai/tools/test_simu_control_robospierre.py
index b1cccf4b..c1a16c3c 100644
--- a/digital/ai/tools/test_simu_control_robospierre.py
+++ b/digital/ai/tools/test_simu_control_robospierre.py
@@ -30,10 +30,13 @@ class TestSimuControl (TestSimu):
ELEVATION_STROKE = 0x3b0b
- ROTATION_STROKE = 0x11c6
+ ROTATION_STROKE = 0x233e
- def __init__ (self, robot_class):
- TestSimu.__init__ (self, robot_class)
+ def __init__ (self, robot_class, *args):
+ TestSimu.__init__ (self, robot_class, *args, color_switch = False)
+ self.io = self.robots[0].io
+ self.asserv = self.robots[0].asserv
+ self.mimot = self.robots[0].mimot
def create_widgets (self):
TestSimu.create_widgets (self)
@@ -46,6 +49,12 @@ class TestSimuControl (TestSimu):
indicatoron = False,
variable = self.clamp_var, command = self.clamp_command)
self.clamp_button.pack ()
+ self.doors_var = IntVar ()
+ self.doors_var.set (1)
+ self.doors_button = Checkbutton (self.control_frame, text = 'Doors',
+ indicatoron = False,
+ variable = self.doors_var, command = self.doors_command)
+ self.doors_button.pack ()
self.elevation_up_button = Button (self.control_frame,
text = 'Elevation up', padx = 0, pady = 0,
command = self.elevation_up_command)
@@ -69,12 +78,35 @@ class TestSimuControl (TestSimu):
text = 'Move clamp', padx = 0, pady = 0,
command = self.clamp_move_command)
self.clamp_move_button.pack ()
+ self.clamp_to_scale = Scale (self.control_frame, orient = HORIZONTAL,
+ from_ = 0, to = 6)
+ self.clamp_to_scale.pack ()
+ self.clamp_element_move_button = Button (self.control_frame,
+ text = 'Move element', padx = 0, pady = 0,
+ command = self.clamp_move_element_command)
+ self.clamp_element_move_button.pack ()
+ self.drop_var = IntVar ()
+ self.drop_button = Checkbutton (self.control_frame, text = 'Drop',
+ indicatoron = False,
+ variable = self.drop_var, command = self.drop_command)
+ self.drop_button.pack ()
+ self.backward_var = IntVar ()
+ self.backward_button = Checkbutton (self.control_frame,
+ text = 'Backward', variable = self.backward_var)
+ self.backward_button.pack ()
+ self.goto_var = IntVar ()
+ self.goto_button = Checkbutton (self.control_frame,
+ text = 'Goto FSM', variable = self.goto_var)
+ self.goto_button.pack ()
self.table_view.bind ('<1>', self.move)
self.table_view.bind ('<3>', self.orient)
def move (self, ev):
pos = self.table_view.screen_coord ((ev.x, ev.y))
- self.asserv.goto (pos[0], pos[1])
+ if self.goto_var.get ():
+ self.io.goto (pos[0], pos[1], self.backward_var.get ())
+ else:
+ self.asserv.goto (pos[0], pos[1], self.backward_var.get ())
def orient (self, ev):
x, y = self.table_view.screen_coord ((ev.x, ev.y))
@@ -84,10 +116,7 @@ class TestSimuControl (TestSimu):
self.asserv.goto_angle (a)
def clamp_command (self):
- if self.clamp_var.get ():
- self.io.pwm_set_timed (0, -0x3ff, 255, 0)
- else:
- self.io.pwm_set_timed (0, 0x3ff, 255, 0)
+ self.io.clamp_openclose (not self.clamp_var.get ())
def elevation_up_command (self):
self.mimot.speed_pos ('a0', self.ELEVATION_STROKE / 2)
@@ -104,6 +133,24 @@ class TestSimuControl (TestSimu):
def clamp_move_command (self):
self.io.clamp_move (self.clamp_pos_scale.get ())
+ def clamp_move_element_command (self):
+ self.io.clamp_move_element (self.clamp_pos_scale.get (),
+ self.clamp_to_scale.get ())
+
+ def doors_command (self):
+ for i in (0, 2, 3, 5):
+ self.io.door (i, not self.doors_var.get ())
+
+ def drop_command (self):
+ if self.drop_var.get ():
+ if self.backward_var.get ():
+ order = 'drop_backward'
+ else:
+ order = 'drop_forward'
+ else:
+ order = 'drop_clear'
+ self.io.drop (order)
+
def change_color (self, *dummy):
pass
diff --git a/digital/asserv/src/asserv/main.c b/digital/asserv/src/asserv/main.c
index 2d53e2fa..677fea84 100644
--- a/digital/asserv/src/asserv/main.c
+++ b/digital/asserv/src/asserv/main.c
@@ -400,6 +400,27 @@ proto_callback (uint8_t cmd, uint8_t size, uint8_t *args)
break;
traj_ftw_start_center (args[0], args[1], args[2]);
break;
+ case c ('f', 12):
+ /* Push the wall.
+ * - b: 0: forward, 1: backward.
+ * - d: init_x, f24.8.
+ * - d: init_y, f24.8.
+ * - w: init_a, f0.16.
+ * - b: sequence number. */
+ {
+ if (args[11] == state_main.sequence)
+ break;
+ int32_t angle;
+ if (args[9] == 0xff && args[10] == 0xff)
+ angle = -1;
+ else
+ angle = v8_to_v32 (0, args[9], args[10], 0);
+ traj_ptw_start (args[0],
+ v8_to_v32 (args[1], args[2], args[3], args[4]),
+ v8_to_v32 (args[5], args[6], args[7], args[8]),
+ angle, args[11]);
+ }
+ break;
case c ('F', 1):
/* Go to the dispenser.
* - b: sequence number. */
diff --git a/digital/asserv/src/asserv/models.host.c b/digital/asserv/src/asserv/models.host.c
index f4d8ca5a..3839af1e 100644
--- a/digital/asserv/src/asserv/models.host.c
+++ b/digital/asserv/src/asserv/models.host.c
@@ -32,6 +32,8 @@
#include <math.h>
#include <string.h>
+#define NO_CORNER { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }
+
/* RE25CLL with 1:10 gearbox model. */
static const struct motor_def_t re25cll_model =
{
@@ -89,6 +91,25 @@ static const struct motor_def_t amax32ghp_model =
-INFINITY, +INFINITY,
};
+/* Faulhaber 2657 and a 1:9.7 ratio gearbox. */
+static const struct motor_def_t faulhaber_2657_model =
+{
+ /* Motor characteristics. */
+ 274 * (2*M_PI) / 60,/* Speed constant ((rad/s)/V). */
+ 34.8 / 1000, /* Torque constant (N.m/A). */
+ 0, /* Bearing friction (N.m/(rad/s)). */
+ 2.84, /* Terminal resistance (Ohm). */
+ 0.380 / 1000, /* Terminal inductance (H). */
+ 24.0, /* Maximum voltage (V). */
+ /* Gearbox characteristics. */
+ 9.7, /* Gearbox ratio. */
+ 0.80, /* Gearbox efficiency. */
+ /* Load characteristics. */
+ 0.0, /* Load (kg.m^2). */
+ /* Hardware limits. */
+ -INFINITY, +INFINITY,
+};
+
/* Gloubi, Efrei 2006. */
static const struct robot_t gloubi_robot =
{
@@ -106,7 +127,7 @@ static const struct robot_t gloubi_robot =
13.0, // approx
/* Whether the encoder is mounted on the main motor (false) or not (true). */
0,
- 0.0, 0.0, { NULL, NULL }, { 0, 0 }, NULL
+ 0.0, 0.0, { NULL, NULL }, { 0, 0 }, NULL, NULL, NO_CORNER
};
/* Taz, APBTeam/Efrei 2005. */
@@ -126,7 +147,7 @@ static const struct robot_t taz_robot =
0.0,
/* Whether the encoder is mounted on the main motor (false) or not (true). */
0,
- 0.0, 0.0, { NULL, NULL }, { 0, 0 }, NULL
+ 0.0, 0.0, { NULL, NULL }, { 0, 0 }, NULL, NULL, NO_CORNER
};
/* TazG, Taz with RE25G motors. */
@@ -146,7 +167,7 @@ static const struct robot_t tazg_robot =
0.0,
/* Whether the encoder is mounted on the main motor (false) or not (true). */
0,
- 0.0, 0.0, { NULL, NULL }, { 0, 0 }, NULL
+ 0.0, 0.0, { NULL, NULL }, { 0, 0 }, NULL, NULL, NO_CORNER
};
/* Giboulée arm model, with a RE25CLL and a 1:10 ratio gearbox. */
@@ -197,6 +218,7 @@ static const struct robot_t giboulee_robot =
{ 500, 0 },
/** Sensor update function. */
simu_sensor_update_giboulee,
+ NULL, NO_CORNER,
};
/* AquaJim arm model, with a RE40G and a 1:4 + 15:80 ratio gearbox. */
@@ -267,6 +289,7 @@ static const struct robot_t aquajim_robot =
{ 250, 250 },
/** Sensor update function. */
simu_sensor_update_aquajim,
+ NULL, NO_CORNER,
};
/* Marcel elevator model, with a Faulhaber 2657 and a 1:9.7 ratio gearbox. */
@@ -338,6 +361,41 @@ static const struct robot_t marcel_robot =
{ 256, 250 },
/** Sensor update function. */
simu_sensor_update_marcel,
+ NULL, NO_CORNER,
+};
+
+/* Robospierre, APBTeam 2011. */
+static const struct robot_t robospierre_robot =
+{
+ /* Main motors. */
+ &faulhaber_2657_model,
+ /* Number of steps on the main motors encoders. */
+ 2500,
+ /* Wheel radius (m). */
+ 0.065 / 2,
+ /* Distance between the wheels (m). */
+ 0.16,
+ /* Weight of the robot (kg). */
+ 10.0,
+ /* Distance of the gravity center from the center of motors axis (m). */
+ 0.0,
+ /* Whether the encoder is mounted on the main motor (false) or not (true). */
+ 1,
+ /** Encoder wheel radius (m). */
+ 0.063 / 2,
+ /** Distance between the encoders wheels (m). */
+ 0.28,
+ /** Auxiliary motors, NULL if not present. */
+ { NULL, NULL },
+ /** Number of steps for each auxiliary motor encoder. */
+ { 0, 0 },
+ /** Sensor update function. */
+ NULL,
+ /** Table test function, return false if given robot point is not in
+ * table. */
+ simu_table_test_robospierre,
+ /** Robot corners, from front left, then clockwise. */
+ { { 150, 110 }, { 150, -110 }, { -150, -110 }, { -150, 110 } },
};
/* Table of models. */
@@ -352,6 +410,7 @@ static const struct
{ "giboulee", &giboulee_robot },
{ "aquajim", &aquajim_robot },
{ "marcel", &marcel_robot },
+ { "robospierre", &robospierre_robot },
{ 0, 0 }
};
diff --git a/digital/asserv/src/asserv/models.host.h b/digital/asserv/src/asserv/models.host.h
index 403e9cd9..d8f1dcb8 100644
--- a/digital/asserv/src/asserv/models.host.h
+++ b/digital/asserv/src/asserv/models.host.h
@@ -27,6 +27,8 @@
#define ECHANT_PERIOD (1.0 / (14745600.0 / 256 / 256))
+#define CORNERS_NB 4
+
/** Define a robot and its peripherals.
* Encoder characteristics are defined at gearbox output. */
struct robot_t
@@ -55,6 +57,11 @@ struct robot_t
int aux_encoder_steps[AC_ASSERV_AUX_NB];
/** Sensor update function. */
void (*sensor_update) (void);
+ /** Table test function, return false if given robot point is not in
+ * table. */
+ int (*table_test) (double p_x, double p_y);
+ /** Robot corners, from front left, then clockwise. */
+ double corners[CORNERS_NB][2];
};
/** Get a pointer to a model by name, or return 0. */
diff --git a/digital/asserv/src/asserv/simu.host.c b/digital/asserv/src/asserv/simu.host.c
index 10cef711..7053ae60 100644
--- a/digital/asserv/src/asserv/simu.host.c
+++ b/digital/asserv/src/asserv/simu.host.c
@@ -36,6 +36,8 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <time.h>
+#include <sys/time.h>
#include "pwm.h"
#include "aux.h"
@@ -87,6 +89,9 @@ double simu_counter_left_th, simu_counter_right_th;
/** Use mex. */
int simu_mex;
+/** Do not sleep. */
+int simu_fast;
+
/** Mex message types. */
uint8_t simu_mex_position;
uint8_t simu_mex_pwm;
@@ -115,6 +120,7 @@ simu_init (void)
simu_mex_pwm = mex_node_reservef ("%s:pwm", mex_instance);
simu_mex_aux = mex_node_reservef ("%s:aux", mex_instance);
}
+ simu_fast = simu_mex;
if (argc != 1)
{
fprintf (stderr, "Syntax: asserv.host [-m[interval]] model\n");
@@ -154,6 +160,16 @@ simu_pos_update (double dl, double dr, double footing)
simu_pos_a = na;
}
+/** Compute a robot point absolute position. */
+static void
+simu_compute_absolute_position (double p_x, double p_y, double *x, double *y)
+{
+ double c = cos (simu_pos_a);
+ double s = sin (simu_pos_a);
+ *x = simu_pos_x + c * p_x - s * p_y;
+ *y = simu_pos_y + s * p_x + c * p_y;
+}
+
/** Update sensors for Giboulee. */
void
simu_sensor_update_giboulee (void)
@@ -175,10 +191,7 @@ simu_sensor_update_giboulee (void)
for (i = 0; i < UTILS_COUNT (sensors); i++)
{
/* Compute absolute position. */
- x = simu_pos_x + cos (simu_pos_a) * sensors[i][0]
- - sin (simu_pos_a) * sensors[i][1];
- y = simu_pos_y + sin (simu_pos_a) * sensors[i][0]
- + cos (simu_pos_a) * sensors[i][1];
+ simu_compute_absolute_position (sensors[i][0], sensors[i][1], &x, &y);
if (x >= 0.0 && x < table_width && y >= 0.0 && y < table_height)
PINC |= sensors_bit[i];
}
@@ -217,10 +230,7 @@ simu_sensor_update_aquajim (void)
for (i = 0; i < UTILS_COUNT (sensors); i++)
{
/* Compute absolute position. */
- x = simu_pos_x + cos (simu_pos_a) * sensors[i][0]
- - sin (simu_pos_a) * sensors[i][1];
- y = simu_pos_y + sin (simu_pos_a) * sensors[i][0]
- + cos (simu_pos_a) * sensors[i][1];
+ simu_compute_absolute_position (sensors[i][0], sensors[i][1], &x, &y);
cx = table_width / 2 - x;
cy = table_height / 2 - y;
ds = cx * cx + cy * cy;
@@ -268,10 +278,7 @@ simu_sensor_update_marcel (void)
for (i = 0; i < UTILS_COUNT (sensors); i++)
{
/* Compute absolute position. */
- x = simu_pos_x + cos (simu_pos_a) * sensors[i][0]
- - sin (simu_pos_a) * sensors[i][1];
- y = simu_pos_y + sin (simu_pos_a) * sensors[i][0]
- + cos (simu_pos_a) * sensors[i][1];
+ simu_compute_absolute_position (sensors[i][0], sensors[i][1], &x, &y);
if (x >= 0.0 && x < table_width && y >= 0.0 && y < table_height
&& (x < stand_x_min || x >= stand_x_max || y < stand_y))
PINC |= sensors_bit[i];
@@ -281,6 +288,18 @@ simu_sensor_update_marcel (void)
PINC |= IO_BV (CONTACT_AUX1_ZERO_IO);
}
+/* Table test for Robospierre. */
+int
+simu_table_test_robospierre (double p_x, double p_y)
+{
+ static const double table_width = 3000.0, table_height = 2100.0;
+ double x, y;
+ simu_compute_absolute_position (p_x, p_y, &x, &y);
+ if (x < 0 || y < 0 || x >= table_width || y >= table_height)
+ return 0;
+ return 1;
+}
+
/** Do a simulation step. */
static void
simu_step (void)
@@ -306,6 +325,39 @@ simu_step (void)
if (simu_robot->aux_motor[i])
motor_model_step (&simu_aux_model[i]);
}
+ /* Update position. */
+ double old_pos_x = simu_pos_x, old_pos_y = simu_pos_y,
+ old_pos_a = simu_pos_a;
+ simu_pos_update ((simu_left_model.th - old_left_th)
+ / simu_left_model.m.i_G * simu_robot->wheel_r * 1000,
+ (simu_right_model.th - old_right_th)
+ / simu_right_model.m.i_G * simu_robot->wheel_r * 1000,
+ simu_robot->footing * 1000);
+ /* Check robot is still on the table. */
+ if (simu_robot->table_test)
+ {
+ static int old_out = 1;
+ int out = 0;
+ for (i = 0; i < CORNERS_NB; i++)
+ {
+ if (!simu_robot->table_test (simu_robot->corners[i][0],
+ simu_robot->corners[i][1]))
+ out = 1;
+ }
+ /* If out, cancel movement. */
+ if (out && !old_out)
+ {
+ simu_pos_x = old_pos_x;
+ simu_pos_y = old_pos_y;
+ simu_pos_a = old_pos_a;
+ simu_left_model.th = old_left_th;
+ simu_right_model.th = old_right_th;
+ }
+ else
+ {
+ old_out = out;
+ }
+ }
/* Modify counters. */
uint32_t counter_left_new;
uint32_t counter_right_new;
@@ -364,12 +416,6 @@ simu_step (void)
simu_counter_aux[i] = 0;
}
}
- /* Update position. */
- simu_pos_update ((simu_left_model.th - old_left_th)
- / simu_left_model.m.i_G * simu_robot->wheel_r * 1000,
- (simu_right_model.th - old_right_th)
- / simu_right_model.m.i_G * simu_robot->wheel_r * 1000,
- simu_robot->footing * 1000);
/* Update sensors. */
if (simu_robot->sensor_update)
simu_robot->sensor_update ();
@@ -450,12 +496,37 @@ timer_init (void)
simu_init ();
}
+/** Slow down program execution. */
+void
+simu_wait (int freq)
+{
+#define ONE_SEC_NS 1000000000ll
+ struct timeval tv;
+ static long long int last_ns = 0;
+ long long int now_ns;
+ gettimeofday (&tv, NULL);
+ now_ns = tv.tv_sec * ONE_SEC_NS + tv.tv_usec * 1000;
+ if (last_ns == 0 || now_ns - last_ns > ONE_SEC_NS)
+ last_ns = now_ns;
+ last_ns = last_ns + ONE_SEC_NS / freq;
+ long long int diff_ns = last_ns - now_ns;
+ if (diff_ns > 0)
+ {
+ struct timespec ts;
+ ts.tv_sec = diff_ns / ONE_SEC_NS;
+ ts.tv_nsec = diff_ns % ONE_SEC_NS;
+ nanosleep (&ts, &ts);
+ }
+}
+
/** Wait for timer overflow. */
void
timer_wait (void)
{
if (simu_mex)
mex_node_wait_date (mex_node_date () + 4);
+ if (!simu_fast)
+ simu_wait (225);
simu_step ();
if (simu_mex && !--simu_send_cpt)
{
diff --git a/digital/asserv/src/asserv/simu.host.h b/digital/asserv/src/asserv/simu.host.h
index 143d3430..93785186 100644
--- a/digital/asserv/src/asserv/simu.host.h
+++ b/digital/asserv/src/asserv/simu.host.h
@@ -47,4 +47,7 @@ simu_sensor_update_aquajim (void);
void
simu_sensor_update_marcel (void);
+int
+simu_table_test_robospierre (double p_x, double p_y);
+
#endif /* simu_host_h */
diff --git a/digital/asserv/src/asserv/speed.c b/digital/asserv/src/asserv/speed.c
index 5c221b7e..32102177 100644
--- a/digital/asserv/src/asserv/speed.c
+++ b/digital/asserv/src/asserv/speed.c
@@ -58,13 +58,21 @@ speed_init (void)
static void
speed_update_by_speed (struct speed_t *speed)
{
- /* Update current speed. */
- if (UTILS_ABS (speed->cons - speed->cur) < speed->acc)
- speed->cur = speed->cons;
- else if (speed->cons > speed->cur)
- speed->cur += speed->acc;
+ /* Update current speed (be careful of overflow!). */
+ if (speed->cons > speed->cur)
+ {
+ if ((uint16_t) (speed->cons - speed->cur) < (uint16_t) speed->acc)
+ speed->cur = speed->cons;
+ else
+ speed->cur += speed->acc;
+ }
else
- speed->cur -= speed->acc;
+ {
+ if ((uint16_t) (speed->cur - speed->cons) < (uint16_t) speed->acc)
+ speed->cur = speed->cons;
+ else
+ speed->cur -= speed->acc;
+ }
}
/** Compute maximum allowed speed according to: distance left, maximum speed,
diff --git a/digital/asserv/src/asserv/test_motor_model.c b/digital/asserv/src/asserv/test_motor_model.c
index 706aa31b..044bab2e 100644
--- a/digital/asserv/src/asserv/test_motor_model.c
+++ b/digital/asserv/src/asserv/test_motor_model.c
@@ -84,3 +84,9 @@ simu_sensor_update_marcel (void)
{
}
+int
+simu_table_test_robospierre (double p_x, double p_y)
+{
+ return 0;
+}
+
diff --git a/digital/asserv/src/asserv/traj.c b/digital/asserv/src/asserv/traj.c
index 11618eca..e147ad5d 100644
--- a/digital/asserv/src/asserv/traj.c
+++ b/digital/asserv/src/asserv/traj.c
@@ -37,6 +37,7 @@
#include "pos.h"
#include "speed.h"
#include "postrack.h"
+#include "pwm.h"
#include "contacts.h"
@@ -59,6 +60,8 @@ enum
TRAJ_FTW,
/* Go to the dispenser. */
TRAJ_GTD,
+ /* Push the wall. */
+ TRAJ_PTW,
/* Go to position. */
TRAJ_GOTO,
/* Go to angle. */
@@ -99,6 +102,9 @@ static uint8_t traj_use_center;
/** Center sensor delay. */
static uint8_t traj_center_delay;
+/** Initial values for x, y and angle, or -1. */
+static int32_t traj_init_x, traj_init_y, traj_init_a;
+
/** Initialise computed factors. */
void
traj_init (void)
@@ -210,6 +216,54 @@ traj_ftw_start_center (uint8_t backward, uint8_t center_delay, uint8_t seq)
state_start (&state_main, MODE_TRAJ, seq);
}
+/** Push the wall mode. */
+static void
+traj_ptw (void)
+{
+ /* If blocking, the wall was found. */
+ if (pos_theta.blocked_counter >= pos_theta.blocked_counter_limit)
+ {
+ /* Initialise position. */
+ if (traj_init_x != -1)
+ postrack_x = traj_init_x;
+ if (traj_init_y != -1)
+ postrack_y = traj_init_y;
+ if (traj_init_a != -1)
+ postrack_a = traj_init_a;
+ /* Stop motor control. */
+ pos_reset (&pos_theta);
+ pos_reset (&pos_alpha);
+ state_main.variant = 0;
+ state_main.mode = MODE_PWM;
+ pwm_set (&pwm_left, 0);
+ pwm_set (&pwm_right, 0);
+ state_finish (&state_main);
+ traj_mode = TRAJ_DONE;
+ }
+}
+
+/** Start push the wall mode. Position is initialised unless -1. */
+void
+traj_ptw_start (uint8_t backward, int32_t init_x, int32_t init_y,
+ int32_t init_a, uint8_t seq)
+{
+ int16_t speed;
+ traj_mode = TRAJ_PTW;
+ traj_init_x = init_x;
+ traj_init_y = init_y;
+ traj_init_a = init_a;
+ state_start (&state_main, MODE_TRAJ, seq);
+ /* Use slow speed, without alpha control. */
+ speed = speed_theta.slow;
+ speed *= 256;
+ if (backward)
+ speed = -speed;
+ speed_theta.use_pos = speed_alpha.use_pos = 0;
+ speed_theta.cons = speed;
+ speed_alpha.cons = 0;
+ state_main.variant = 2;
+}
+
/** Go to the dispenser mode. */
static void
traj_gtd (void)
@@ -392,6 +446,9 @@ traj_update (void)
case TRAJ_FTW:
traj_ftw ();
break;
+ case TRAJ_PTW:
+ traj_ptw ();
+ break;
case TRAJ_GTD:
traj_gtd ();
break;
diff --git a/digital/asserv/src/asserv/traj.h b/digital/asserv/src/asserv/traj.h
index 706fbdaf..ec345d0c 100644
--- a/digital/asserv/src/asserv/traj.h
+++ b/digital/asserv/src/asserv/traj.h
@@ -49,6 +49,10 @@ void
traj_ftw_start_center (uint8_t backward, uint8_t center_delay, uint8_t seq);
void
+traj_ptw_start (uint8_t backward, int32_t init_x, int32_t init_y,
+ int32_t init_a, uint8_t seq);
+
+void
traj_gtd_start (uint8_t seq);
void
diff --git a/digital/asserv/src/asserv/twi_proto.c b/digital/asserv/src/asserv/twi_proto.c
index ff15c82f..fcf0a9cc 100644
--- a/digital/asserv/src/asserv/twi_proto.c
+++ b/digital/asserv/src/asserv/twi_proto.c
@@ -168,6 +168,24 @@ twi_proto_callback (u8 *buf, u8 size)
* - b: 0: forward, 1: backward. */
traj_ftw_start (buf[2], 0);
break;
+ case c ('G', 9):
+ /* Push the wall.
+ * - b: 0: forward, 1: backward.
+ * - 3b: init_x.
+ * - 3b: init_y.
+ * - w: init_a. */
+ {
+ int32_t angle;
+ if (buf[9] == 0xff && buf[10] == 0xff)
+ angle = -1;
+ else
+ angle = v8_to_v32 (0, buf[9], buf[10], 0);
+ traj_ptw_start (buf[2],
+ v8_to_v32 (buf[3], buf[4], buf[5], 0xff),
+ v8_to_v32 (buf[6], buf[7], buf[8], 0xff),
+ angle, 0);
+ }
+ break;
case c ('g', 2):
/* Go to the wall using center sensor with delay.
* - b: 0: forward, 1: backward.
diff --git a/digital/asserv/tools/asserv/asserv.py b/digital/asserv/tools/asserv/asserv.py
index 997b05fb..4f386d7a 100644
--- a/digital/asserv/tools/asserv/asserv.py
+++ b/digital/asserv/tools/asserv/asserv.py
@@ -269,6 +269,15 @@ class Proto:
self.proto.send ('f', 'BB', backward and 1 or 0, self.mseq)
self.wait (self.finished, auto = True)
+ def ptw (self, backward = True, init_x = None, init_y = None,
+ init_a = None):
+ """Push the wall."""
+ self.mseq += 1
+ self.proto.send ('f', 'BllHB', backward and 1 or 0,
+ self._dist_f248 (init_x), self._dist_f248 (init_y),
+ self._angle_f16 (init_a), self.mseq)
+ self.wait (self.finished, auto = True)
+
def set_simu_pos (self, x, y, a):
"""Set simulated position."""
self.proto.send ('h', 'chhh', 'X', int (round (x)), int (round (y)),
@@ -381,10 +390,16 @@ class Proto:
return int (round (d / self.param['scale']))
def _dist_f248 (self, d):
- return int (round ((1 << 8) * d / self.param['scale']))
+ if d is None:
+ return -1
+ else:
+ return int (round ((1 << 8) * d / self.param['scale']))
def _angle_f16 (self, a):
- return int (round ((1 << 16) * a / (2 * math.pi))) & 0xffff
+ if a is None:
+ return 0xffff
+ else:
+ return int (round ((1 << 16) * a / (2 * math.pi))) & 0xffff
def _angle_f824 (self, a):
return int (round ((1 << 24) * a / (2 * math.pi)))
diff --git a/digital/asserv/tools/asserv/init.py b/digital/asserv/tools/asserv/init.py
index 3f0afa36..c845af03 100644
--- a/digital/asserv/tools/asserv/init.py
+++ b/digital/asserv/tools/asserv/init.py
@@ -12,10 +12,19 @@ host_marcel = dict (
E = 0x3ff, D = 0x1ff,
l = 0x1000,
)
+host_robospierre = dict (
+ scale = 0.0395840674352314, f = 0xdd1,
+ tkp = 1, tkd = 16,
+ ta = 0.75, tsm = 0x60, tss = 0x10,
+ akp = 2, akd = 16,
+ aa = 0.25, asm = 0x60, ass = 0x10,
+ E = 0x3ff, D = 0x1ff,
+ l = 0x1000,
+ )
host = {
'giboulee': host_marcel,
'marcel': host_marcel,
- 'robospierre': host_marcel,
+ 'robospierre': host_robospierre,
}
target_marcel = dict (
scale = 0.0415178942124, f = 0xcef,
@@ -34,8 +43,21 @@ target_marcel = dict (
l = 0x1000,
w = 0x09,
)
+target_robospierre = dict (
+ scale = 0.0317975134344, f = 0x134e,
+ c = float (0xffa897) / (1 << 24),
+ tkp = 1, tkd = 16,
+ ta = 0.75, tsm = 0x60, tss = 0x10,
+ tbe = 256, tbs = 0x08, tbc = 40,
+ akp = 2, akd = 16,
+ aa = 0.5, asm = 0x60, ass = 0x10,
+ abe = 128, abs = 0x08, abc = 40,
+ E = 0x3ff, D = 0x1ff,
+ l = 0x1000,
+ w = 0x00,
+ )
target = {
'giboulee': target_marcel,
'marcel': target_marcel,
- 'robospierre': target_marcel,
+ 'robospierre': target_robospierre,
}
diff --git a/digital/asserv/tools/inter_asserv.py b/digital/asserv/tools/inter_asserv.py
index 82a92c32..72e31f60 100644
--- a/digital/asserv/tools/inter_asserv.py
+++ b/digital/asserv/tools/inter_asserv.py
@@ -43,7 +43,7 @@ class InterAsserv (Inter):
self.tk.createfilehandler (self.a, READABLE, self.read)
self.timeout ()
# Query position.
- self.a.register_pos ()
+ self.a.register_pos (interval = 225 / 20)
self.a.position.register (self.pos)
def createWidgets (self):
diff --git a/digital/asserv/tools/test_goto.py b/digital/asserv/tools/test_goto.py
index 2cbbb350..f2aa2535 100644
--- a/digital/asserv/tools/test_goto.py
+++ b/digital/asserv/tools/test_goto.py
@@ -3,14 +3,29 @@ import math
import asserv
import asserv.init
-from utils.init_proto import init_proto
+from utils.init_proto import InitProto
-a = init_proto (None, asserv.Proto, asserv.init)
-for i in xrange (10):
- x = random.randrange (2000)
- y = random.randrange (1100)
- a.goto (x, y)
- a.goto_angle (math.radians (random.randrange (360)))
-a.goto (0, 0)
-a.goto_angle (0)
+ip = InitProto (None, asserv.Proto, asserv.init)
+ip.parser.add_option ('-i', '--iterations',
+ help = "number of test iterations", metavar = 'NB', default = 10)
+ip.parser.add_option ('-t', '--type',
+ help = "test type, one of random or linear", metavar = 'TYPE',
+ default = 'random')
+ip.parse_args ()
+a = ip.get_proto ()
+try:
+ if ip.options.type == 'random':
+ for i in xrange (ip.options.iterations):
+ x = random.randrange (2000)
+ y = random.randrange (1100)
+ a.goto (x, y)
+ a.goto_angle (math.radians (random.randrange (360)))
+ a.goto (0, 0)
+ a.goto_angle (0)
+ elif ip.options.type == 'linear':
+ for i in xrange (ip.options.iterations):
+ a.speed_pos ('t', 1000)
+ a.speed_pos ('t', -1000)
+except:
+ pass
a.close ()
diff --git a/digital/avr/doc/fuses.txt b/digital/avr/doc/fuses.txt
index 3f353fcd..1345c0ef 100644
--- a/digital/avr/doc/fuses.txt
+++ b/digital/avr/doc/fuses.txt
@@ -19,36 +19,44 @@ m16 0xff 0xc1 --
m32 0xff 0xc1 --
m64 0xff 0xc1 0xff
m128 0xff 0xc1 0xff
+usb128 0xff 0xd1 0xf3
====== ===== ===== =====
This correspond to ('!' means unprogrammed, i.e. '1'):
-=== === === === ==== =======
-m8 m16 m32 m64 m128 Meaning
-=== === === === ==== =======
-l7 l7 l7 l7 l7 !BODLEVEL (BOD trigger level)
-l6 l6 l6 l6 l6 !BODEN (BOD enabled)
-l5 l5 l5 l5 l5 !SUT1 (start up time)
-l4 l4 l4 l4 l4 !SUT0 (start up time)
-l3 l3 l3 l3 l3 !CKSEL3 (clock source select)
-l2 l2 l2 l2 l2 !CKSEL2 (clock source select)
-l1 l1 l1 l1 l1 !CKSEL1 (clock source select)
-l0 l0 l0 l0 l0 !CKSEL0 (clock source select)
---- --- --- --- ---- -------
-h7 .. .. .. .. !RSTDISBL (no reset pin disabled)
-.. h7 h7 h7 h7 !OCDEN (OCD enabled)
-h6 .. .. .. .. !WDTON (no watchdog always on)
-.. h6 h6 h6 h6 !JTAGEN (JTAG enabled)
-h5 h5 h5 h5 h5 SPIEN (spi programming enabled)
-h4 h4 h4 h4 h4 CKOPT (clock option)
-h3 h3 h3 h3 h3 EESAVE (eeprom preserved on chip erase)
-h2 h2 h2 h2 h2 BOOTSZ1 (boot size)
-h1 h1 h1 h1 h1 BOOTSZ0 (boot size)
-h0 h0 h0 h0 h0 !BOOTRST (use boot reset vector)
---- --- --- --- ---- -------
-.. .. .. e1 e1 !M103C (ATmega103 compatibility)
-.. .. .. e0 e0 !WDTON (watchdog always on)
-=== === === === ==== =======
+=== === === === ==== ====== =======
+m8 m16 m32 m64 m128 usb128 Meaning
+=== === === === ==== ====== =======
+l7 l7 l7 l7 l7 .. !BODLEVEL (BOD trigger level)
+l6 l6 l6 l6 l6 .. !BODEN (BOD enabled)
+.. .. .. .. .. l7 !CKDIV8 (divide clock by 8)
+.. .. .. .. .. l6 !CKOUT (clock output)
+l5 l5 l5 l5 l5 l5 !SUT1 (start up time)
+l4 l4 l4 l4 l4 l4 !SUT0 (start up time)
+l3 l3 l3 l3 l3 l3 !CKSEL3 (clock source select)
+l2 l2 l2 l2 l2 l2 !CKSEL2 (clock source select)
+l1 l1 l1 l1 l1 l1 !CKSEL1 (clock source select)
+l0 l0 l0 l0 l0 l0 !CKSEL0 (clock source select)
+--- --- --- --- ---- ------ -------
+h7 .. .. .. .. .. !RSTDISBL (no reset pin disabled)
+.. h7 h7 h7 h7 h7 !OCDEN (OCD enabled)
+h6 .. .. .. .. .. !WDTON (no watchdog always on)
+.. h6 h6 h6 h6 h6 !JTAGEN (JTAG enabled)
+h5 h5 h5 h5 h5 h5 SPIEN (spi programming enabled)
+h4 h4 h4 h4 h4 .. CKOPT (clock option)
+.. .. .. .. .. h4 !WDTON (watchdog always on)
+h3 h3 h3 h3 h3 h3 EESAVE (eeprom preserved on chip erase)
+h2 h2 h2 h2 h2 h2 BOOTSZ1 (boot size)
+h1 h1 h1 h1 h1 h1 BOOTSZ0 (boot size)
+h0 h0 h0 h0 h0 h0 !BOOTRST (use boot reset vector)
+--- --- --- --- ---- ------ -------
+.. .. .. e1 e1 !M103C (ATmega103 compatibility)
+.. .. .. e0 e0 !WDTON (watchdog always on)
+.. .. .. .. .. e3 HWBE (hardware boot enable)
+.. .. .. .. .. e2 BODLEVEL2 (brown-out detector select)
+.. .. .. .. .. e1 !BODLEVEL1 (brown-out detector select)
+.. .. .. .. .. e0 !BODLEVEL0 (brown-out detector select)
+=== === === === ==== ====== =======
- CKSEL321 = 111, CKOPT = 0 corresponds to external crystal, more than 1 MHz.
- CKSEL0 = 1, SUT10 = 11 corresponds to crystal, slowly rising power, this is
diff --git a/digital/avr/make/Makefile.avr b/digital/avr/make/Makefile.avr
index bffca25a..1fe5ff31 100644
--- a/digital/avr/make/Makefile.avr
+++ b/digital/avr/make/Makefile.avr
@@ -11,6 +11,7 @@ AVR_LDLIBS := $(LDLIBS) $(AVR_LIBS)
AVR_CC := avr-gcc
AVR_OBJCOPY := avr-objcopy
AVR_OBJDUMP := avr-objdump
+AVR_SIZE := avr-size --mcu=$(AVR_MCU) -C
AVR_COMPILE.c = $(AVR_CC) $(AVR_CFLAGS) $(AVR_CPPFLAGS) -c
ifdef L
AVR_COMPILE.c += -Wa,-adhlns=$(@:%.avr.o=%.c.avr.lst)
@@ -20,7 +21,7 @@ AVR_LINK.o := $(AVR_CC) $(AVR_CFLAGS) $(AVR_LDFLAGS)
# Main rules.
-avr: elf lst hex
+avr: elf lst hex size
simu: simuelf
@@ -90,6 +91,7 @@ text: hex
hex: $(AVR_PROGS:%=%.hex)
bin: $(AVR_PROGS:%=%.bin)
srec: $(AVR_PROGS:%=%.srec)
+size: $(AVR_PROGS:%=%.size)
%.hex: %.avr.elf
$(AVR_OBJCOPY) -j .text -j .data -O ihex $< $@
@@ -100,6 +102,9 @@ srec: $(AVR_PROGS:%=%.srec)
%.bin: %.avr.elf
$(AVR_OBJCOPY) -j .text -j .data -O binary $< $@
+%.size: %.avr.elf
+ $(AVR_SIZE) $< | grep Full
+
# Rules for building the .eeprom rom images.
EEPROMS := $(AVR_PROGS:%=%_eeprom.hex) $(AVR_PROGS:%=%_eeprom.bin) \
diff --git a/digital/avr/modules/adc/adc.avr.c b/digital/avr/modules/adc/adc.avr.c
index 3bfdefa9..96392a86 100644
--- a/digital/avr/modules/adc/adc.avr.c
+++ b/digital/avr/modules/adc/adc.avr.c
@@ -32,6 +32,10 @@
#elif defined (__AVR_ATmega128__)
#elif defined (__AVR_ATmega64__)
#elif defined (__AVR_ATmega16__)
+# elif defined (__AVR_AT90USB646__)
+# elif defined (__AVR_AT90USB647__)
+# elif defined (__AVR_AT90USB1286__)
+# elif defined (__AVR_AT90USB1287__)
#else
# warning "adc: not tested on this chip."
#endif
@@ -48,7 +52,7 @@
* 11: Internal 2.56V Voltage Reference with external capacitor
* at AREF pin. */
#define ADMUX_CFG (regv (REFS1, REFS0, ADLAR, MUX4, MUX3, MUX2, MUX1, MUX0, \
- 1, 1, 0, 0, 0, 0, 0, 0))
+ 0, 1, 0, 0, 0, 0, 0, 0))
#define ADCSR_CFG (regv (ADEN, ADSC, ADFR, ADIF, ADIE, ADPS2, ADPS1, ADPS0, \
1, 0, 0, 1, 0, 0, 0, 0))
#define ADCSR_CFG_115200 7
diff --git a/digital/avr/modules/devices/servo/Makefile.module b/digital/avr/modules/devices/servo/Makefile.module
new file mode 100644
index 00000000..bf82ffac
--- /dev/null
+++ b/digital/avr/modules/devices/servo/Makefile.module
@@ -0,0 +1 @@
+devices_servo_SOURCES = servo_pos.c servo.avr.c
diff --git a/digital/avr/modules/devices/servo/README b/digital/avr/modules/devices/servo/README
new file mode 100644
index 00000000..4981de17
--- /dev/null
+++ b/digital/avr/modules/devices/servo/README
@@ -0,0 +1,23 @@
+avr.devices.servo - Servo AVR module.
+
+Servo module for AVR. See modules README for more details about AVR modules.
+
+Copyright (C) 2011 Maxime Hadjinlian
+
+APBTeam:
+ Web: http://apbteam.org/
+ Email: team AT apbteam DOT org
+
+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/digital/avr/modules/devices/servo/avrconfig.h b/digital/avr/modules/devices/servo/avrconfig.h
new file mode 100644
index 00000000..d192598a
--- /dev/null
+++ b/digital/avr/modules/devices/servo/avrconfig.h
@@ -0,0 +1,33 @@
+#ifndef avrconfig_h
+#define avrconfig_h
+/* avrconfig.h */
+/* avr.devices.servo - Servo AVR module. {{{
+ *
+ * Copyright (C) 2011 Maxime Hadjinlian
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * 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.
+ *
+ * }}} */
+
+/* servo - Servo module. */
+/** All servos are currently connected to the same port. */
+#define AC_SERVO_PORT PORTA
+#define AC_SERVO_DDR DDRA
+
+#endif /* avrconfig_h */
diff --git a/digital/io/src/servo.avr.c b/digital/avr/modules/devices/servo/servo.avr.c
index de50c819..fc5adc78 100644
--- a/digital/io/src/servo.avr.c
+++ b/digital/avr/modules/devices/servo/servo.avr.c
@@ -1,5 +1,5 @@
/* servo.avr.c */
-/* io - Input & Output with Artificial Intelligence (ai) support on AVR. {{{
+/* avr.devices.servo - Servo AVR module. {{{
*
* Copyright (C) 2008 Dufour Jérémy
*
@@ -22,7 +22,6 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* }}} */
-
#include "common.h"
#include "servo.h"
@@ -36,12 +35,6 @@
*/
/**
- * All servos are connected to the PORTA.
- */
-#define SERVO_PORT PORTA
-#define SERVO_DDR DDRA
-
-/**
* TOP of the timer/counter.
*/
#define SERVO_TCNT_TOP 0xFF
@@ -76,7 +69,7 @@ volatile int8_t servo_updating_id_;
/**
* A table for the time spent by each servo in high state.
*/
-volatile uint8_t servo_high_time_[SERVO_NUMBER];
+volatile uint8_t servo_position_[SERVO_NUMBER];
/**
* Overflow of timer/counter 2 handler.
@@ -90,13 +83,13 @@ void
servo_init (void)
{
/* Set-up all the pins of the servo to out direction */
- SERVO_DDR = 0xff;
+ AC_SERVO_DDR = 0xff;
/* All pins are at low state by default */
/* Set-up the timer/counter 2:
- prescaler 256 => 4.44 ms TOP */
TCCR2 = regv (FOC2, WGM20, COM21, COM20, WGM21, CS22, CS21, CS20,
- 0, 0, 0, 0, 0, 1, 0, 0);
+ 0, 0, 0, 0, 0, 1, 0, 0);
/* The state machine start with the first servo */
servo_updating_id_ = 0;
@@ -107,29 +100,29 @@ servo_init (void)
/* By default, servo init disable all servo. */
uint8_t i;
for (i = 0; i < SERVO_NUMBER; i++)
- servo_set_high_time (i, 0);
+ servo_set_position (i, 0);
}
-/* Set the high time of the input signal of a servo (and its position). */
+/* Set the duration of the input signal at the high state of a servo. */
void
-servo_set_high_time (uint8_t servo, uint8_t high_time)
+servo_set_position (uint8_t servo, uint8_t position)
{
- uint8_t filtered = high_time;
+ uint8_t filtered = position;
if (filtered != 0)
UTILS_BOUND (filtered, SERVO_HIGH_TIME_MIN, SERVO_HIGH_TIME_MAX);
/* Sanity check */
if (servo < SERVO_NUMBER)
/* Set new desired position (high value time) */
- servo_high_time_[servo] = filtered;
+ servo_position_[servo] = filtered;
}
-/* Get the high time of the servo. */
+/* Get the duration of the servo's input signal at high state. */
uint8_t
-servo_get_high_time (uint8_t servo)
+servo_get_position (uint8_t servo)
{
/* Sanity check */
if (servo < SERVO_NUMBER)
- return servo_high_time_[servo];
+ return servo_position_[servo];
return 0;
}
@@ -141,7 +134,7 @@ SIGNAL (SIG_OVERFLOW2)
overflow */
static int8_t servo_overflow_count = -1;
/* Time spent by each servo motor at high state during a whole cycle */
- static uint16_t servo_high_time_cycle = servo_tic_cycle_;
+ static uint16_t servo_position_cycle = servo_tic_cycle_;
/* State machine actions */
if (servo_updating_id_ >= 0)
@@ -151,16 +144,16 @@ SIGNAL (SIG_OVERFLOW2)
/* Set to low state the previous servo motor pin if needed (not for
* the first one) */
if (servo_updating_id_ != 0)
- SERVO_PORT &= ~_BV (servo_updating_id_ - 1);
+ AC_SERVO_PORT &= ~_BV (servo_updating_id_ - 1);
/* Set to high state the current servo motor pin, unless is zero */
- if (servo_high_time_[servo_updating_id_])
- set_bit (SERVO_PORT, servo_updating_id_);
+ if (servo_position_[servo_updating_id_])
+ set_bit (AC_SERVO_PORT, servo_updating_id_);
/* Plan next timer overflow to the TOP minus the current configuration
* of the servo motor */
- TCNT2 = SERVO_TCNT_TOP - servo_high_time_[servo_updating_id_];
+ TCNT2 = SERVO_TCNT_TOP - servo_position_[servo_updating_id_];
/* Update the time spent at high state by all servo motors for this
* cycle */
- servo_high_time_cycle += servo_high_time_[servo_updating_id_];
+ servo_position_cycle += servo_position_[servo_updating_id_];
/* Update the identifier of the current servo motor (and manage when
* we are at the last one) */
if (++servo_updating_id_ == SERVO_NUMBER)
@@ -174,13 +167,13 @@ SIGNAL (SIG_OVERFLOW2)
if (servo_overflow_count == -1)
{
/* Set to low state the previous servo motor pin */
- SERVO_PORT &= ~_BV (SERVO_NUMBER - 1);
+ AC_SERVO_PORT &= ~_BV (SERVO_NUMBER - 1);
/* Number of full overflow (from 0 to SERVO_TCNT_TOP) we need to
* wait (division by SERVO_TCNT_TOP or >> 8) */
- servo_overflow_count = servo_high_time_cycle >> 8;
+ servo_overflow_count = servo_position_cycle >> 8;
/* Restart the counter from remaining TIC that are left and can
* not be used to make a full overflow */
- TCNT2 = SERVO_TCNT_TOP - v16_to_v8 (servo_high_time_cycle, 0);
+ TCNT2 = SERVO_TCNT_TOP - v16_to_v8 (servo_position_cycle, 0);
}
else
{
@@ -193,7 +186,7 @@ SIGNAL (SIG_OVERFLOW2)
servo_updating_id_ = 0;
/* Re-initialize the counter of time spent by each servo motor
* at high state */
- servo_high_time_cycle = servo_tic_cycle_;
+ servo_position_cycle = servo_tic_cycle_;
}
}
}
diff --git a/digital/io/src/servo.h b/digital/avr/modules/devices/servo/servo.h
index b9f7e3ea..59d35907 100644
--- a/digital/io/src/servo.h
+++ b/digital/avr/modules/devices/servo/servo.h
@@ -1,7 +1,7 @@
#ifndef servo_h
#define servo_h
/* servo.h */
-/* io - Input & Output with Artificial Intelligence (ai) support on AVR. {{{
+/* avr.devices.servo - Servo AVR module. {{{
*
* Copyright (C) 2008 Dufour Jérémy
*
@@ -24,7 +24,6 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* }}} */
-
#include "common.h" // uint8_t
/**
@@ -48,7 +47,7 @@
* set-up the timer to overflow a certain number of times to wait before
* restarting the whole cycle.
*
- * All servos are connected to the PORTA of the ATmega.
+ * All servos are connected to AC_SERVO_PORT defined in avrconfig.h
*/
/**
@@ -76,21 +75,22 @@ void
servo_init (void);
/**
- * Set the high time of the input signal of a servo (and its position).
+ * Set the duration of the input signal of a servo at high state
+ * and thus its position.
* @param servo the servo to change the position.
- * @param high_time the high time we want the input signal to spend at the
- * high state to set the servo motor to a position. A zero will let the servo
- * floating.
+ * @param position the duration while the input signal will be at the
+ * high state. The servo will then move to a position.
+ * A zero will let the servo floating.
*/
void
-servo_set_high_time (uint8_t servo, uint8_t high_time);
+servo_set_position (uint8_t servo, uint8_t position);
/**
- * Get the high time of the servo.
+ * Get the duration of the servo's input signal at high state.
* @param servo the servo to get the position of.
* @return the current position of the servo.
*/
uint8_t
-servo_get_high_time (uint8_t servo);
+servo_get_position (uint8_t servo);
#endif /* servo_h */
diff --git a/digital/io/src/servo_pos.c b/digital/avr/modules/devices/servo/servo_pos.c
index d04077fd..6308ceaf 100644
--- a/digital/io/src/servo_pos.c
+++ b/digital/avr/modules/devices/servo/servo_pos.c
@@ -1,5 +1,5 @@
/* servo_pos.c */
-/* io - Input & Output with Artificial Intelligence (ai) support on AVR. {{{
+/* avr.devices.servo - Servo AVR module. {{{
*
* Copyright (C) 2009 Dufour Jérémy
*
@@ -56,5 +56,5 @@ servo_pos_set_high_time (uint8_t servo_id,
void
servo_pos_move_to (uint8_t servo_id, uint8_t position)
{
- servo_set_high_time (servo_id, servo_pos_high_time[servo_id][position]);
+ servo_set_position (servo_id, servo_pos_high_time[servo_id][position]);
}
diff --git a/digital/io/src/servo_pos.h b/digital/avr/modules/devices/servo/servo_pos.h
index c8e56d2b..e173ab6d 100644
--- a/digital/io/src/servo_pos.h
+++ b/digital/avr/modules/devices/servo/servo_pos.h
@@ -1,7 +1,7 @@
#ifndef servo_pos_h
#define servo_pos_h
-/* servo_pos.h */
-/* io - Input & Output with Artificial Intelligence (ai) support on AVR. {{{
+/* servo.pos.h */
+/* avr.devices.servo - Servo AVR module. {{{
*
* Copyright (C) 2009 Dufour Jérémy
*
diff --git a/digital/avr/modules/devices/servo/test/Makefile b/digital/avr/modules/devices/servo/test/Makefile
new file mode 100644
index 00000000..a0ad639f
--- /dev/null
+++ b/digital/avr/modules/devices/servo/test/Makefile
@@ -0,0 +1,12 @@
+BASE = ../../../..
+AVR_PROGS = test_servo
+test_servo_SOURCES = test_servo.c
+MODULES = proto devices/servo uart utils
+CONFIGFILE = avrconfig.h
+# atmega8, atmega8535, atmega128...
+AVR_MCU = atmega128
+# -O2 : speed
+# -Os : size
+OPTIMIZE = -O2
+
+include $(BASE)/make/Makefile.gen
diff --git a/digital/avr/modules/devices/servo/test/avrconfig.h b/digital/avr/modules/devices/servo/test/avrconfig.h
new file mode 100644
index 00000000..6ee81392
--- /dev/null
+++ b/digital/avr/modules/devices/servo/test/avrconfig.h
@@ -0,0 +1,91 @@
+#ifndef avrconfig_h
+#define avrconfig_h
+/* avrconfig.h */
+/* avr.devices.servo - Servo AVR module. {{{
+ *
+ * Copyright (C) 2011 Maxime Hadjinlian
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * 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.
+ *
+ * }}} */
+
+/* global */
+/** AVR Frequency : 1000000, 1843200, 2000000, 3686400, 4000000, 7372800,
+ * 8000000, 11059200, 14745600, 16000000, 18432000, 20000000. */
+#define AC_FREQ 14745600
+
+/* servo - Servo module. */
+/** All servos are currently connected to the same port. */
+#define AC_SERVO_PORT PORTA
+#define AC_SERVO_DDR DDRA
+
+/* uart - UART module. */
+/** Select hardware uart for primary uart: 0, 1 or -1 to disable. */
+#define AC_UART0_PORT 1
+/** Baudrate: 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600, 76800,
+ * 115200, 230400, 250000, 500000, 1000000. */
+#define AC_UART0_BAUDRATE 38400
+/** Send mode:
+ * - POLLING: no interrupts.
+ * - RING: interrupts, ring buffer. */
+#define AC_UART0_SEND_MODE RING
+/** Recv mode, same as send mode. */
+#define AC_UART0_RECV_MODE RING
+/** Character size: 5, 6, 7, 8, 9 (only 8 implemented). */
+#define AC_UART0_CHAR_SIZE 8
+/** Parity : ODD, EVEN, NONE. */
+#define AC_UART0_PARITY EVEN
+/** Stop bits : 1, 2. */
+#define AC_UART0_STOP_BITS 1
+/** Send buffer size, should be power of 2 for RING mode. */
+#define AC_UART0_SEND_BUFFER_SIZE 32
+/** Recv buffer size, should be power of 2 for RING mode. */
+#define AC_UART0_RECV_BUFFER_SIZE 32
+/** If the send buffer is full when putc:
+ * - DROP: drop the new byte.
+ * - WAIT: wait until there is room in the send buffer. */
+#define AC_UART0_SEND_BUFFER_FULL DROP
+/** In HOST compilation:
+ * - STDIO: use stdin/out.
+ * - PTS: use pseudo terminal. */
+#define AC_UART0_HOST_DRIVER STDIO
+/** Same thing for secondary port. */
+#define AC_UART1_PORT -1
+#define AC_UART1_BAUDRATE 115200
+#define AC_UART1_SEND_MODE RING
+#define AC_UART1_RECV_MODE RING
+#define AC_UART1_CHAR_SIZE 8
+#define AC_UART1_PARITY EVEN
+#define AC_UART1_STOP_BITS 1
+#define AC_UART1_SEND_BUFFER_SIZE 32
+#define AC_UART1_RECV_BUFFER_SIZE 32
+#define AC_UART1_SEND_BUFFER_FULL WAIT
+#define AC_UART1_HOST_DRIVER PTS
+
+/* proto - Protocol module. */
+/** Maximum argument size. */
+#define AC_PROTO_ARGS_MAX_SIZE 8
+/** Callback function name. */
+#define AC_PROTO_CALLBACK proto_callback
+/** Putchar function name. */
+#define AC_PROTO_PUTC uart0_putc
+/** Support for quote parameter. */
+#define AC_PROTO_QUOTE 1
+
+#endif /* avrconfig_h */
diff --git a/digital/avr/modules/devices/servo/test/test_servo.c b/digital/avr/modules/devices/servo/test/test_servo.c
new file mode 100644
index 00000000..924fae1c
--- /dev/null
+++ b/digital/avr/modules/devices/servo/test/test_servo.c
@@ -0,0 +1,86 @@
+/* test_servo.c. */
+/* avr.servo - Servo AVR module. {{{
+ *
+ * Copyright (C) 2011 Maxime Hadjinlian
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * 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 "common.h"
+#include "modules/uart/uart.h"
+#include "modules/proto/proto.h"
+#include "modules/devices/servo/servo.h"
+#include "modules/utils/utils.h"
+#include "modules/utils/byte.h"
+#include "io.h"
+
+/* proto_callback is called by proto
+ * when a command is complete and valid.
+ * proto act as an intelligent buffer for us.
+*/
+void
+proto_callback (uint8_t cmd, uint8_t size, uint8_t *args)
+{
+ /* This macro combine command and size in one integer. */
+#define c(cmd, size) (cmd << 8 | size)
+ switch (c (cmd, size))
+ {
+ case c ('z', 0):
+ /* This should be generaly implemented. */
+ utils_reset ();
+ break;
+ case c ('s', 3):
+ /* We are looking to receive a command in the form !sxxyyyy
+ * where xx is the servo id and yyyy is the command itself.
+ * For the size, please read digital/avr/modules/proto/proto.txt
+ */
+ servo_set_position (args[0], v8_to_v16 (args[1], args[2]));
+ break;
+ default:
+ /* This is to handle default commands, return an error. */
+ proto_send0 ('?');
+ return;
+ }
+ /* When no error acknoledge. */
+ proto_send (cmd, size, args);
+#undef c
+}
+
+int
+main (int argc, char **argv)
+{
+ avr_init (argc, argv);
+ sei ();
+ uart0_init ();
+ servo_init ();
+
+ /* This command should be generaly sent on reset. */
+ proto_send0 ('z');
+ /* This is to accept commands. */
+ while (1)
+ {
+ uint8_t c = uart0_getc ();
+ proto_accept (c);
+ /* once the command is complete according to
+ * proto's state machine, proto_callback will
+ * be called with the full command.
+ */
+ }
+}
diff --git a/digital/avr/modules/devices/usdist/Makefile.module b/digital/avr/modules/devices/usdist/Makefile.module
new file mode 100644
index 00000000..61691300
--- /dev/null
+++ b/digital/avr/modules/devices/usdist/Makefile.module
@@ -0,0 +1 @@
+devices_usdist_SOURCES = usdist.c
diff --git a/digital/avr/modules/devices/usdist/README b/digital/avr/modules/devices/usdist/README
new file mode 100644
index 00000000..5ddb8aa6
--- /dev/null
+++ b/digital/avr/modules/devices/usdist/README
@@ -0,0 +1,23 @@
+usdist - Analog US distance sensor support.
+
+Used with Sensopart UT20-700.
+
+Copyright (C) 2011 Nicolas Schodet
+
+APBTeam:
+ Web: http://apbteam.org/
+ Email: team AT apbteam DOT org
+
+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/digital/avr/modules/devices/usdist/avrconfig.h b/digital/avr/modules/devices/usdist/avrconfig.h
new file mode 100644
index 00000000..2a908794
--- /dev/null
+++ b/digital/avr/modules/devices/usdist/avrconfig.h
@@ -0,0 +1,40 @@
+#ifndef avrconfig_h
+#define avrconfig_h
+/* avrconfig.h - TWI module configuration template. */
+/* usdist - Analog US distance sensor support. {{{
+ *
+ * Copyright (C) 2011 Nicolas Schodet
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * 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.
+ *
+ * }}} */
+
+/* usdist - Analog US distance sensor. */
+/** Number of sensors. */
+#define AC_USDIST_NB 4
+/** Measuring period, in number of update call. */
+#define AC_USDIST_PERIOD 2
+/** List of space separated sensor definition, see usdist.h. */
+#define AC_USDIST_SENSORS \
+ USDIST_SENSOR (0, G, 3) \
+ USDIST_SENSOR (1, G, 1) \
+ USDIST_SENSOR (2, C, 7) \
+ USDIST_SENSOR (3, D, 4)
+
+#endif /* avrconfig_h */
diff --git a/digital/io/src/usdist.c b/digital/avr/modules/devices/usdist/usdist.c
index d6fd9730..75c7899b 100644
--- a/digital/io/src/usdist.c
+++ b/digital/avr/modules/devices/usdist/usdist.c
@@ -24,15 +24,15 @@
* }}} */
#include "common.h"
#include "usdist.h"
-#include "timer.h"
#include "modules/adc/adc.h"
#include "modules/utils/utils.h"
#include "io.h"
+/* This include is to be defined by user program. */
#include "simu.host.h"
-uint16_t usdist_mm[USDIST_NB];
+uint16_t usdist_mm[AC_USDIST_NB];
/** Describe a sensor. */
struct usdist_sensor_t
@@ -49,12 +49,9 @@ struct usdist_sensor_t
/** Define sensors configuration. */
#define USDIST_SENSOR(adc, p, n) \
- { adc, &IO_PORT_ (p, n), &IO_DDR_ (p, n), IO_BV_ (p, n) }
-struct usdist_sensor_t usdist_sensors[USDIST_NB] = {
- USDIST_SENSOR (0, G, 3),
- USDIST_SENSOR (1, G, 1),
- USDIST_SENSOR (2, C, 7),
- USDIST_SENSOR (3, D, 4),
+ { adc, &IO_PORT_ (p, n), &IO_DDR_ (p, n), IO_BV_ (p, n) },
+struct usdist_sensor_t usdist_sensors[AC_USDIST_NB] = {
+ AC_USDIST_SENSORS
};
void
@@ -62,7 +59,7 @@ usdist_init (void)
{
uint8_t i;
adc_init ();
- for (i = 0; i < USDIST_NB; i++)
+ for (i = 0; i < AC_USDIST_NB; i++)
{
usdist_mm[i] = 0xffff;
*usdist_sensors[i].sync_port &= ~usdist_sensors[i].sync_bv;
@@ -106,13 +103,13 @@ usdist_update (void)
if (usdist_mm[current] >= USDIST_MM_TOO_FAR)
usdist_mm[current] = 0xffff;
/* Next. */
- current = (current + 1) % USDIST_NB;
+ current = (current + 1) % AC_USDIST_NB;
}
init = 1;
/* Prepare next measure. */
*usdist_sensors[current].sync_port |=
usdist_sensors[current].sync_bv;
- wait = USDIST_PERIOD_CYCLE;
+ wait = AC_USDIST_PERIOD;
/* New mesure done. */
return 1;
}
diff --git a/digital/io/src/usdist.h b/digital/avr/modules/devices/usdist/usdist.h
index 9a4a6646..37683091 100644
--- a/digital/io/src/usdist.h
+++ b/digital/avr/modules/devices/usdist/usdist.h
@@ -1,9 +1,9 @@
#ifndef usdist_h
#define usdist_h
/* usdist.h */
-/* io - Input & Output with Artificial Intelligence (ai) support on AVR. {{{
+/* usdist - Analog US distance sensor support. {{{
*
- * Copyright (C) 2010 Nicolas Schodet
+ * Copyright (C) 2011 Nicolas Schodet
*
* APBTeam:
* Web: http://apbteam.org/
@@ -27,11 +27,13 @@
/*
* Manage ultrasonic distance sensors using analog to digital converter.
+ *
+ * AC_USDIST_SENSORS should be set to a list of space separated USDIST_SENSOR
+ * macro calls:
+ *
+ * USDIST_SENSOR (adc_number, synchro_io_port, synchro_io_n)
*/
-/** Number of sensors. */
-#define USDIST_NB 4
-
/** Minimal calibrated distance. */
#define USDIST_MM_MIN 100
@@ -41,11 +43,8 @@
/** Distance considered as too far to be true. */
#define USDIST_MM_TOO_FAR 650
-/** Measuring period in cycles. */
-#define USDIST_PERIOD_CYCLE (uint8_t) (8.0 / TIMER_PERIOD_MS)
-
/** Array containing the last measures in millimeters. */
-extern uint16_t usdist_mm[USDIST_NB];
+extern uint16_t usdist_mm[AC_USDIST_NB];
/** Initialise module. */
void
diff --git a/digital/avr/modules/twi/twi_hard.avr.c b/digital/avr/modules/twi/twi_hard.avr.c
index 8bd18d34..71483ecb 100644
--- a/digital/avr/modules/twi/twi_hard.avr.c
+++ b/digital/avr/modules/twi/twi_hard.avr.c
@@ -56,6 +56,7 @@
# if defined (__AVR_ATmega32__)
# elif defined (__AVR_ATmega64__)
# elif defined (__AVR_ATmega128__)
+# elif defined (__AVR_ATmega164P__)
# elif defined (__AVR_AT90USB646__)
# elif defined (__AVR_AT90USB647__)
# elif defined (__AVR_AT90USB1286__)
diff --git a/digital/avr/modules/uart/uart.avr.c b/digital/avr/modules/uart/uart.avr.c
index 689866ae..0b0ab107 100644
--- a/digital/avr/modules/uart/uart.avr.c
+++ b/digital/avr/modules/uart/uart.avr.c
@@ -35,6 +35,7 @@
#if defined (__AVR_ATmega8__)
#elif defined (__AVR_ATmega8535__)
#elif defined (__AVR_ATmega16__)
+#elif defined (__AVR_ATmega164P__)
#elif defined (__AVR_ATmega32__)
#elif defined (__AVR_ATmega64__)
#elif defined (__AVR_ATmega128__)
diff --git a/digital/beacon/simu/Makefile b/digital/beacon/simu/Makefile
new file mode 100644
index 00000000..132f0b2e
--- /dev/null
+++ b/digital/beacon/simu/Makefile
@@ -0,0 +1,12 @@
+BASE = ../../avr
+HOST_PROGS = beacon
+beacon_SOURCES = beacon.c position.c
+MODULES = math/fixed utils
+CONFIGFILE = avrconfig.h
+# atmega8, atmega8535, atmega128...
+AVR_MCU = atmega128
+# -O2 : speed
+# -Os : size
+OPTIMIZE = -O2 -lm
+
+include $(BASE)/make/Makefile.gen
diff --git a/digital/beacon/simu/avrconfig.h b/digital/beacon/simu/avrconfig.h
new file mode 100644
index 00000000..8da6dbc6
--- /dev/null
+++ b/digital/beacon/simu/avrconfig.h
@@ -0,0 +1,39 @@
+#ifndef avrconfig_h
+#define avrconfig_h
+/* avrconfig.h - Path module configuration template. */
+/* avr.path - Path finding module. {{{
+ *
+ * Copyright (C) 2008 Nicolas Schodet
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * 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.
+ *
+ * }}} */
+
+/* path - Path finding module. */
+/** Report path found for debug. */
+#define AC_PATH_REPORT defined (HOST)
+/** Report function name. */
+#define AC_PATH_REPORT_CALLBACK path_report
+/** Number of possible obstacles. */
+#define AC_PATH_OBSTACLES_NB 10
+/** Number of points per obstacle. */
+#define AC_PATH_OBSTACLES_POINTS_NB 8
+
+
+#endif /* avrconfig_h */
diff --git a/digital/beacon/simu/beacon.c b/digital/beacon/simu/beacon.c
new file mode 100644
index 00000000..5ea8a263
--- /dev/null
+++ b/digital/beacon/simu/beacon.c
@@ -0,0 +1,106 @@
+/* beacon.c */
+/* Beacon Simulator Interface. {{{
+ *
+ * Copyright (C) 2011 Florent Duchon
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include "position.h"
+#include "common.h"
+
+/* Globals Declaration */
+beacon_value_s beacon;
+opponent_s opponent;
+
+void syntax (void)
+{
+ fprintf (stderr,
+ "beacon sources_number source1 angle1 ... sourceX angleX\n"
+ "example: beacon 2,1,3.2,3,0.82\n"
+ );
+ exit (1);
+}
+
+void read_tab (const char *s, double *tab, int n)
+{
+ assert (n > 0);
+ while (n)
+ {
+ char *sp;
+ double v;
+ v = strtod (s, &sp);
+ if (sp == s)
+ syntax ();
+ if ((n > 1 && *sp != ',')
+ || (n == 1 && *sp != '\0'))
+ syntax ();
+ s = sp + 1;
+ *tab++ = v;
+ n--;
+ }
+}
+
+int main (int argc, char **argv)
+{
+ if (argc < 8 || argc > 10)
+ syntax ();
+
+ double input[7] = {0};
+ /* Init global structures */
+ init_struct();
+
+
+ /* Read Beacon num */
+ read_tab (argv[2], input, 1);
+
+ /* Read Beacon angle */
+ read_tab (argv[3], input+1, 1);
+
+ /* Read Beacon num */
+ read_tab (argv[4], input+2, 1);
+
+ /* Read Beacon angle */
+ read_tab (argv[5], input+3, 1);
+
+ /* Read Activate filter */
+ read_tab (argv[6],input+4, 1);
+
+ /* Read last x */
+ read_tab (argv[7],input+5, 1);
+
+ /* Read last y */
+ read_tab (argv[8],input+6, 1);
+
+// printf("Balise %d --- Angle %f\n",(int)input[0],input[1]);
+// printf("Balise %d --- Angle %f\n",(int)input[2],input[3]);
+
+ /* Compute position */
+ update_position(input[0],input[1]);
+ update_position(input[2],input[3]);
+
+ /* Return position to the simulator */
+ printf("%d\n",(int)opponent.x);
+ printf("%d\n",(int)opponent.y);
+
+ return 0;
+}
diff --git a/digital/beacon/simu/position.c b/digital/beacon/simu/position.c
new file mode 100644
index 00000000..5bc4a8f8
--- /dev/null
+++ b/digital/beacon/simu/position.c
@@ -0,0 +1,103 @@
+/* position.c */
+/* Beacon triangulation algorithms. {{{
+ *
+ * Copyright (C) 2011 Florent Duchon
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * 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 <stdio.h>
+#include "position.h"
+
+extern beacon_value_s beacon;
+extern opponent_s opponent;
+
+void init_struct(void)
+{
+ beacon.angle[0]=0;
+ beacon.angle[1]=0;
+ beacon.angle[2]=0;
+ beacon.angle[3]=0;
+ beacon.last_updated_beacon = 0;
+ beacon.before_last_updated_beacon = 0;
+ opponent.x = 0;
+ opponent.y = 0;
+}
+
+float degree_to_radian(int value)
+{
+ float temp = 0;
+ temp = (value * 2 * M_PI) / 360;
+ return temp;
+}
+
+void update_position(int beacon_number,double angle)
+{
+ int which_formula = 0;
+ if(beacon_number == beacon.last_updated_beacon)
+ {
+ beacon.last_updated_beacon = beacon_number;
+ }
+ else
+ {
+ beacon.before_last_updated_beacon = beacon.last_updated_beacon;
+ beacon.last_updated_beacon = beacon_number;
+ }
+ which_formula = beacon.before_last_updated_beacon + beacon.last_updated_beacon;
+// printf("[position.c] => Update_position beacon_number = %d angle = %f\n",(int)beacon_number,(double)angle);
+ beacon.angle[beacon_number] = angle;
+
+ switch(which_formula)
+ {
+ case 3:
+// printf("[position.c] => Formula 3\r\n");
+// printf("[position.c] => angle[1] = %f angle[2] = %f\n",beacon.angle[1],beacon.angle[2]);
+ opponent.x = LARGEUR_TABLE * tan(beacon.angle[2]) * tan(beacon.angle[1]) / (tan(beacon.angle[2])+tan(beacon.angle[1]));
+ opponent.y = LARGEUR_TABLE * tan(beacon.angle[1]) / (tan(beacon.angle[2])+tan(beacon.angle[1]));
+ break;
+ case 4:
+// printf("[position.c] => Formula 4\r\n");
+ if(beacon.angle[3] > M_PI/2)
+ {
+ opponent.y = (LARGEUR_DEMI_TABLE*tan(M_PI - beacon.angle[3]) - LARGEUR_TABLE*tan(beacon.angle[1]) + LONGUEUR_TABLE) / (tan(M_PI - beacon.angle[3]) - tan(beacon.angle[1]));
+ }
+ else
+ {
+ opponent.y = (LARGEUR_DEMI_TABLE*tan(beacon.angle[3]) + LARGEUR_TABLE*tan(beacon.angle[1])-LONGUEUR_TABLE) / (tan(beacon.angle[1]) + tan(beacon.angle[3]));
+ }
+ opponent.x = (LARGEUR_TABLE - opponent.y)*tan(beacon.angle[1]);
+ break;
+ case 5:
+// printf("[position.c] => formula 5\r\n");
+ if(beacon.angle[3] > M_PI/2)
+ {
+ opponent.y = (LONGUEUR_TABLE + LARGEUR_DEMI_TABLE * tan(M_PI - beacon.angle[3])) / (tan(beacon.angle[2]) + tan(M_PI - beacon.angle[3]));
+ }
+ else
+ {
+ opponent.y = (LARGEUR_DEMI_TABLE*tan(beacon.angle[3]) - LONGUEUR_TABLE) / (tan(beacon.angle[3]) - tan(beacon.angle[2]));
+ }
+ opponent.x = tan(beacon.angle[2]) * opponent.y;
+ break;
+ default:
+// printf("[position.c] => Unknown Formula\r\n");
+ break;
+ }
+} \ No newline at end of file
diff --git a/digital/beacon/simu/position.h b/digital/beacon/simu/position.h
new file mode 100644
index 00000000..de962e5a
--- /dev/null
+++ b/digital/beacon/simu/position.h
@@ -0,0 +1,59 @@
+/* position.h */
+/* Beacon triangulation algorithms. {{{
+ *
+ * Copyright (C) 2011 Florent Duchon
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * 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.
+ *
+ * }}} */
+
+#ifndef _POSITION_H
+#define _POSITION_H
+
+#define LARGEUR_TABLE 2000
+#define LONGUEUR_TABLE 3000
+#define LARGEUR_DEMI_TABLE LARGEUR_TABLE/2
+#define M_PI 3.14
+
+typedef struct
+{
+ float angle[4];
+ int last_updated_beacon;
+ int before_last_updated_beacon;
+
+}beacon_value_s;
+
+typedef struct
+{
+ int x;
+ int y;
+ int old_x;
+ int old_y;
+}opponent_s;
+
+typedef struct
+{
+ int lost_beacon;
+}status_s;
+
+void init_struct(void);
+void update_position(int beacon_number,double angle);
+void distance_filter(void);
+
+#endif \ No newline at end of file
diff --git a/digital/beacon/simu/simulator.py b/digital/beacon/simu/simulator.py
new file mode 100644
index 00000000..4284b3d0
--- /dev/null
+++ b/digital/beacon/simu/simulator.py
@@ -0,0 +1,322 @@
+# simu - Beacon simulation. {{{
+#
+# Copyright (C) 2011 Florent DUCHON
+#
+# APBTeam:
+# Web: http://apbteam.org/
+# Email: team AT apbteam DOT org
+#
+# 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.
+#
+# }}}
+
+"""Graphic interface for beacon simulator."""
+
+import re
+from Tkinter import *
+from simu.inter.drawable import *
+from subprocess import Popen, PIPE
+from math import pi
+import math
+import random
+import decimal
+
+class Obstacle:
+ def __init__ (self, pos, radius, factor):
+ self.pos = pos
+ self.radius = radius
+ self.factor = factor
+
+ def move (self, pos):
+ self.pos = pos
+
+
+class Beacon (Drawable):
+ def __init__ (self,onto, num, pos, orientation, size):
+ Drawable.__init__ (self, onto)
+ self.id = num # ID
+ self.pos = pos # position (x,y)
+ self.orientation = orientation # orientation in degrees
+ self.size = size # side size
+ self.angle = 0 # obstacles angle
+ self.mode = 0 # 0 = deactivated
+ # 1 = activated
+ def draw_beacon (self):
+ # Color depends of the beacon mode
+ if self.mode is 1:
+ color = 'black'
+ else:
+ color = 'red'
+ # Draw it
+ self.draw_rectangle ((self.pos[0]-self.size/2,self.pos[1]-self.size/2),(self.pos[0]+self.size/2,self.pos[1]+self.size/2), fill = color)
+
+ def draw_axes (self):
+ self.draw_line (self.pos,(self.pos[0]+(300)*math.cos(math.radians(self.orientation)),self.pos[1]+300*math.sin(math.radians(self.orientation))),fill='red', arrow = LAST)
+ self.draw_line (self.pos,(self.pos[0]+(300)*math.cos(math.radians(self.orientation+90)),self.pos[1]+300*math.sin(math.radians(self.orientation+90))),fill='red', arrow = LAST)
+
+ def toogle_mode (self):
+ if self.mode is 0:
+ self.mode = 1
+ else:
+ self.mode = 0
+
+
+class Area (Drawable):
+ def __init__ (self, onto, border_min, border_max):
+ Drawable.__init__ (self, onto)
+ self.border_min = border_min
+ self.border_max = border_max
+ self.border = None
+ self.phantoms_counter = 0
+ self.obstacles = [ ]
+ self.beacons = [ ]
+ self.phantoms = [ ] # virtual obstacles computed by the beacon module.
+
+ def draw (self):
+ self.reset ()
+ self.draw_rectangle (self.border_min, self.border_max, fill = 'grey')
+ self.draw_rectangle ((self.border_min[0],self.border_max[1]-500),(self.border_min[0]+500,self.border_max[1]), fill = 'blue')
+ self.draw_rectangle ((self.border_max[0]-500,self.border_max[1]-500), self.border_max, fill = 'red')
+ self.draw_line ((0,0),(150,0),fill='black', arrow = LAST)
+ self.draw_line ((0,0),(0,150),fill='black', arrow = LAST)
+
+ for b in self.beacons:
+ if b.pos is not None:
+ b.draw_beacon ()
+ for o in self.obstacles:
+ if o.pos is not None:
+ self.draw_circle (o.pos, o.radius,fill = o.factor and 'gray50' or 'gray25')
+ for p in self.phantoms:
+ if p is not None:
+ self.draw_circle (p, 20,fill = 0 and 'gray50' or 'red')
+
+ def show_angles (self):
+ for b in self.beacons:
+ for o in self.obstacles:
+ self.draw_line ((b.pos[0],b.pos[1]),(o.pos[0],o.pos[1]),fill='cyan', arrow = NONE)
+
+ def populate (self):
+ self.obstacles.append (Obstacle ((500, 500), 200, 0))
+ self.beacons.append (Beacon (self, 1, (-40,2040), 270,80))
+ self.beacons.append (Beacon (self, 2, (-40,-40),0,80))
+ self.beacons.append (Beacon (self, 3, (3040,1000), 180,80))
+
+ def add_phantom (self,center):
+ # Only take care of the 100 latest value. Delete previous one.
+ if self.phantoms_counter is 100:
+ del self.phantoms[0]
+ else:
+ self.phantoms_counter += 1
+ self.phantoms.append(center)
+
+
+class AreaView (DrawableCanvas):
+ def __init__ (self, border_min, border_max, master = None):
+ self.border_min = border_min
+ self.border_max = border_max
+ width = border_max[0] - border_min[0]
+ height = border_max[1] - border_min[0]
+ DrawableCanvas.__init__ (self, width * 1.3, height * 1.3, -width / 2,-height / 2,master, borderwidth = 1, relief = 'sunken', background = 'white')
+ self.area = Area (self, border_min, border_max)
+ self.area.populate ()
+
+ def draw (self):
+ self.area.draw ()
+
+ def add_phantom (self,center):
+ self.area.add_phantom(center)
+
+
+class beacon_simu (Frame):
+ def __init__ (self, border_min, border_max, master = None):
+ Frame.__init__ (self, master)
+ self.pack (expand = 1, fill = 'both')
+ self.createWidgets (border_min, border_max)
+ self.robot_pos.set("Robot position = (0 , 0)")
+ self.phantom_pos.set("Last phantom position = ")
+
+ def createWidgets (self, border_min, border_max):
+ # Bottom Panel
+ self.bottomFrame = Frame (self)
+ self.bottomFrame.pack (side = 'bottom', fill = 'both')
+
+ # First subPanel for display options
+ self.subPanel1 = Frame (self.bottomFrame)
+ self.subPanel1.pack (side = 'left', fill = 'both')
+ self.display_axes = IntVar ()
+ self.axesButton = Checkbutton (self.subPanel1,variable = self.display_axes, command = self.update,text = 'Display axes', indicatoron = True)
+ self.axesButton.pack (anchor='w')
+ self.display_angles = IntVar ()
+ self.anglesButton = Checkbutton (self.subPanel1,variable = self.display_angles, command = self.update,text = 'Display angles', indicatoron = True)
+ self.anglesButton.pack (anchor='w')
+
+ # Second subPanel for simulator options
+ self.subPanel2 = Frame (self.bottomFrame)
+ self.subPanel2.pack (side = 'left', fill = 'both')
+ self.mode = StringVar()
+ self.manualRadioButton = Radiobutton (self.subPanel2, text = 'Manual', variable = self.mode, value='manual').pack(anchor='w')
+ self.autoRadioButton = Radiobutton (self.subPanel2, text = 'Auto', variable = self.mode, value='auto').pack(anchor='w')
+
+ # Third subPanel for simulator options
+ self.subPanel3 = Frame (self.bottomFrame)
+ self.subPanel3.pack (side = 'left', fill = 'both')
+ self.precisionScale = Scale (self.subPanel3, label = 'Precision', orient = 'horizontal', from_ = 1, to = 3)
+ self.precisionScale.pack ()
+
+ # Fourth subPanel for buttons
+ self.subPanel4 = Frame (self.bottomFrame)
+ self.subPanel4.pack (side = 'left', fill = 'both')
+ self.clearPhantomsButton = Button (self.subPanel4, text = 'Clear', command = self.clear_phantoms)
+ self.clearPhantomsButton.pack (side = 'bottom')
+ self.startButton = Button (self.subPanel4, text = 'Start', command = self.start)
+ self.startButton.pack (side = 'top')
+
+ # Fifth subPanel for Label
+ self.subPanel5 = Frame (self.bottomFrame)
+ self.subPanel5.pack (side = 'left', fill = 'both')
+ self.robot_pos = StringVar()
+ self.label = Label(self.subPanel5, textvariable=self.robot_pos).pack(anchor='w')
+ self.phantom_pos = StringVar()
+ self.label = Label(self.subPanel5, textvariable=self.phantom_pos).pack(anchor='w')
+
+ # Sixth subPanel for Exit button
+ self.subPanel6 = Frame (self.bottomFrame)
+ self.subPanel6.pack (side = 'right', fill = 'both')
+ self.quitButton = Button (self.subPanel6, text = 'Quit', command = self.quit)
+ self.quitButton.pack (side = 'right', fill = 'both')
+
+ self.areaview = AreaView (border_min, border_max, self)
+ self.areaview.pack (expand = True, fill = 'both')
+ self.areaview.bind ('<1>', self.click)
+
+ def clear (self):
+ self.areaview.area.draw ()
+
+ def clear_phantoms (self):
+ del self.areaview.area.phantoms[:]
+ self.areaview.area.phantoms_counter = 0
+ self.update()
+
+ def update (self):
+ self.areaview.area.update ()
+ self.areaview.area.draw ()
+ if self.display_angles.get() is 1:
+ self.areaview.area.show_angles()
+ if self.display_axes.get() is 1:
+ for b in self.areaview.area.beacons:
+ b.draw_axes()
+
+ def click (self, ev):
+ pos = self.areaview.screen_coord ((ev.x, ev.y))
+
+ # Update obstacles position
+ for o in self.areaview.area.obstacles:
+ if self.areaview.area.border_min[0] < pos[0] < self.areaview.area.border_max[0] and self.areaview.area.border_min[1] < pos[1] < self.areaview.area.border_max[1]:
+ o.pos = pos
+ self.robot_pos.set("Robot position = (%.0f , %.0f)" % pos)
+
+ # Check beacon mode
+ for b in self.areaview.area.beacons:
+ dx = abs(b.pos[0] - pos[0])
+ dy = abs(b.pos[1] - pos[1])
+ if dx < b.size and dy < b.size:
+ b.toogle_mode ()
+ # Update area
+ self.update ()
+
+ def call_algorithm (self,num1,num2):
+ args = [0,0,0,0,0,0,0,0]
+ for b in self.areaview.area.beacons:
+ if b.id is num1:
+ args[1]=num1
+ args[2]=b.angle
+ if b.id is num2:
+ args[3]=num2
+ args[4]=b.angle
+ args = [repr(a) for a in args]
+ args[0:0] = [ './beacon.host' ]
+ p = Popen (args, stdout = PIPE)
+ output = p.communicate ()[0]
+ del p
+ output = output.split ('\n')
+ return output
+
+ def rotate_beacons (self): # Simulate a rotation for a all beacons, ie set beacon.angles.
+ # Set the requested imprecision
+ imprecision = self.precisionScale.get () #1 to 3 degrees
+ imprecision = int (math.radians(imprecision)*1000)
+ imprecision = decimal.Decimal(random.randrange(-imprecision,imprecision))/1000
+ # Compute angles for every beaconss
+ for o in self.areaview.area.obstacles:
+ for b in self.areaview.area.beacons:
+ if b.id is 1:
+ b.angle = math.atan(o.pos[0]/(2000-o.pos[1]))+float(imprecision)
+ if b.id is 2:
+ b.angle = math.atan(o.pos[0]/o.pos[1])+float(imprecision)
+ if b.id is 3:
+ b.angle = math.atan((3000-o.pos[0])/(1000-o.pos[1]))+float(imprecision)
+ if b.angle < 0:
+ b.angle = pi - abs(b.angle)
+
+ def manual_mode (self):
+ # Manual mode : warning : two beacons must already be activated
+ self.rotate_beacons ()
+ temp = [0,0,0]
+ i = 0
+ for b in self.areaview.area.beacons:
+ if b.mode is 1:
+ temp[i] = b.id
+ i=i+1
+ phantom_pos = self.call_algorithm(temp[0],temp[1])
+ self.areaview.add_phantom((int (phantom_pos[0]),int (phantom_pos[1])))
+ self.phantom_pos.set("Last phantom position = (%.0f , %.0f)" %(float(phantom_pos[0]),float(phantom_pos[1])))
+ self.update ()
+
+ def automatic_mode (self):
+ # Automatic mode : all beacons are used
+ self.rotate_beacons ()
+
+ # Randomly select two beacons and update obstacles position
+ exclude = random.randrange(1,4)
+ if exclude is 1:
+ phantom_pos = self.call_algorithm(2,3)
+ if exclude is 2:
+ phantom_pos = self.call_algorithm(1,3)
+ if exclude is 3:
+ phantom_pos = self.call_algorithm(1,2)
+
+ # Draw the computed position
+ self.areaview.add_phantom((int (phantom_pos[0]),int (phantom_pos[1])))
+ self.phantom_pos.set("Last phantom position = (%.0f , %.0f)" %(float(phantom_pos[0]),float(phantom_pos[1])))
+
+ def start (self) :
+ if self.mode.get() == "manual":
+ self.manual_mode()
+ return
+ if self.mode.get() == "auto":
+ #for o in self.areaview.area.obstacles:
+ #x = o.pos[0] + float (decimal.Decimal(random.randrange(-5,40)))
+ #y = o.pos[1] + float (decimal.Decimal(random.randrange(-25,25)))
+ #o.pos = (x,y)
+ self.automatic_mode()
+ self.after (30,self.start)
+ self.update()
+ else:
+ print "No mode selected"
+ return
+
+if __name__ == '__main__':
+ app = beacon_simu ((0, 0), (3000, 2000))
+ app.mainloop ()
diff --git a/digital/cms-intro/pcb/orders/eurocircuits_2011-05-11/cms_intro.GBL b/digital/cms-intro/pcb/orders/eurocircuits_2011-05-11/cms_intro.GBL
new file mode 100644
index 00000000..b0ed3258
--- /dev/null
+++ b/digital/cms-intro/pcb/orders/eurocircuits_2011-05-11/cms_intro.GBL
@@ -0,0 +1,2556 @@
+G75*
+G70*
+%OFA0B0*%
+%FSLAX24Y24*%
+%IPPOS*%
+%LPD*%
+%AMOC8*
+5,1,8,0,0,1.08239X$1,22.5*
+%
+%ADD10OC8,0.0640*%
+%ADD11C,0.0436*%
+%ADD12C,0.0100*%
+%ADD13C,0.0400*%
+D10*
+X000651Y011568D03*
+X001651Y011568D03*
+X002651Y011568D03*
+X003651Y011568D03*
+X004651Y011568D03*
+X005651Y011568D03*
+X006651Y011568D03*
+X007651Y011568D03*
+X008651Y011568D03*
+X009651Y011568D03*
+X010651Y011568D03*
+X011651Y011568D03*
+X012651Y011568D03*
+X013651Y011568D03*
+X014651Y011568D03*
+X015651Y011568D03*
+X016651Y011568D03*
+X016651Y010568D03*
+X015651Y010568D03*
+X015651Y009568D03*
+X016651Y009568D03*
+X016651Y008568D03*
+X015651Y008568D03*
+X015651Y007568D03*
+X016651Y007568D03*
+X016651Y006568D03*
+X015651Y006568D03*
+X015651Y005568D03*
+X016651Y005568D03*
+X016651Y004568D03*
+X015651Y004568D03*
+X015651Y003568D03*
+X016651Y003568D03*
+X016651Y002568D03*
+X015651Y002568D03*
+X015651Y001568D03*
+X016651Y001568D03*
+X016651Y012568D03*
+X015651Y012568D03*
+X014651Y012568D03*
+X013651Y012568D03*
+X012651Y012568D03*
+X011651Y012568D03*
+X010651Y012568D03*
+X009651Y012568D03*
+X008651Y012568D03*
+X007651Y012568D03*
+X006651Y012568D03*
+X005651Y012568D03*
+X004651Y012568D03*
+X003651Y012568D03*
+X002651Y012568D03*
+X001651Y012568D03*
+X000651Y012568D03*
+D11*
+X006801Y009718D03*
+X008101Y010318D03*
+X005301Y007568D03*
+X005301Y005568D03*
+X006151Y003518D03*
+X009351Y004218D03*
+X008601Y006718D03*
+X013151Y003518D03*
+X001501Y003668D03*
+D12*
+X000301Y001218D02*
+X000301Y011254D01*
+X000456Y011098D01*
+X000846Y011098D01*
+X001121Y011374D01*
+X001121Y011763D01*
+X000846Y012038D01*
+X000456Y012038D01*
+X000301Y011883D01*
+X000301Y012254D01*
+X000456Y012098D01*
+X000601Y012098D01*
+X000601Y012518D01*
+X000701Y012518D01*
+X000701Y012098D01*
+X000846Y012098D01*
+X001121Y012374D01*
+X001121Y012518D01*
+X000701Y012518D01*
+X000701Y012618D01*
+X001121Y012618D01*
+X001121Y012763D01*
+X000966Y012918D01*
+X001337Y012918D01*
+X001181Y012763D01*
+X001181Y012618D01*
+X001601Y012618D01*
+X001601Y012518D01*
+X001701Y012518D01*
+X001701Y012098D01*
+X001846Y012098D01*
+X002121Y012374D01*
+X002121Y012518D01*
+X001701Y012518D01*
+X001701Y012618D01*
+X002121Y012618D01*
+X002121Y012763D01*
+X001966Y012918D01*
+X002337Y012918D01*
+X002181Y012763D01*
+X002181Y012618D01*
+X002601Y012618D01*
+X002601Y012518D01*
+X002701Y012518D01*
+X002701Y012098D01*
+X002846Y012098D01*
+X003121Y012374D01*
+X003121Y012518D01*
+X002701Y012518D01*
+X002701Y012618D01*
+X003121Y012618D01*
+X003121Y012763D01*
+X002966Y012918D01*
+X003337Y012918D01*
+X003181Y012763D01*
+X003181Y012618D01*
+X003601Y012618D01*
+X003601Y012518D01*
+X003701Y012518D01*
+X003701Y012098D01*
+X003846Y012098D01*
+X004121Y012374D01*
+X004121Y012518D01*
+X003701Y012518D01*
+X003701Y012618D01*
+X004121Y012618D01*
+X004121Y012763D01*
+X003966Y012918D01*
+X004337Y012918D01*
+X004181Y012763D01*
+X004181Y012618D01*
+X004601Y012618D01*
+X004601Y012518D01*
+X004701Y012518D01*
+X004701Y012098D01*
+X004846Y012098D01*
+X005121Y012374D01*
+X005121Y012518D01*
+X004701Y012518D01*
+X004701Y012618D01*
+X005121Y012618D01*
+X005121Y012763D01*
+X004966Y012918D01*
+X005337Y012918D01*
+X005181Y012763D01*
+X005181Y012618D01*
+X005601Y012618D01*
+X005601Y012518D01*
+X005701Y012518D01*
+X005701Y012098D01*
+X005846Y012098D01*
+X006121Y012374D01*
+X006121Y012518D01*
+X005701Y012518D01*
+X005701Y012618D01*
+X006121Y012618D01*
+X006121Y012763D01*
+X005966Y012918D01*
+X006337Y012918D01*
+X006181Y012763D01*
+X006181Y012618D01*
+X006601Y012618D01*
+X006601Y012518D01*
+X006701Y012518D01*
+X006701Y012098D01*
+X006846Y012098D01*
+X007121Y012374D01*
+X007121Y012518D01*
+X006701Y012518D01*
+X006701Y012618D01*
+X007121Y012618D01*
+X007121Y012763D01*
+X006966Y012918D01*
+X007337Y012918D01*
+X007181Y012763D01*
+X007181Y012618D01*
+X007601Y012618D01*
+X007601Y012518D01*
+X007701Y012518D01*
+X007701Y012098D01*
+X007846Y012098D01*
+X008121Y012374D01*
+X008121Y012518D01*
+X007701Y012518D01*
+X007701Y012618D01*
+X008121Y012618D01*
+X008121Y012763D01*
+X007966Y012918D01*
+X008337Y012918D01*
+X008181Y012763D01*
+X008181Y012618D01*
+X008601Y012618D01*
+X008601Y012518D01*
+X008701Y012518D01*
+X008701Y012098D01*
+X008846Y012098D01*
+X009121Y012374D01*
+X009121Y012518D01*
+X008701Y012518D01*
+X008701Y012618D01*
+X009121Y012618D01*
+X009121Y012763D01*
+X008966Y012918D01*
+X009337Y012918D01*
+X009181Y012763D01*
+X009181Y012618D01*
+X009601Y012618D01*
+X009601Y012518D01*
+X009701Y012518D01*
+X009701Y012098D01*
+X009846Y012098D01*
+X010121Y012374D01*
+X010121Y012518D01*
+X009701Y012518D01*
+X009701Y012618D01*
+X010121Y012618D01*
+X010121Y012763D01*
+X009966Y012918D01*
+X010337Y012918D01*
+X010181Y012763D01*
+X010181Y012618D01*
+X010601Y012618D01*
+X010601Y012518D01*
+X010701Y012518D01*
+X010701Y012098D01*
+X010846Y012098D01*
+X011121Y012374D01*
+X011121Y012518D01*
+X010701Y012518D01*
+X010701Y012618D01*
+X011121Y012618D01*
+X011121Y012763D01*
+X010966Y012918D01*
+X011337Y012918D01*
+X011181Y012763D01*
+X011181Y012618D01*
+X011601Y012618D01*
+X011601Y012518D01*
+X011701Y012518D01*
+X011701Y012098D01*
+X011846Y012098D01*
+X012121Y012374D01*
+X012121Y012518D01*
+X011701Y012518D01*
+X011701Y012618D01*
+X012121Y012618D01*
+X012121Y012763D01*
+X011966Y012918D01*
+X012337Y012918D01*
+X012181Y012763D01*
+X012181Y012618D01*
+X012601Y012618D01*
+X012601Y012518D01*
+X012701Y012518D01*
+X012701Y012098D01*
+X012846Y012098D01*
+X013121Y012374D01*
+X013121Y012518D01*
+X012701Y012518D01*
+X012701Y012618D01*
+X013121Y012618D01*
+X013121Y012763D01*
+X012966Y012918D01*
+X013337Y012918D01*
+X013181Y012763D01*
+X013181Y012618D01*
+X013601Y012618D01*
+X013601Y012518D01*
+X013701Y012518D01*
+X013701Y012098D01*
+X013846Y012098D01*
+X014121Y012374D01*
+X014121Y012518D01*
+X013701Y012518D01*
+X013701Y012618D01*
+X014121Y012618D01*
+X014121Y012763D01*
+X013966Y012918D01*
+X014337Y012918D01*
+X014181Y012763D01*
+X014181Y012618D01*
+X014601Y012618D01*
+X014601Y012518D01*
+X014701Y012518D01*
+X014701Y012098D01*
+X014846Y012098D01*
+X015121Y012374D01*
+X015121Y012518D01*
+X014701Y012518D01*
+X014701Y012618D01*
+X015121Y012618D01*
+X015121Y012763D01*
+X014966Y012918D01*
+X015337Y012918D01*
+X015181Y012763D01*
+X015181Y012618D01*
+X015601Y012618D01*
+X015601Y012518D01*
+X015701Y012518D01*
+X015701Y012098D01*
+X015846Y012098D01*
+X016121Y012374D01*
+X016121Y012518D01*
+X015701Y012518D01*
+X015701Y012618D01*
+X016121Y012618D01*
+X016121Y012763D01*
+X015966Y012918D01*
+X016337Y012918D01*
+X016181Y012763D01*
+X016181Y012618D01*
+X016601Y012618D01*
+X016601Y012518D01*
+X016701Y012518D01*
+X016701Y012098D01*
+X016846Y012098D01*
+X017001Y012254D01*
+X017001Y011883D01*
+X016846Y012038D01*
+X016701Y012038D01*
+X016701Y011619D01*
+X016601Y011619D01*
+X016601Y012038D01*
+X016456Y012038D01*
+X016181Y011763D01*
+X016181Y011618D01*
+X016601Y011618D01*
+X016601Y011518D01*
+X016701Y011518D01*
+X016701Y011098D01*
+X016846Y011098D01*
+X017001Y011254D01*
+X017001Y010883D01*
+X016846Y011038D01*
+X016701Y011038D01*
+X016701Y010619D01*
+X016601Y010619D01*
+X016601Y011038D01*
+X016456Y011038D01*
+X016181Y010763D01*
+X016181Y010618D01*
+X016601Y010618D01*
+X016601Y010518D01*
+X016701Y010518D01*
+X016701Y010098D01*
+X016846Y010098D01*
+X017001Y010254D01*
+X017001Y009883D01*
+X016846Y010038D01*
+X016701Y010038D01*
+X016701Y009619D01*
+X016601Y009619D01*
+X016601Y010038D01*
+X016456Y010038D01*
+X016181Y009763D01*
+X016181Y009618D01*
+X016601Y009618D01*
+X016601Y009518D01*
+X016701Y009518D01*
+X016701Y009098D01*
+X016846Y009098D01*
+X017001Y009254D01*
+X017001Y008883D01*
+X016846Y009038D01*
+X016701Y009038D01*
+X016701Y008619D01*
+X016601Y008619D01*
+X016601Y009038D01*
+X016456Y009038D01*
+X016181Y008763D01*
+X016181Y008618D01*
+X016601Y008618D01*
+X016601Y008518D01*
+X016701Y008518D01*
+X016701Y008098D01*
+X016846Y008098D01*
+X017001Y008254D01*
+X017001Y007883D01*
+X016846Y008038D01*
+X016701Y008038D01*
+X016701Y007619D01*
+X016601Y007619D01*
+X016601Y008038D01*
+X016456Y008038D01*
+X016181Y007763D01*
+X016181Y007618D01*
+X016601Y007618D01*
+X016601Y007518D01*
+X016701Y007518D01*
+X016701Y007098D01*
+X016846Y007098D01*
+X017001Y007254D01*
+X017001Y006883D01*
+X016846Y007038D01*
+X016701Y007038D01*
+X016701Y006619D01*
+X016601Y006619D01*
+X016601Y007038D01*
+X016456Y007038D01*
+X016181Y006763D01*
+X016181Y006618D01*
+X016601Y006618D01*
+X016601Y006518D01*
+X016701Y006518D01*
+X016701Y006098D01*
+X016846Y006098D01*
+X017001Y006254D01*
+X017001Y005883D01*
+X016846Y006038D01*
+X016701Y006038D01*
+X016701Y005619D01*
+X016601Y005619D01*
+X016601Y006038D01*
+X016456Y006038D01*
+X016181Y005763D01*
+X016181Y005618D01*
+X016601Y005618D01*
+X016601Y005518D01*
+X016701Y005518D01*
+X016701Y005098D01*
+X016846Y005098D01*
+X017001Y005254D01*
+X017001Y004883D01*
+X016846Y005038D01*
+X016701Y005038D01*
+X016701Y004619D01*
+X016601Y004619D01*
+X016601Y005038D01*
+X016456Y005038D01*
+X016181Y004763D01*
+X016181Y004618D01*
+X016601Y004618D01*
+X016601Y004518D01*
+X016701Y004518D01*
+X016701Y004098D01*
+X016846Y004098D01*
+X017001Y004254D01*
+X017001Y003883D01*
+X016846Y004038D01*
+X016701Y004038D01*
+X016701Y003619D01*
+X016601Y003619D01*
+X016601Y004038D01*
+X016456Y004038D01*
+X016181Y003763D01*
+X016181Y003618D01*
+X016601Y003618D01*
+X016601Y003518D01*
+X016701Y003518D01*
+X016701Y003098D01*
+X016846Y003098D01*
+X017001Y003254D01*
+X017001Y002883D01*
+X016846Y003038D01*
+X016701Y003038D01*
+X016701Y002619D01*
+X016601Y002619D01*
+X016601Y003038D01*
+X016456Y003038D01*
+X016181Y002763D01*
+X016181Y002618D01*
+X016601Y002618D01*
+X016601Y002518D01*
+X016701Y002518D01*
+X016701Y002098D01*
+X016846Y002098D01*
+X017001Y002254D01*
+X017001Y001883D01*
+X016846Y002038D01*
+X016701Y002038D01*
+X016701Y001619D01*
+X016601Y001619D01*
+X016601Y002038D01*
+X016456Y002038D01*
+X016181Y001763D01*
+X016181Y001618D01*
+X016601Y001618D01*
+X016601Y001518D01*
+X016181Y001518D01*
+X016181Y001374D01*
+X016337Y001218D01*
+X015966Y001218D01*
+X016121Y001374D01*
+X016121Y001518D01*
+X015701Y001518D01*
+X015701Y001618D01*
+X016121Y001618D01*
+X016121Y001763D01*
+X015846Y002038D01*
+X015701Y002038D01*
+X015701Y001619D01*
+X015601Y001619D01*
+X015601Y002038D01*
+X015456Y002038D01*
+X015181Y001763D01*
+X015181Y001618D01*
+X015601Y001618D01*
+X015601Y001518D01*
+X015181Y001518D01*
+X015181Y001374D01*
+X015337Y001218D01*
+X000301Y001218D01*
+X000301Y001265D02*
+X015289Y001265D01*
+X015191Y001364D02*
+X000301Y001364D01*
+X000301Y001463D02*
+X015181Y001463D01*
+X015181Y001660D02*
+X000301Y001660D01*
+X000301Y001758D02*
+X015181Y001758D01*
+X015275Y001857D02*
+X000301Y001857D01*
+X000301Y001955D02*
+X001981Y001955D01*
+X002068Y001868D02*
+X001868Y002068D01*
+X001868Y002068D01*
+X001751Y002185D01*
+X001751Y002973D01*
+X001654Y003070D01*
+X001601Y003199D01*
+X001601Y003338D01*
+X001654Y003467D01*
+X001753Y003565D01*
+X001882Y003618D01*
+X002021Y003618D01*
+X002149Y003565D01*
+X002248Y003467D01*
+X002301Y003338D01*
+X002301Y003199D01*
+X002248Y003070D01*
+X002151Y002973D01*
+X002151Y002351D01*
+X002234Y002268D01*
+X002768Y002268D01*
+X002851Y002351D01*
+X002851Y003473D01*
+X002754Y003570D01*
+X002701Y003699D01*
+X002701Y003838D01*
+X002754Y003967D01*
+X002853Y004065D01*
+X002982Y004118D01*
+X003121Y004118D01*
+X003249Y004065D01*
+X003348Y003967D01*
+X003401Y003838D01*
+X003401Y003699D01*
+X003348Y003570D01*
+X003251Y003473D01*
+X003251Y002351D01*
+X003251Y002185D01*
+X002934Y001868D01*
+X002768Y001868D01*
+X002234Y001868D01*
+X002068Y001868D01*
+X002151Y002068D02*
+X001951Y002268D01*
+X001951Y003268D01*
+X001641Y003433D02*
+X000301Y003433D01*
+X000301Y003335D02*
+X001601Y003335D01*
+X001601Y003236D02*
+X000301Y003236D01*
+X000301Y003138D02*
+X001626Y003138D01*
+X001685Y003039D02*
+X000301Y003039D01*
+X000301Y002941D02*
+X001751Y002941D01*
+X001751Y002842D02*
+X000301Y002842D01*
+X000301Y002744D02*
+X001751Y002744D01*
+X001751Y002645D02*
+X000301Y002645D01*
+X000301Y002546D02*
+X001751Y002546D01*
+X001751Y002448D02*
+X000301Y002448D01*
+X000301Y002349D02*
+X001751Y002349D01*
+X001751Y002251D02*
+X000301Y002251D01*
+X000301Y002152D02*
+X001784Y002152D01*
+X001883Y002054D02*
+X000301Y002054D01*
+X000301Y001561D02*
+X015601Y001561D01*
+X015601Y001660D02*
+X015701Y001660D01*
+X015701Y001758D02*
+X015601Y001758D01*
+X015601Y001857D02*
+X015701Y001857D01*
+X015701Y001955D02*
+X015601Y001955D01*
+X015456Y002098D02*
+X015846Y002098D01*
+X016121Y002374D01*
+X016121Y002763D01*
+X015846Y003038D01*
+X015456Y003038D01*
+X015181Y002763D01*
+X015181Y002374D01*
+X015456Y002098D01*
+X015403Y002152D02*
+X003218Y002152D01*
+X003251Y002251D02*
+X015304Y002251D01*
+X015205Y002349D02*
+X003251Y002349D01*
+X003251Y002448D02*
+X015181Y002448D01*
+X015181Y002546D02*
+X003251Y002546D01*
+X003251Y002645D02*
+X015181Y002645D01*
+X015181Y002744D02*
+X003251Y002744D01*
+X003251Y002842D02*
+X015260Y002842D01*
+X015359Y002941D02*
+X003251Y002941D01*
+X003251Y003039D02*
+X017001Y003039D01*
+X017001Y002941D02*
+X016943Y002941D01*
+X016701Y002941D02*
+X016601Y002941D01*
+X016601Y002842D02*
+X016701Y002842D01*
+X016701Y002744D02*
+X016601Y002744D01*
+X016601Y002645D02*
+X016701Y002645D01*
+X016601Y002546D02*
+X016121Y002546D01*
+X016181Y002518D02*
+X016181Y002374D01*
+X016456Y002098D01*
+X016601Y002098D01*
+X016601Y002518D01*
+X016181Y002518D01*
+X016181Y002448D02*
+X016121Y002448D01*
+X016097Y002349D02*
+X016205Y002349D01*
+X016304Y002251D02*
+X015998Y002251D01*
+X015900Y002152D02*
+X016403Y002152D01*
+X016601Y002152D02*
+X016701Y002152D01*
+X016701Y002251D02*
+X016601Y002251D01*
+X016601Y002349D02*
+X016701Y002349D01*
+X016701Y002448D02*
+X016601Y002448D01*
+X016900Y002152D02*
+X017001Y002152D01*
+X017001Y002054D02*
+X003119Y002054D01*
+X003021Y001955D02*
+X015373Y001955D01*
+X015701Y001561D02*
+X016601Y001561D01*
+X016601Y001660D02*
+X016701Y001660D01*
+X016701Y001758D02*
+X016601Y001758D01*
+X016601Y001857D02*
+X016701Y001857D01*
+X016701Y001955D02*
+X016601Y001955D01*
+X016373Y001955D02*
+X015929Y001955D01*
+X016027Y001857D02*
+X016275Y001857D01*
+X016181Y001758D02*
+X016121Y001758D01*
+X016121Y001660D02*
+X016181Y001660D01*
+X016181Y001463D02*
+X016121Y001463D01*
+X016111Y001364D02*
+X016191Y001364D01*
+X016289Y001265D02*
+X016013Y001265D01*
+X016929Y001955D02*
+X017001Y001955D01*
+X016998Y002251D02*
+X017001Y002251D01*
+X016181Y002645D02*
+X016121Y002645D01*
+X016121Y002744D02*
+X016181Y002744D01*
+X016260Y002842D02*
+X016042Y002842D01*
+X015943Y002941D02*
+X016359Y002941D01*
+X016456Y003098D02*
+X016601Y003098D01*
+X016601Y003518D01*
+X016181Y003518D01*
+X016181Y003374D01*
+X016456Y003098D01*
+X016417Y003138D02*
+X015885Y003138D01*
+X015846Y003098D02*
+X016121Y003374D01*
+X016121Y003763D01*
+X015846Y004038D01*
+X015456Y004038D01*
+X015181Y003763D01*
+X015181Y003374D01*
+X015456Y003098D01*
+X015846Y003098D01*
+X015984Y003236D02*
+X016319Y003236D01*
+X016220Y003335D02*
+X016082Y003335D01*
+X016121Y003433D02*
+X016181Y003433D01*
+X016121Y003532D02*
+X016601Y003532D01*
+X016601Y003630D02*
+X016701Y003630D01*
+X016701Y003729D02*
+X016601Y003729D01*
+X016601Y003828D02*
+X016701Y003828D01*
+X016701Y003926D02*
+X016601Y003926D01*
+X016601Y004025D02*
+X016701Y004025D01*
+X016701Y004123D02*
+X016601Y004123D01*
+X016601Y004098D02*
+X016601Y004518D01*
+X016181Y004518D01*
+X016181Y004374D01*
+X016456Y004098D01*
+X016601Y004098D01*
+X016601Y004222D02*
+X016701Y004222D01*
+X016701Y004320D02*
+X016601Y004320D01*
+X016601Y004419D02*
+X016701Y004419D01*
+X016701Y004517D02*
+X016601Y004517D01*
+X016601Y004616D02*
+X016121Y004616D01*
+X016121Y004714D02*
+X016181Y004714D01*
+X016121Y004763D02*
+X015846Y005038D01*
+X015456Y005038D01*
+X015181Y004763D01*
+X015181Y004374D01*
+X015456Y004098D01*
+X015846Y004098D01*
+X016121Y004374D01*
+X016121Y004763D01*
+X016071Y004813D02*
+X016231Y004813D01*
+X016330Y004912D02*
+X015973Y004912D01*
+X015874Y005010D02*
+X016428Y005010D01*
+X016456Y005098D02*
+X016601Y005098D01*
+X016601Y005518D01*
+X016181Y005518D01*
+X016181Y005374D01*
+X016456Y005098D01*
+X016446Y005109D02*
+X015856Y005109D01*
+X015846Y005098D02*
+X016121Y005374D01*
+X016121Y005763D01*
+X015846Y006038D01*
+X015456Y006038D01*
+X015181Y005763D01*
+X015181Y005374D01*
+X015456Y005098D01*
+X015846Y005098D01*
+X015955Y005207D02*
+X016348Y005207D01*
+X016249Y005306D02*
+X016053Y005306D01*
+X016121Y005404D02*
+X016181Y005404D01*
+X016181Y005503D02*
+X016121Y005503D01*
+X016121Y005601D02*
+X016601Y005601D01*
+X016601Y005503D02*
+X016701Y005503D01*
+X016701Y005404D02*
+X016601Y005404D01*
+X016601Y005306D02*
+X016701Y005306D01*
+X016701Y005207D02*
+X016601Y005207D01*
+X016601Y005109D02*
+X016701Y005109D01*
+X016701Y005010D02*
+X016601Y005010D01*
+X016601Y004912D02*
+X016701Y004912D01*
+X016701Y004813D02*
+X016601Y004813D01*
+X016601Y004714D02*
+X016701Y004714D01*
+X016973Y004912D02*
+X017001Y004912D01*
+X017001Y005010D02*
+X016874Y005010D01*
+X016856Y005109D02*
+X017001Y005109D01*
+X017001Y005207D02*
+X016955Y005207D01*
+X016701Y005700D02*
+X016601Y005700D01*
+X016601Y005798D02*
+X016701Y005798D01*
+X016701Y005897D02*
+X016601Y005897D01*
+X016601Y005996D02*
+X016701Y005996D01*
+X016601Y006098D02*
+X016601Y006518D01*
+X016181Y006518D01*
+X016181Y006374D01*
+X016456Y006098D01*
+X016601Y006098D01*
+X016601Y006193D02*
+X016701Y006193D01*
+X016701Y006291D02*
+X016601Y006291D01*
+X016601Y006390D02*
+X016701Y006390D01*
+X016701Y006488D02*
+X016601Y006488D01*
+X016601Y006587D02*
+X016121Y006587D01*
+X016121Y006685D02*
+X016181Y006685D01*
+X016121Y006763D02*
+X015846Y007038D01*
+X015456Y007038D01*
+X015181Y006763D01*
+X015181Y006374D01*
+X015456Y006098D01*
+X015846Y006098D01*
+X016121Y006374D01*
+X016121Y006763D01*
+X016100Y006784D02*
+X016202Y006784D01*
+X016301Y006882D02*
+X016002Y006882D01*
+X015903Y006981D02*
+X016399Y006981D01*
+X016456Y007098D02*
+X016601Y007098D01*
+X016601Y007518D01*
+X016181Y007518D01*
+X016181Y007374D01*
+X016456Y007098D01*
+X016377Y007178D02*
+X015926Y007178D01*
+X015846Y007098D02*
+X016121Y007374D01*
+X016121Y007763D01*
+X015846Y008038D01*
+X015456Y008038D01*
+X015181Y007763D01*
+X015181Y007374D01*
+X015456Y007098D01*
+X015846Y007098D01*
+X016024Y007277D02*
+X016278Y007277D01*
+X016181Y007375D02*
+X016121Y007375D01*
+X016121Y007474D02*
+X016181Y007474D01*
+X016121Y007572D02*
+X016601Y007572D01*
+X016601Y007474D02*
+X016701Y007474D01*
+X016701Y007375D02*
+X016601Y007375D01*
+X016601Y007277D02*
+X016701Y007277D01*
+X016701Y007178D02*
+X016601Y007178D01*
+X016601Y006981D02*
+X016701Y006981D01*
+X016701Y006882D02*
+X016601Y006882D01*
+X016601Y006784D02*
+X016701Y006784D01*
+X016701Y006685D02*
+X016601Y006685D01*
+X016903Y006981D02*
+X017001Y006981D01*
+X017001Y007079D02*
+X000301Y007079D01*
+X000301Y006981D02*
+X015399Y006981D01*
+X015301Y006882D02*
+X000301Y006882D01*
+X000301Y006784D02*
+X015202Y006784D01*
+X015181Y006685D02*
+X000301Y006685D01*
+X000301Y006587D02*
+X015181Y006587D01*
+X015181Y006488D02*
+X000301Y006488D01*
+X000301Y006390D02*
+X015181Y006390D01*
+X015264Y006291D02*
+X000301Y006291D01*
+X000301Y006193D02*
+X015362Y006193D01*
+X015414Y005996D02*
+X000301Y005996D01*
+X000301Y006094D02*
+X017001Y006094D01*
+X017001Y005996D02*
+X016889Y005996D01*
+X016987Y005897D02*
+X017001Y005897D01*
+X017001Y006193D02*
+X016940Y006193D01*
+X016414Y005996D02*
+X015889Y005996D01*
+X015987Y005897D02*
+X016315Y005897D01*
+X016217Y005798D02*
+X016086Y005798D01*
+X016121Y005700D02*
+X016181Y005700D01*
+X016362Y006193D02*
+X015940Y006193D01*
+X016039Y006291D02*
+X016264Y006291D01*
+X016181Y006390D02*
+X016121Y006390D01*
+X016121Y006488D02*
+X016181Y006488D01*
+X016925Y007178D02*
+X017001Y007178D01*
+X016701Y007671D02*
+X016601Y007671D01*
+X016601Y007769D02*
+X016701Y007769D01*
+X016701Y007868D02*
+X016601Y007868D01*
+X016601Y007966D02*
+X016701Y007966D01*
+X016601Y008098D02*
+X016601Y008518D01*
+X016181Y008518D01*
+X016181Y008374D01*
+X016456Y008098D01*
+X016601Y008098D01*
+X016601Y008163D02*
+X016701Y008163D01*
+X016701Y008262D02*
+X016601Y008262D01*
+X016601Y008361D02*
+X016701Y008361D01*
+X016701Y008459D02*
+X016601Y008459D01*
+X016601Y008558D02*
+X016121Y008558D01*
+X016121Y008656D02*
+X016181Y008656D01*
+X016181Y008755D02*
+X016121Y008755D01*
+X016121Y008763D02*
+X015846Y009038D01*
+X015456Y009038D01*
+X015181Y008763D01*
+X015181Y008374D01*
+X015456Y008098D01*
+X015846Y008098D01*
+X016121Y008374D01*
+X016121Y008763D01*
+X016031Y008853D02*
+X016271Y008853D01*
+X016370Y008952D02*
+X015932Y008952D01*
+X015846Y009098D02*
+X016121Y009374D01*
+X016121Y009763D01*
+X015846Y010038D01*
+X015456Y010038D01*
+X015181Y009763D01*
+X015181Y009374D01*
+X015456Y009098D01*
+X015846Y009098D01*
+X015896Y009149D02*
+X016406Y009149D01*
+X016456Y009098D02*
+X016181Y009374D01*
+X016181Y009518D01*
+X016601Y009518D01*
+X016601Y009098D01*
+X016456Y009098D01*
+X016601Y009149D02*
+X016701Y009149D01*
+X016701Y009247D02*
+X016601Y009247D01*
+X016601Y009346D02*
+X016701Y009346D01*
+X016701Y009445D02*
+X016601Y009445D01*
+X016601Y009543D02*
+X016121Y009543D01*
+X016121Y009445D02*
+X016181Y009445D01*
+X016209Y009346D02*
+X016093Y009346D01*
+X015995Y009247D02*
+X016307Y009247D01*
+X016601Y008952D02*
+X016701Y008952D01*
+X016701Y008853D02*
+X016601Y008853D01*
+X016601Y008755D02*
+X016701Y008755D01*
+X016701Y008656D02*
+X016601Y008656D01*
+X016932Y008952D02*
+X017001Y008952D01*
+X017001Y009050D02*
+X000301Y009050D01*
+X000301Y008952D02*
+X015370Y008952D01*
+X015271Y008853D02*
+X000301Y008853D01*
+X000301Y008755D02*
+X015181Y008755D01*
+X015181Y008656D02*
+X000301Y008656D01*
+X000301Y008558D02*
+X015181Y008558D01*
+X015181Y008459D02*
+X000301Y008459D01*
+X000301Y008361D02*
+X015194Y008361D01*
+X015293Y008262D02*
+X000301Y008262D01*
+X000301Y008163D02*
+X015391Y008163D01*
+X015385Y007966D02*
+X000301Y007966D01*
+X000301Y007868D02*
+X015286Y007868D01*
+X015187Y007769D02*
+X000301Y007769D01*
+X000301Y007671D02*
+X015181Y007671D01*
+X015181Y007572D02*
+X000301Y007572D01*
+X000301Y007474D02*
+X015181Y007474D01*
+X015181Y007375D02*
+X000301Y007375D01*
+X000301Y007277D02*
+X015278Y007277D01*
+X015377Y007178D02*
+X000301Y007178D01*
+X000301Y008065D02*
+X017001Y008065D01*
+X017001Y008163D02*
+X016911Y008163D01*
+X016918Y007966D02*
+X017001Y007966D01*
+X016385Y007966D02*
+X015918Y007966D01*
+X016016Y007868D02*
+X016286Y007868D01*
+X016187Y007769D02*
+X016115Y007769D01*
+X016121Y007671D02*
+X016181Y007671D01*
+X016391Y008163D02*
+X015911Y008163D01*
+X016009Y008262D02*
+X016293Y008262D01*
+X016194Y008361D02*
+X016108Y008361D01*
+X016121Y008459D02*
+X016181Y008459D01*
+X016896Y009149D02*
+X017001Y009149D01*
+X016995Y009247D02*
+X017001Y009247D01*
+X016701Y009642D02*
+X016601Y009642D01*
+X016601Y009740D02*
+X016701Y009740D01*
+X016701Y009839D02*
+X016601Y009839D01*
+X016601Y009937D02*
+X016701Y009937D01*
+X016701Y010036D02*
+X016601Y010036D01*
+X016601Y010098D02*
+X016601Y010518D01*
+X016181Y010518D01*
+X016181Y010374D01*
+X016456Y010098D01*
+X016601Y010098D01*
+X016601Y010134D02*
+X016701Y010134D01*
+X016701Y010233D02*
+X016601Y010233D01*
+X016601Y010331D02*
+X016701Y010331D01*
+X016701Y010430D02*
+X016601Y010430D01*
+X016601Y010529D02*
+X016121Y010529D01*
+X016121Y010627D02*
+X016181Y010627D01*
+X016181Y010726D02*
+X016121Y010726D01*
+X016121Y010763D02*
+X015846Y011038D01*
+X015456Y011038D01*
+X015181Y010763D01*
+X015181Y010374D01*
+X015456Y010098D01*
+X015846Y010098D01*
+X016121Y010374D01*
+X016121Y010763D01*
+X016060Y010824D02*
+X016242Y010824D01*
+X016341Y010923D02*
+X015961Y010923D01*
+X015863Y011021D02*
+X016439Y011021D01*
+X016456Y011098D02*
+X016601Y011098D01*
+X016601Y011518D01*
+X016181Y011518D01*
+X016181Y011374D01*
+X016456Y011098D01*
+X016435Y011120D02*
+X015867Y011120D01*
+X015846Y011098D02*
+X016121Y011374D01*
+X016121Y011763D01*
+X015846Y012038D01*
+X015456Y012038D01*
+X015181Y011763D01*
+X015181Y011374D01*
+X015456Y011098D01*
+X015846Y011098D01*
+X015966Y011218D02*
+X016337Y011218D01*
+X016238Y011317D02*
+X016064Y011317D01*
+X016121Y011415D02*
+X016181Y011415D01*
+X016181Y011514D02*
+X016121Y011514D01*
+X016121Y011612D02*
+X016601Y011612D01*
+X016601Y011514D02*
+X016701Y011514D01*
+X016701Y011415D02*
+X016601Y011415D01*
+X016601Y011317D02*
+X016701Y011317D01*
+X016701Y011218D02*
+X016601Y011218D01*
+X016601Y011120D02*
+X016701Y011120D01*
+X016701Y011021D02*
+X016601Y011021D01*
+X016601Y010923D02*
+X016701Y010923D01*
+X016701Y010824D02*
+X016601Y010824D01*
+X016601Y010726D02*
+X016701Y010726D01*
+X016701Y010627D02*
+X016601Y010627D01*
+X016181Y010430D02*
+X016121Y010430D01*
+X016079Y010331D02*
+X016223Y010331D01*
+X016322Y010233D02*
+X015980Y010233D01*
+X015882Y010134D02*
+X016421Y010134D01*
+X016454Y010036D02*
+X015848Y010036D01*
+X015947Y009937D02*
+X016355Y009937D01*
+X016257Y009839D02*
+X016045Y009839D01*
+X016121Y009740D02*
+X016181Y009740D01*
+X016181Y009642D02*
+X016121Y009642D01*
+X015454Y010036D02*
+X008339Y010036D01*
+X008310Y010006D02*
+X008174Y009950D01*
+X008028Y009950D01*
+X007893Y010006D01*
+X007789Y010110D01*
+X007786Y010118D01*
+X007484Y010118D01*
+X007166Y009800D01*
+X007169Y009792D01*
+X007169Y009645D01*
+X007113Y009510D01*
+X007010Y009406D01*
+X006874Y009350D01*
+X006728Y009350D01*
+X006593Y009406D01*
+X006489Y009510D01*
+X006433Y009645D01*
+X006433Y009792D01*
+X006489Y009927D01*
+X006593Y010030D01*
+X006728Y010086D01*
+X006874Y010086D01*
+X006883Y010083D01*
+X007318Y010518D01*
+X007484Y010518D01*
+X007786Y010518D01*
+X007789Y010527D01*
+X007893Y010630D01*
+X008028Y010686D01*
+X008174Y010686D01*
+X008310Y010630D01*
+X008413Y010527D01*
+X008469Y010392D01*
+X008469Y010245D01*
+X008413Y010110D01*
+X008310Y010006D01*
+X008423Y010134D02*
+X015421Y010134D01*
+X015322Y010233D02*
+X008464Y010233D01*
+X008469Y010331D02*
+X015223Y010331D01*
+X015181Y010430D02*
+X008453Y010430D01*
+X008412Y010529D02*
+X015181Y010529D01*
+X015181Y010627D02*
+X008313Y010627D01*
+X008101Y010318D02*
+X007401Y010318D01*
+X006801Y009718D01*
+X006554Y009445D02*
+X000301Y009445D01*
+X000301Y009543D02*
+X006475Y009543D01*
+X006434Y009642D02*
+X000301Y009642D01*
+X000301Y009740D02*
+X006433Y009740D01*
+X006453Y009839D02*
+X000301Y009839D01*
+X000301Y009937D02*
+X006499Y009937D01*
+X006606Y010036D02*
+X000301Y010036D01*
+X000301Y010134D02*
+X006934Y010134D01*
+X007033Y010233D02*
+X000301Y010233D01*
+X000301Y010331D02*
+X007131Y010331D01*
+X007230Y010430D02*
+X000301Y010430D01*
+X000301Y010529D02*
+X007791Y010529D01*
+X007889Y010627D02*
+X000301Y010627D01*
+X000301Y010726D02*
+X015181Y010726D01*
+X015242Y010824D02*
+X000301Y010824D01*
+X000301Y010923D02*
+X015341Y010923D01*
+X015439Y011021D02*
+X000301Y011021D01*
+X000301Y011120D02*
+X000435Y011120D01*
+X000337Y011218D02*
+X000301Y011218D01*
+X000867Y011120D02*
+X001435Y011120D01*
+X001456Y011098D02*
+X001846Y011098D01*
+X002121Y011374D01*
+X002121Y011763D01*
+X001846Y012038D01*
+X001456Y012038D01*
+X001181Y011763D01*
+X001181Y011374D01*
+X001456Y011098D01*
+X001337Y011218D02*
+X000966Y011218D01*
+X001064Y011317D02*
+X001238Y011317D01*
+X001181Y011415D02*
+X001121Y011415D01*
+X001121Y011514D02*
+X001181Y011514D01*
+X001181Y011612D02*
+X001121Y011612D01*
+X001121Y011711D02*
+X001181Y011711D01*
+X001228Y011810D02*
+X001075Y011810D01*
+X000976Y011908D02*
+X001326Y011908D01*
+X001425Y012007D02*
+X000877Y012007D01*
+X000853Y012105D02*
+X001450Y012105D01*
+X001456Y012098D02*
+X001181Y012374D01*
+X001181Y012518D01*
+X001601Y012518D01*
+X001601Y012098D01*
+X001456Y012098D01*
+X001601Y012105D02*
+X001701Y012105D01*
+X001701Y012204D02*
+X001601Y012204D01*
+X001601Y012302D02*
+X001701Y012302D01*
+X001701Y012401D02*
+X001601Y012401D01*
+X001601Y012499D02*
+X001701Y012499D01*
+X001701Y012598D02*
+X002601Y012598D01*
+X002601Y012518D02*
+X002181Y012518D01*
+X002181Y012374D01*
+X002456Y012098D01*
+X002601Y012098D01*
+X002601Y012518D01*
+X002601Y012499D02*
+X002701Y012499D01*
+X002701Y012401D02*
+X002601Y012401D01*
+X002601Y012302D02*
+X002701Y012302D01*
+X002701Y012204D02*
+X002601Y012204D01*
+X002601Y012105D02*
+X002701Y012105D01*
+X002853Y012105D02*
+X003450Y012105D01*
+X003456Y012098D02*
+X003601Y012098D01*
+X003601Y012518D01*
+X003181Y012518D01*
+X003181Y012374D01*
+X003456Y012098D01*
+X003456Y012038D02*
+X003181Y011763D01*
+X003181Y011374D01*
+X003456Y011098D01*
+X003846Y011098D01*
+X004121Y011374D01*
+X004121Y011763D01*
+X003846Y012038D01*
+X003456Y012038D01*
+X003425Y012007D02*
+X002877Y012007D01*
+X002846Y012038D02*
+X002456Y012038D01*
+X002181Y011763D01*
+X002181Y011374D01*
+X002456Y011098D01*
+X002846Y011098D01*
+X003121Y011374D01*
+X003121Y011763D01*
+X002846Y012038D01*
+X002976Y011908D02*
+X003326Y011908D01*
+X003228Y011810D02*
+X003075Y011810D01*
+X003121Y011711D02*
+X003181Y011711D01*
+X003181Y011612D02*
+X003121Y011612D01*
+X003121Y011514D02*
+X003181Y011514D01*
+X003181Y011415D02*
+X003121Y011415D01*
+X003064Y011317D02*
+X003238Y011317D01*
+X003337Y011218D02*
+X002966Y011218D01*
+X002867Y011120D02*
+X003435Y011120D01*
+X003867Y011120D02*
+X004435Y011120D01*
+X004456Y011098D02*
+X004846Y011098D01*
+X005121Y011374D01*
+X005121Y011763D01*
+X004846Y012038D01*
+X004456Y012038D01*
+X004181Y011763D01*
+X004181Y011374D01*
+X004456Y011098D01*
+X004337Y011218D02*
+X003966Y011218D01*
+X004064Y011317D02*
+X004238Y011317D01*
+X004181Y011415D02*
+X004121Y011415D01*
+X004121Y011514D02*
+X004181Y011514D01*
+X004181Y011612D02*
+X004121Y011612D01*
+X004121Y011711D02*
+X004181Y011711D01*
+X004228Y011810D02*
+X004075Y011810D01*
+X003976Y011908D02*
+X004326Y011908D01*
+X004425Y012007D02*
+X003877Y012007D01*
+X003853Y012105D02*
+X004450Y012105D01*
+X004456Y012098D02*
+X004601Y012098D01*
+X004601Y012518D01*
+X004181Y012518D01*
+X004181Y012374D01*
+X004456Y012098D01*
+X004601Y012105D02*
+X004701Y012105D01*
+X004701Y012204D02*
+X004601Y012204D01*
+X004601Y012302D02*
+X004701Y012302D01*
+X004701Y012401D02*
+X004601Y012401D01*
+X004601Y012499D02*
+X004701Y012499D01*
+X004701Y012598D02*
+X005601Y012598D01*
+X005601Y012518D02*
+X005181Y012518D01*
+X005181Y012374D01*
+X005456Y012098D01*
+X005601Y012098D01*
+X005601Y012518D01*
+X005601Y012499D02*
+X005701Y012499D01*
+X005701Y012401D02*
+X005601Y012401D01*
+X005601Y012302D02*
+X005701Y012302D01*
+X005701Y012204D02*
+X005601Y012204D01*
+X005601Y012105D02*
+X005701Y012105D01*
+X005853Y012105D02*
+X006450Y012105D01*
+X006456Y012098D02*
+X006601Y012098D01*
+X006601Y012518D01*
+X006181Y012518D01*
+X006181Y012374D01*
+X006456Y012098D01*
+X006456Y012038D02*
+X006181Y011763D01*
+X006181Y011618D01*
+X006601Y011618D01*
+X006601Y011518D01*
+X006701Y011518D01*
+X006701Y011098D01*
+X006846Y011098D01*
+X007121Y011374D01*
+X007121Y011518D01*
+X006701Y011518D01*
+X006701Y011618D01*
+X007121Y011618D01*
+X007121Y011763D01*
+X006846Y012038D01*
+X006701Y012038D01*
+X006701Y011619D01*
+X006601Y011619D01*
+X006601Y012038D01*
+X006456Y012038D01*
+X006425Y012007D02*
+X005877Y012007D01*
+X005846Y012038D02*
+X005456Y012038D01*
+X005181Y011763D01*
+X005181Y011374D01*
+X005456Y011098D01*
+X005846Y011098D01*
+X006121Y011374D01*
+X006121Y011763D01*
+X005846Y012038D01*
+X005976Y011908D02*
+X006326Y011908D01*
+X006228Y011810D02*
+X006075Y011810D01*
+X006121Y011711D02*
+X006181Y011711D01*
+X006121Y011612D02*
+X006601Y011612D01*
+X006601Y011518D02*
+X006181Y011518D01*
+X006181Y011374D01*
+X006456Y011098D01*
+X006601Y011098D01*
+X006601Y011518D01*
+X006601Y011514D02*
+X006701Y011514D01*
+X006701Y011612D02*
+X007181Y011612D01*
+X007181Y011514D02*
+X007121Y011514D01*
+X007121Y011415D02*
+X007181Y011415D01*
+X007181Y011374D02*
+X007456Y011098D01*
+X007846Y011098D01*
+X008121Y011374D01*
+X008121Y011763D01*
+X007846Y012038D01*
+X007456Y012038D01*
+X007181Y011763D01*
+X007181Y011374D01*
+X007238Y011317D02*
+X007064Y011317D01*
+X006966Y011218D02*
+X007337Y011218D01*
+X007435Y011120D02*
+X006867Y011120D01*
+X006701Y011120D02*
+X006601Y011120D01*
+X006601Y011218D02*
+X006701Y011218D01*
+X006701Y011317D02*
+X006601Y011317D01*
+X006601Y011415D02*
+X006701Y011415D01*
+X006701Y011711D02*
+X006601Y011711D01*
+X006601Y011810D02*
+X006701Y011810D01*
+X006701Y011908D02*
+X006601Y011908D01*
+X006601Y012007D02*
+X006701Y012007D01*
+X006701Y012105D02*
+X006601Y012105D01*
+X006601Y012204D02*
+X006701Y012204D01*
+X006701Y012302D02*
+X006601Y012302D01*
+X006601Y012401D02*
+X006701Y012401D01*
+X006701Y012499D02*
+X006601Y012499D01*
+X006601Y012598D02*
+X005701Y012598D01*
+X005991Y012894D02*
+X006312Y012894D01*
+X006213Y012795D02*
+X006089Y012795D01*
+X006121Y012696D02*
+X006181Y012696D01*
+X006181Y012499D02*
+X006121Y012499D01*
+X006121Y012401D02*
+X006181Y012401D01*
+X006253Y012302D02*
+X006050Y012302D01*
+X005951Y012204D02*
+X006351Y012204D01*
+X006853Y012105D02*
+X007450Y012105D01*
+X007456Y012098D02*
+X007601Y012098D01*
+X007601Y012518D01*
+X007181Y012518D01*
+X007181Y012374D01*
+X007456Y012098D01*
+X007425Y012007D02*
+X006877Y012007D01*
+X006976Y011908D02*
+X007326Y011908D01*
+X007228Y011810D02*
+X007075Y011810D01*
+X007121Y011711D02*
+X007181Y011711D01*
+X007351Y012204D02*
+X006951Y012204D01*
+X007050Y012302D02*
+X007253Y012302D01*
+X007181Y012401D02*
+X007121Y012401D01*
+X007121Y012499D02*
+X007181Y012499D01*
+X007181Y012696D02*
+X007121Y012696D01*
+X007089Y012795D02*
+X007213Y012795D01*
+X007312Y012894D02*
+X006991Y012894D01*
+X006701Y012598D02*
+X007601Y012598D01*
+X007601Y012499D02*
+X007701Y012499D01*
+X007701Y012401D02*
+X007601Y012401D01*
+X007601Y012302D02*
+X007701Y012302D01*
+X007701Y012204D02*
+X007601Y012204D01*
+X007601Y012105D02*
+X007701Y012105D01*
+X007853Y012105D02*
+X008450Y012105D01*
+X008456Y012098D02*
+X008601Y012098D01*
+X008601Y012518D01*
+X008181Y012518D01*
+X008181Y012374D01*
+X008456Y012098D01*
+X008456Y012038D02*
+X008181Y011763D01*
+X008181Y011374D01*
+X008456Y011098D01*
+X008846Y011098D01*
+X009121Y011374D01*
+X009121Y011763D01*
+X008846Y012038D01*
+X008456Y012038D01*
+X008425Y012007D02*
+X007877Y012007D01*
+X007976Y011908D02*
+X008326Y011908D01*
+X008228Y011810D02*
+X008075Y011810D01*
+X008121Y011711D02*
+X008181Y011711D01*
+X008181Y011612D02*
+X008121Y011612D01*
+X008121Y011514D02*
+X008181Y011514D01*
+X008181Y011415D02*
+X008121Y011415D01*
+X008064Y011317D02*
+X008238Y011317D01*
+X008337Y011218D02*
+X007966Y011218D01*
+X007867Y011120D02*
+X008435Y011120D01*
+X008867Y011120D02*
+X009435Y011120D01*
+X009456Y011098D02*
+X009846Y011098D01*
+X010121Y011374D01*
+X010121Y011763D01*
+X009846Y012038D01*
+X009456Y012038D01*
+X009181Y011763D01*
+X009181Y011374D01*
+X009456Y011098D01*
+X009337Y011218D02*
+X008966Y011218D01*
+X009064Y011317D02*
+X009238Y011317D01*
+X009181Y011415D02*
+X009121Y011415D01*
+X009121Y011514D02*
+X009181Y011514D01*
+X009181Y011612D02*
+X009121Y011612D01*
+X009121Y011711D02*
+X009181Y011711D01*
+X009228Y011810D02*
+X009075Y011810D01*
+X008976Y011908D02*
+X009326Y011908D01*
+X009425Y012007D02*
+X008877Y012007D01*
+X008853Y012105D02*
+X009450Y012105D01*
+X009456Y012098D02*
+X009601Y012098D01*
+X009601Y012518D01*
+X009181Y012518D01*
+X009181Y012374D01*
+X009456Y012098D01*
+X009601Y012105D02*
+X009701Y012105D01*
+X009701Y012204D02*
+X009601Y012204D01*
+X009601Y012302D02*
+X009701Y012302D01*
+X009701Y012401D02*
+X009601Y012401D01*
+X009601Y012499D02*
+X009701Y012499D01*
+X009701Y012598D02*
+X010601Y012598D01*
+X010601Y012518D02*
+X010181Y012518D01*
+X010181Y012374D01*
+X010456Y012098D01*
+X010601Y012098D01*
+X010601Y012518D01*
+X010601Y012499D02*
+X010701Y012499D01*
+X010701Y012401D02*
+X010601Y012401D01*
+X010601Y012302D02*
+X010701Y012302D01*
+X010701Y012204D02*
+X010601Y012204D01*
+X010601Y012105D02*
+X010701Y012105D01*
+X010853Y012105D02*
+X011450Y012105D01*
+X011456Y012098D02*
+X011601Y012098D01*
+X011601Y012518D01*
+X011181Y012518D01*
+X011181Y012374D01*
+X011456Y012098D01*
+X011456Y012038D02*
+X011181Y011763D01*
+X011181Y011374D01*
+X011456Y011098D01*
+X011846Y011098D01*
+X012121Y011374D01*
+X012121Y011763D01*
+X011846Y012038D01*
+X011456Y012038D01*
+X011425Y012007D02*
+X010877Y012007D01*
+X010846Y012038D02*
+X010456Y012038D01*
+X010181Y011763D01*
+X010181Y011374D01*
+X010456Y011098D01*
+X010846Y011098D01*
+X011121Y011374D01*
+X011121Y011763D01*
+X010846Y012038D01*
+X010976Y011908D02*
+X011326Y011908D01*
+X011228Y011810D02*
+X011075Y011810D01*
+X011121Y011711D02*
+X011181Y011711D01*
+X011181Y011612D02*
+X011121Y011612D01*
+X011121Y011514D02*
+X011181Y011514D01*
+X011181Y011415D02*
+X011121Y011415D01*
+X011064Y011317D02*
+X011238Y011317D01*
+X011337Y011218D02*
+X010966Y011218D01*
+X010867Y011120D02*
+X011435Y011120D01*
+X011867Y011120D02*
+X012435Y011120D01*
+X012456Y011098D02*
+X012846Y011098D01*
+X013121Y011374D01*
+X013121Y011763D01*
+X012846Y012038D01*
+X012456Y012038D01*
+X012181Y011763D01*
+X012181Y011374D01*
+X012456Y011098D01*
+X012337Y011218D02*
+X011966Y011218D01*
+X012064Y011317D02*
+X012238Y011317D01*
+X012181Y011415D02*
+X012121Y011415D01*
+X012121Y011514D02*
+X012181Y011514D01*
+X012181Y011612D02*
+X012121Y011612D01*
+X012121Y011711D02*
+X012181Y011711D01*
+X012228Y011810D02*
+X012075Y011810D01*
+X011976Y011908D02*
+X012326Y011908D01*
+X012425Y012007D02*
+X011877Y012007D01*
+X011853Y012105D02*
+X012450Y012105D01*
+X012456Y012098D02*
+X012601Y012098D01*
+X012601Y012518D01*
+X012181Y012518D01*
+X012181Y012374D01*
+X012456Y012098D01*
+X012601Y012105D02*
+X012701Y012105D01*
+X012701Y012204D02*
+X012601Y012204D01*
+X012601Y012302D02*
+X012701Y012302D01*
+X012701Y012401D02*
+X012601Y012401D01*
+X012601Y012499D02*
+X012701Y012499D01*
+X012701Y012598D02*
+X013601Y012598D01*
+X013601Y012518D02*
+X013181Y012518D01*
+X013181Y012374D01*
+X013456Y012098D01*
+X013601Y012098D01*
+X013601Y012518D01*
+X013601Y012499D02*
+X013701Y012499D01*
+X013701Y012401D02*
+X013601Y012401D01*
+X013601Y012302D02*
+X013701Y012302D01*
+X013701Y012204D02*
+X013601Y012204D01*
+X013601Y012105D02*
+X013701Y012105D01*
+X013853Y012105D02*
+X014450Y012105D01*
+X014456Y012098D02*
+X014601Y012098D01*
+X014601Y012518D01*
+X014181Y012518D01*
+X014181Y012374D01*
+X014456Y012098D01*
+X014456Y012038D02*
+X014181Y011763D01*
+X014181Y011374D01*
+X014456Y011098D01*
+X014846Y011098D01*
+X015121Y011374D01*
+X015121Y011763D01*
+X014846Y012038D01*
+X014456Y012038D01*
+X014425Y012007D02*
+X013877Y012007D01*
+X013846Y012038D02*
+X013456Y012038D01*
+X013181Y011763D01*
+X013181Y011374D01*
+X013456Y011098D01*
+X013846Y011098D01*
+X014121Y011374D01*
+X014121Y011763D01*
+X013846Y012038D01*
+X013976Y011908D02*
+X014326Y011908D01*
+X014228Y011810D02*
+X014075Y011810D01*
+X014121Y011711D02*
+X014181Y011711D01*
+X014181Y011612D02*
+X014121Y011612D01*
+X014121Y011514D02*
+X014181Y011514D01*
+X014181Y011415D02*
+X014121Y011415D01*
+X014064Y011317D02*
+X014238Y011317D01*
+X014337Y011218D02*
+X013966Y011218D01*
+X013867Y011120D02*
+X014435Y011120D01*
+X014867Y011120D02*
+X015435Y011120D01*
+X015337Y011218D02*
+X014966Y011218D01*
+X015064Y011317D02*
+X015238Y011317D01*
+X015181Y011415D02*
+X015121Y011415D01*
+X015121Y011514D02*
+X015181Y011514D01*
+X015181Y011612D02*
+X015121Y011612D01*
+X015121Y011711D02*
+X015181Y011711D01*
+X015228Y011810D02*
+X015075Y011810D01*
+X014976Y011908D02*
+X015326Y011908D01*
+X015425Y012007D02*
+X014877Y012007D01*
+X014853Y012105D02*
+X015450Y012105D01*
+X015456Y012098D02*
+X015601Y012098D01*
+X015601Y012518D01*
+X015181Y012518D01*
+X015181Y012374D01*
+X015456Y012098D01*
+X015601Y012105D02*
+X015701Y012105D01*
+X015701Y012204D02*
+X015601Y012204D01*
+X015601Y012302D02*
+X015701Y012302D01*
+X015701Y012401D02*
+X015601Y012401D01*
+X015601Y012499D02*
+X015701Y012499D01*
+X015701Y012598D02*
+X016601Y012598D01*
+X016601Y012518D02*
+X016181Y012518D01*
+X016181Y012374D01*
+X016456Y012098D01*
+X016601Y012098D01*
+X016601Y012518D01*
+X016601Y012499D02*
+X016701Y012499D01*
+X016701Y012401D02*
+X016601Y012401D01*
+X016601Y012302D02*
+X016701Y012302D01*
+X016701Y012204D02*
+X016601Y012204D01*
+X016601Y012105D02*
+X016701Y012105D01*
+X016701Y012007D02*
+X016601Y012007D01*
+X016601Y011908D02*
+X016701Y011908D01*
+X016701Y011810D02*
+X016601Y011810D01*
+X016601Y011711D02*
+X016701Y011711D01*
+X016976Y011908D02*
+X017001Y011908D01*
+X017001Y012007D02*
+X016877Y012007D01*
+X016853Y012105D02*
+X017001Y012105D01*
+X017001Y012204D02*
+X016951Y012204D01*
+X016450Y012105D02*
+X015853Y012105D01*
+X015877Y012007D02*
+X016425Y012007D01*
+X016326Y011908D02*
+X015976Y011908D01*
+X016075Y011810D02*
+X016228Y011810D01*
+X016181Y011711D02*
+X016121Y011711D01*
+X015951Y012204D02*
+X016351Y012204D01*
+X016253Y012302D02*
+X016050Y012302D01*
+X016121Y012401D02*
+X016181Y012401D01*
+X016181Y012499D02*
+X016121Y012499D01*
+X016121Y012696D02*
+X016181Y012696D01*
+X016213Y012795D02*
+X016089Y012795D01*
+X015991Y012894D02*
+X016312Y012894D01*
+X015601Y012598D02*
+X014701Y012598D01*
+X014701Y012499D02*
+X014601Y012499D01*
+X014601Y012401D02*
+X014701Y012401D01*
+X014701Y012302D02*
+X014601Y012302D01*
+X014601Y012204D02*
+X014701Y012204D01*
+X014701Y012105D02*
+X014601Y012105D01*
+X014351Y012204D02*
+X013951Y012204D01*
+X014050Y012302D02*
+X014253Y012302D01*
+X014181Y012401D02*
+X014121Y012401D01*
+X014121Y012499D02*
+X014181Y012499D01*
+X014181Y012696D02*
+X014121Y012696D01*
+X014089Y012795D02*
+X014213Y012795D01*
+X014312Y012894D02*
+X013991Y012894D01*
+X013701Y012598D02*
+X014601Y012598D01*
+X014991Y012894D02*
+X015312Y012894D01*
+X015213Y012795D02*
+X015089Y012795D01*
+X015121Y012696D02*
+X015181Y012696D01*
+X015181Y012499D02*
+X015121Y012499D01*
+X015121Y012401D02*
+X015181Y012401D01*
+X015253Y012302D02*
+X015050Y012302D01*
+X014951Y012204D02*
+X015351Y012204D01*
+X016867Y011120D02*
+X017001Y011120D01*
+X017001Y011218D02*
+X016966Y011218D01*
+X017001Y011021D02*
+X016863Y011021D01*
+X016961Y010923D02*
+X017001Y010923D01*
+X016980Y010233D02*
+X017001Y010233D01*
+X017001Y010134D02*
+X016882Y010134D01*
+X016848Y010036D02*
+X017001Y010036D01*
+X017001Y009937D02*
+X016947Y009937D01*
+X015406Y009149D02*
+X000301Y009149D01*
+X000301Y009247D02*
+X015307Y009247D01*
+X015209Y009346D02*
+X000301Y009346D01*
+X001867Y011120D02*
+X002435Y011120D01*
+X002337Y011218D02*
+X001966Y011218D01*
+X002064Y011317D02*
+X002238Y011317D01*
+X002181Y011415D02*
+X002121Y011415D01*
+X002121Y011514D02*
+X002181Y011514D01*
+X002181Y011612D02*
+X002121Y011612D01*
+X002121Y011711D02*
+X002181Y011711D01*
+X002228Y011810D02*
+X002075Y011810D01*
+X001976Y011908D02*
+X002326Y011908D01*
+X002425Y012007D02*
+X001877Y012007D01*
+X001853Y012105D02*
+X002450Y012105D01*
+X002351Y012204D02*
+X001951Y012204D01*
+X002050Y012302D02*
+X002253Y012302D01*
+X002181Y012401D02*
+X002121Y012401D01*
+X002121Y012499D02*
+X002181Y012499D01*
+X002181Y012696D02*
+X002121Y012696D01*
+X002089Y012795D02*
+X002213Y012795D01*
+X002312Y012894D02*
+X001991Y012894D01*
+X001601Y012598D02*
+X000701Y012598D01*
+X000701Y012499D02*
+X000601Y012499D01*
+X000601Y012401D02*
+X000701Y012401D01*
+X000701Y012302D02*
+X000601Y012302D01*
+X000601Y012204D02*
+X000701Y012204D01*
+X000701Y012105D02*
+X000601Y012105D01*
+X000450Y012105D02*
+X000301Y012105D01*
+X000301Y012007D02*
+X000425Y012007D01*
+X000326Y011908D02*
+X000301Y011908D01*
+X000301Y012204D02*
+X000351Y012204D01*
+X000951Y012204D02*
+X001351Y012204D01*
+X001253Y012302D02*
+X001050Y012302D01*
+X001121Y012401D02*
+X001181Y012401D01*
+X001181Y012499D02*
+X001121Y012499D01*
+X001121Y012696D02*
+X001181Y012696D01*
+X001213Y012795D02*
+X001089Y012795D01*
+X000991Y012894D02*
+X001312Y012894D01*
+X002701Y012598D02*
+X003601Y012598D01*
+X003601Y012499D02*
+X003701Y012499D01*
+X003701Y012401D02*
+X003601Y012401D01*
+X003601Y012302D02*
+X003701Y012302D01*
+X003701Y012204D02*
+X003601Y012204D01*
+X003601Y012105D02*
+X003701Y012105D01*
+X003951Y012204D02*
+X004351Y012204D01*
+X004253Y012302D02*
+X004050Y012302D01*
+X004121Y012401D02*
+X004181Y012401D01*
+X004181Y012499D02*
+X004121Y012499D01*
+X004121Y012696D02*
+X004181Y012696D01*
+X004213Y012795D02*
+X004089Y012795D01*
+X003991Y012894D02*
+X004312Y012894D01*
+X004601Y012598D02*
+X003701Y012598D01*
+X003312Y012894D02*
+X002991Y012894D01*
+X003089Y012795D02*
+X003213Y012795D01*
+X003181Y012696D02*
+X003121Y012696D01*
+X003121Y012499D02*
+X003181Y012499D01*
+X003181Y012401D02*
+X003121Y012401D01*
+X003050Y012302D02*
+X003253Y012302D01*
+X003351Y012204D02*
+X002951Y012204D01*
+X004853Y012105D02*
+X005450Y012105D01*
+X005425Y012007D02*
+X004877Y012007D01*
+X004976Y011908D02*
+X005326Y011908D01*
+X005228Y011810D02*
+X005075Y011810D01*
+X005121Y011711D02*
+X005181Y011711D01*
+X005181Y011612D02*
+X005121Y011612D01*
+X005121Y011514D02*
+X005181Y011514D01*
+X005181Y011415D02*
+X005121Y011415D01*
+X005064Y011317D02*
+X005238Y011317D01*
+X005337Y011218D02*
+X004966Y011218D01*
+X004867Y011120D02*
+X005435Y011120D01*
+X005867Y011120D02*
+X006435Y011120D01*
+X006337Y011218D02*
+X005966Y011218D01*
+X006064Y011317D02*
+X006238Y011317D01*
+X006181Y011415D02*
+X006121Y011415D01*
+X006121Y011514D02*
+X006181Y011514D01*
+X005351Y012204D02*
+X004951Y012204D01*
+X005050Y012302D02*
+X005253Y012302D01*
+X005181Y012401D02*
+X005121Y012401D01*
+X005121Y012499D02*
+X005181Y012499D01*
+X005181Y012696D02*
+X005121Y012696D01*
+X005089Y012795D02*
+X005213Y012795D01*
+X005312Y012894D02*
+X004991Y012894D01*
+X007701Y012598D02*
+X008601Y012598D01*
+X008601Y012499D02*
+X008701Y012499D01*
+X008701Y012401D02*
+X008601Y012401D01*
+X008601Y012302D02*
+X008701Y012302D01*
+X008701Y012204D02*
+X008601Y012204D01*
+X008601Y012105D02*
+X008701Y012105D01*
+X008951Y012204D02*
+X009351Y012204D01*
+X009253Y012302D02*
+X009050Y012302D01*
+X009121Y012401D02*
+X009181Y012401D01*
+X009181Y012499D02*
+X009121Y012499D01*
+X009121Y012696D02*
+X009181Y012696D01*
+X009213Y012795D02*
+X009089Y012795D01*
+X008991Y012894D02*
+X009312Y012894D01*
+X009601Y012598D02*
+X008701Y012598D01*
+X008312Y012894D02*
+X007991Y012894D01*
+X008089Y012795D02*
+X008213Y012795D01*
+X008181Y012696D02*
+X008121Y012696D01*
+X008121Y012499D02*
+X008181Y012499D01*
+X008181Y012401D02*
+X008121Y012401D01*
+X008050Y012302D02*
+X008253Y012302D01*
+X008351Y012204D02*
+X007951Y012204D01*
+X009853Y012105D02*
+X010450Y012105D01*
+X010425Y012007D02*
+X009877Y012007D01*
+X009976Y011908D02*
+X010326Y011908D01*
+X010228Y011810D02*
+X010075Y011810D01*
+X010121Y011711D02*
+X010181Y011711D01*
+X010181Y011612D02*
+X010121Y011612D01*
+X010121Y011514D02*
+X010181Y011514D01*
+X010181Y011415D02*
+X010121Y011415D01*
+X010064Y011317D02*
+X010238Y011317D01*
+X010337Y011218D02*
+X009966Y011218D01*
+X009867Y011120D02*
+X010435Y011120D01*
+X010351Y012204D02*
+X009951Y012204D01*
+X010050Y012302D02*
+X010253Y012302D01*
+X010181Y012401D02*
+X010121Y012401D01*
+X010121Y012499D02*
+X010181Y012499D01*
+X010181Y012696D02*
+X010121Y012696D01*
+X010089Y012795D02*
+X010213Y012795D01*
+X010312Y012894D02*
+X009991Y012894D01*
+X010701Y012598D02*
+X011601Y012598D01*
+X011601Y012499D02*
+X011701Y012499D01*
+X011701Y012401D02*
+X011601Y012401D01*
+X011601Y012302D02*
+X011701Y012302D01*
+X011701Y012204D02*
+X011601Y012204D01*
+X011601Y012105D02*
+X011701Y012105D01*
+X011951Y012204D02*
+X012351Y012204D01*
+X012253Y012302D02*
+X012050Y012302D01*
+X012121Y012401D02*
+X012181Y012401D01*
+X012181Y012499D02*
+X012121Y012499D01*
+X012121Y012696D02*
+X012181Y012696D01*
+X012213Y012795D02*
+X012089Y012795D01*
+X011991Y012894D02*
+X012312Y012894D01*
+X012601Y012598D02*
+X011701Y012598D01*
+X011312Y012894D02*
+X010991Y012894D01*
+X011089Y012795D02*
+X011213Y012795D01*
+X011181Y012696D02*
+X011121Y012696D01*
+X011121Y012499D02*
+X011181Y012499D01*
+X011181Y012401D02*
+X011121Y012401D01*
+X011050Y012302D02*
+X011253Y012302D01*
+X011351Y012204D02*
+X010951Y012204D01*
+X012853Y012105D02*
+X013450Y012105D01*
+X013425Y012007D02*
+X012877Y012007D01*
+X012976Y011908D02*
+X013326Y011908D01*
+X013228Y011810D02*
+X013075Y011810D01*
+X013121Y011711D02*
+X013181Y011711D01*
+X013181Y011612D02*
+X013121Y011612D01*
+X013121Y011514D02*
+X013181Y011514D01*
+X013181Y011415D02*
+X013121Y011415D01*
+X013064Y011317D02*
+X013238Y011317D01*
+X013337Y011218D02*
+X012966Y011218D01*
+X012867Y011120D02*
+X013435Y011120D01*
+X013351Y012204D02*
+X012951Y012204D01*
+X013050Y012302D02*
+X013253Y012302D01*
+X013181Y012401D02*
+X013121Y012401D01*
+X013121Y012499D02*
+X013181Y012499D01*
+X013181Y012696D02*
+X013121Y012696D01*
+X013089Y012795D02*
+X013213Y012795D01*
+X013312Y012894D02*
+X012991Y012894D01*
+X015355Y009937D02*
+X007303Y009937D01*
+X007204Y009839D02*
+X015257Y009839D01*
+X015181Y009740D02*
+X007169Y009740D01*
+X007168Y009642D02*
+X015181Y009642D01*
+X015181Y009543D02*
+X007127Y009543D01*
+X007048Y009445D02*
+X015181Y009445D01*
+X015315Y005897D02*
+X000301Y005897D01*
+X000301Y005798D02*
+X015217Y005798D01*
+X015181Y005700D02*
+X000301Y005700D01*
+X000301Y005601D02*
+X015181Y005601D01*
+X015181Y005503D02*
+X000301Y005503D01*
+X000301Y005404D02*
+X015181Y005404D01*
+X015249Y005306D02*
+X000301Y005306D01*
+X000301Y005207D02*
+X015348Y005207D01*
+X015446Y005109D02*
+X000301Y005109D01*
+X000301Y005010D02*
+X015428Y005010D01*
+X015330Y004912D02*
+X000301Y004912D01*
+X000301Y004813D02*
+X015231Y004813D01*
+X015181Y004714D02*
+X000301Y004714D01*
+X000301Y004616D02*
+X015181Y004616D01*
+X015181Y004517D02*
+X000301Y004517D01*
+X000301Y004419D02*
+X015181Y004419D01*
+X015235Y004320D02*
+X000301Y004320D01*
+X000301Y004222D02*
+X015333Y004222D01*
+X015432Y004123D02*
+X000301Y004123D01*
+X000301Y004025D02*
+X002813Y004025D01*
+X002738Y003926D02*
+X000301Y003926D01*
+X000301Y003828D02*
+X002701Y003828D01*
+X002701Y003729D02*
+X000301Y003729D01*
+X000301Y003630D02*
+X002729Y003630D01*
+X002793Y003532D02*
+X002183Y003532D01*
+X002262Y003433D02*
+X002851Y003433D01*
+X002851Y003335D02*
+X002301Y003335D01*
+X002301Y003236D02*
+X002851Y003236D01*
+X002851Y003138D02*
+X002276Y003138D01*
+X002217Y003039D02*
+X002851Y003039D01*
+X002851Y002941D02*
+X002151Y002941D01*
+X002151Y002842D02*
+X002851Y002842D01*
+X002851Y002744D02*
+X002151Y002744D01*
+X002151Y002645D02*
+X002851Y002645D01*
+X002851Y002546D02*
+X002151Y002546D01*
+X002151Y002448D02*
+X002851Y002448D01*
+X002849Y002349D02*
+X002153Y002349D01*
+X002151Y002068D02*
+X002851Y002068D01*
+X003051Y002268D01*
+X003051Y003768D01*
+X003373Y003630D02*
+X015181Y003630D01*
+X015181Y003532D02*
+X003310Y003532D01*
+X003251Y003433D02*
+X015181Y003433D01*
+X015220Y003335D02*
+X003251Y003335D01*
+X003251Y003236D02*
+X015319Y003236D01*
+X015417Y003138D02*
+X003251Y003138D01*
+X003401Y003729D02*
+X015181Y003729D01*
+X015246Y003828D02*
+X003401Y003828D01*
+X003365Y003926D02*
+X015344Y003926D01*
+X015443Y004025D02*
+X003290Y004025D01*
+X001720Y003532D02*
+X000301Y003532D01*
+X007401Y010036D02*
+X007863Y010036D01*
+X015871Y004123D02*
+X016432Y004123D01*
+X016443Y004025D02*
+X015859Y004025D01*
+X015958Y003926D02*
+X016344Y003926D01*
+X016246Y003828D02*
+X016057Y003828D01*
+X016121Y003729D02*
+X016181Y003729D01*
+X016181Y003630D02*
+X016121Y003630D01*
+X016601Y003433D02*
+X016701Y003433D01*
+X016701Y003335D02*
+X016601Y003335D01*
+X016601Y003236D02*
+X016701Y003236D01*
+X016701Y003138D02*
+X016601Y003138D01*
+X016885Y003138D02*
+X017001Y003138D01*
+X017001Y003236D02*
+X016984Y003236D01*
+X016958Y003926D02*
+X017001Y003926D01*
+X017001Y004025D02*
+X016859Y004025D01*
+X016871Y004123D02*
+X017001Y004123D01*
+X017001Y004222D02*
+X016969Y004222D01*
+X016333Y004222D02*
+X015969Y004222D01*
+X016068Y004320D02*
+X016235Y004320D01*
+X016181Y004419D02*
+X016121Y004419D01*
+X016121Y004517D02*
+X016181Y004517D01*
+D13*
+X003051Y003768D03*
+X001951Y003268D03*
+M02*
diff --git a/digital/cms-intro/pcb/orders/eurocircuits_2011-05-11/cms_intro.GBO b/digital/cms-intro/pcb/orders/eurocircuits_2011-05-11/cms_intro.GBO
new file mode 100644
index 00000000..fa114b37
--- /dev/null
+++ b/digital/cms-intro/pcb/orders/eurocircuits_2011-05-11/cms_intro.GBO
@@ -0,0 +1,2103 @@
+G75*
+G70*
+%OFA0B0*%
+%FSLAX24Y24*%
+%IPPOS*%
+%LPD*%
+%AMOC8*
+5,1,8,0,0,1.08239X$1,22.5*
+%
+%ADD10C,0.0080*%
+%ADD11C,0.0060*%
+D10*
+X003901Y003528D02*
+X004061Y003428D01*
+X005821Y002628D01*
+X006621Y002348D01*
+X007061Y002228D01*
+X007301Y002228D01*
+X007501Y002268D01*
+X010941Y003388D01*
+X010901Y003388D02*
+X009981Y003668D01*
+X009861Y003628D02*
+X009541Y003428D01*
+X009141Y003268D01*
+X008861Y003188D01*
+X008581Y003148D01*
+X008261Y003108D01*
+X007861Y003148D01*
+X007501Y003228D01*
+X007141Y003348D01*
+X006821Y003508D01*
+X006581Y003748D01*
+X006381Y004028D01*
+X006261Y004308D01*
+X006241Y004468D01*
+X006301Y004668D01*
+X006241Y004688D01*
+X006241Y004468D01*
+X006481Y004428D02*
+X006481Y004328D01*
+X006581Y004208D01*
+X006701Y004148D01*
+X006801Y004188D01*
+X006801Y004248D01*
+X006721Y004268D01*
+X006641Y004368D01*
+X006621Y004528D01*
+X006541Y004508D01*
+X006481Y004428D01*
+X006494Y004446D02*
+X006632Y004446D01*
+X006661Y004388D02*
+X006741Y004268D01*
+X006861Y004228D01*
+X008581Y003428D01*
+X008741Y003388D01*
+X008901Y003428D01*
+X009301Y003588D01*
+X009781Y003828D01*
+X009861Y003908D01*
+X009881Y003988D01*
+X009981Y004088D01*
+X009981Y004168D01*
+X009921Y004228D01*
+X009981Y004308D02*
+X009821Y004188D01*
+X009661Y004268D02*
+X009861Y004428D01*
+X009861Y004588D01*
+X009856Y004603D02*
+X009642Y004603D01*
+X009641Y004608D02*
+X009721Y004688D01*
+X009821Y004748D01*
+X009901Y004768D01*
+X009941Y005148D01*
+X010041Y005088D01*
+X010001Y004748D01*
+X010041Y004748D01*
+X010121Y004688D01*
+X010141Y004628D01*
+X010121Y004548D01*
+X010061Y004508D01*
+X009881Y004628D01*
+X009841Y004588D01*
+X009841Y004508D01*
+X009741Y004468D01*
+X009661Y004508D01*
+X009641Y004608D01*
+X009658Y004524D02*
+X009841Y004524D01*
+X009920Y004603D02*
+X010135Y004603D01*
+X010124Y004681D02*
+X009714Y004681D01*
+X009601Y004808D02*
+X009561Y004768D01*
+X009401Y004868D01*
+X009361Y004828D01*
+X009341Y004728D01*
+X009261Y004708D01*
+X009181Y004768D01*
+X009181Y004888D01*
+X009261Y004968D01*
+X009381Y005028D01*
+X009421Y005068D01*
+X009441Y005468D01*
+X009541Y005428D01*
+X009501Y005028D01*
+X009561Y004988D01*
+X009621Y004928D01*
+X009621Y004868D01*
+X009601Y004808D01*
+X009611Y004838D02*
+X009449Y004838D01*
+X009381Y004828D02*
+X009381Y004668D01*
+X009181Y004508D01*
+X009261Y004588D02*
+X008961Y004748D01*
+X009021Y004788D02*
+X009061Y004828D01*
+X009061Y004988D01*
+X009061Y005008D02*
+X008921Y005108D01*
+X008881Y005048D01*
+X008841Y004928D01*
+X008721Y004928D01*
+X008661Y004988D01*
+X008661Y005108D01*
+X008761Y005208D01*
+X008881Y005268D01*
+X008921Y005308D01*
+X008941Y005628D01*
+X009041Y005628D01*
+X009021Y005408D01*
+X009001Y005268D01*
+X009061Y005228D01*
+X009141Y005168D01*
+X009141Y005108D01*
+X009101Y005028D01*
+X009061Y005008D01*
+X009124Y005074D02*
+X008969Y005074D01*
+X008901Y005068D02*
+X008901Y004908D01*
+X008801Y004828D01*
+X008501Y004988D01*
+X008541Y005068D02*
+X008381Y004908D01*
+X008221Y004988D02*
+X008381Y005148D01*
+X008381Y005308D01*
+X008363Y005310D02*
+X008208Y005310D01*
+X008201Y005288D02*
+X008241Y005408D01*
+X008301Y005448D01*
+X008421Y005468D01*
+X008421Y005668D01*
+X008541Y005668D01*
+X008541Y005468D01*
+X008641Y005428D01*
+X008661Y005348D01*
+X008641Y005248D01*
+X008581Y005188D01*
+X008561Y005248D01*
+X008401Y005348D01*
+X008341Y005288D01*
+X008321Y005148D01*
+X008241Y005168D01*
+X008201Y005288D01*
+X008220Y005231D02*
+X008333Y005231D01*
+X008322Y005153D02*
+X008304Y005153D01*
+X008301Y005088D02*
+X008021Y005228D01*
+X007941Y005268D01*
+X007861Y005268D01*
+X007701Y005228D01*
+X007341Y005068D01*
+X007461Y005128D01*
+X006981Y005428D01*
+X006861Y005368D01*
+X007341Y005068D01*
+X007021Y004908D01*
+X006781Y004708D01*
+X006621Y004548D01*
+X006661Y004388D01*
+X006642Y004367D02*
+X006481Y004367D01*
+X006514Y004289D02*
+X006705Y004289D01*
+X006801Y004210D02*
+X006580Y004210D01*
+X006861Y004228D02*
+X006861Y004348D01*
+X007101Y004548D01*
+X007701Y004828D01*
+X007901Y004908D01*
+X007981Y004908D01*
+X009881Y003988D01*
+X010061Y003828D02*
+X009861Y003628D01*
+X010061Y003828D02*
+X010221Y004068D01*
+X010261Y004268D01*
+X010261Y004508D01*
+X010181Y004868D01*
+X009941Y005148D01*
+X009661Y005348D01*
+X009341Y005548D01*
+X008941Y005668D01*
+X008501Y005708D01*
+X007981Y005708D01*
+X007541Y005628D01*
+X007141Y005508D01*
+X006741Y005268D01*
+X006421Y004988D01*
+X006341Y004808D01*
+X006301Y004668D01*
+X006305Y004681D02*
+X006262Y004681D01*
+X006241Y004688D02*
+X006301Y005068D01*
+X006361Y005208D01*
+X006461Y005348D01*
+X006621Y005528D01*
+X006781Y005668D01*
+X007181Y005908D01*
+X007621Y006028D01*
+X008021Y006108D01*
+X008381Y006148D01*
+X008941Y006068D01*
+X009501Y005828D01*
+X009541Y005788D01*
+X009501Y005708D01*
+X009501Y005628D01*
+X009541Y005508D01*
+X009661Y005468D01*
+X009781Y005468D01*
+X009901Y005548D01*
+X010061Y005348D01*
+X010221Y005028D01*
+X010261Y004828D01*
+X010261Y004508D01*
+X010258Y004524D02*
+X010261Y004524D01*
+X010261Y004603D02*
+X010240Y004603D01*
+X010223Y004681D02*
+X010261Y004681D01*
+X010261Y004760D02*
+X010205Y004760D01*
+X010188Y004838D02*
+X010259Y004838D01*
+X010243Y004917D02*
+X010140Y004917D01*
+X010072Y004996D02*
+X010228Y004996D01*
+X010198Y005074D02*
+X010005Y005074D01*
+X010040Y005074D02*
+X009933Y005074D01*
+X009935Y005153D02*
+X010159Y005153D01*
+X010120Y005231D02*
+X009825Y005231D01*
+X009715Y005310D02*
+X010081Y005310D01*
+X010029Y005388D02*
+X009597Y005388D01*
+X009537Y005388D02*
+X009437Y005388D01*
+X009433Y005310D02*
+X009529Y005310D01*
+X009521Y005231D02*
+X009429Y005231D01*
+X009425Y005153D02*
+X009514Y005153D01*
+X009506Y005074D02*
+X009421Y005074D01*
+X009316Y004996D02*
+X009550Y004996D01*
+X009621Y004917D02*
+X009210Y004917D01*
+X009181Y004838D02*
+X009371Y004838D01*
+X009348Y004760D02*
+X009192Y004760D01*
+X009021Y004788D02*
+X008861Y004668D01*
+X008801Y004828D02*
+X008701Y004748D01*
+X008661Y004996D02*
+X008864Y004996D01*
+X008898Y005074D02*
+X008661Y005074D01*
+X008705Y005153D02*
+X009141Y005153D01*
+X009057Y005231D02*
+X008807Y005231D01*
+X008921Y005310D02*
+X009007Y005310D01*
+X009018Y005388D02*
+X008926Y005388D01*
+X008931Y005467D02*
+X009026Y005467D01*
+X009034Y005545D02*
+X008936Y005545D01*
+X008941Y005624D02*
+X009041Y005624D01*
+X009089Y005624D02*
+X009503Y005624D01*
+X009501Y005702D02*
+X008567Y005702D01*
+X008541Y005624D02*
+X008421Y005624D01*
+X008421Y005545D02*
+X008541Y005545D01*
+X008545Y005467D02*
+X008412Y005467D01*
+X008463Y005310D02*
+X008653Y005310D01*
+X008651Y005388D02*
+X008234Y005388D01*
+X008021Y005228D02*
+X008021Y005108D01*
+X007981Y004948D01*
+X007721Y005248D02*
+X007601Y005188D01*
+X007081Y005508D01*
+X007201Y005568D01*
+X007721Y005248D01*
+X007687Y005231D02*
+X007532Y005231D01*
+X007621Y005310D02*
+X007404Y005310D01*
+X007494Y005388D02*
+X007276Y005388D01*
+X007366Y005467D02*
+X007149Y005467D01*
+X007072Y005467D02*
+X006566Y005467D01*
+X006497Y005388D02*
+X006941Y005388D01*
+X006901Y005388D02*
+X007045Y005388D01*
+X006955Y005310D02*
+X007171Y005310D01*
+X007081Y005231D02*
+X007297Y005231D01*
+X007206Y005153D02*
+X007422Y005153D01*
+X007353Y005074D02*
+X007332Y005074D01*
+X007221Y005008D02*
+X007081Y004948D01*
+X006641Y005208D01*
+X006741Y005288D01*
+X007221Y005008D01*
+X007191Y004996D02*
+X007001Y004996D01*
+X007109Y005074D02*
+X006868Y005074D01*
+X006974Y005153D02*
+X006736Y005153D01*
+X006699Y005231D02*
+X006377Y005231D01*
+X006337Y005153D02*
+X006609Y005153D01*
+X006670Y005231D02*
+X006839Y005231D01*
+X006810Y005310D02*
+X006434Y005310D01*
+X006519Y005074D02*
+X006304Y005074D01*
+X005661Y005628D02*
+X005625Y005583D01*
+X005591Y005535D01*
+X005561Y005486D01*
+X005534Y005434D01*
+X005510Y005381D01*
+X005490Y005327D01*
+X005474Y005271D01*
+X005461Y005215D01*
+X005451Y005157D01*
+X005446Y005100D01*
+X005444Y005041D01*
+X005446Y004983D01*
+X005452Y004926D01*
+X005461Y004868D01*
+X005501Y004828D01*
+X005541Y004828D01*
+X005621Y004868D01*
+X005550Y004917D02*
+X005501Y004917D01*
+X005501Y004868D02*
+X005661Y005028D01*
+X005741Y005308D01*
+X005661Y005548D01*
+X005501Y005228D01*
+X005501Y004868D01*
+X005501Y004996D02*
+X005628Y004996D01*
+X005674Y005074D02*
+X005501Y005074D01*
+X005501Y005153D02*
+X005697Y005153D01*
+X005719Y005231D02*
+X005503Y005231D01*
+X005542Y005310D02*
+X005741Y005310D01*
+X005715Y005388D02*
+X005581Y005388D01*
+X005620Y005467D02*
+X005688Y005467D01*
+X005660Y005545D02*
+X005662Y005545D01*
+X005661Y005628D02*
+X005701Y005628D01*
+X005582Y005708D02*
+X005595Y005727D01*
+X005610Y005744D01*
+X005628Y005758D01*
+X005648Y005770D01*
+X005670Y005778D01*
+X005692Y005784D01*
+X005715Y005786D01*
+X005738Y005785D01*
+X005761Y005780D01*
+X005782Y005772D01*
+X005803Y005761D01*
+X005821Y005748D01*
+X005847Y005719D01*
+X005869Y005687D01*
+X005890Y005654D01*
+X005907Y005619D01*
+X005921Y005583D01*
+X005933Y005546D01*
+X005941Y005508D01*
+X006290Y004996D02*
+X006429Y004996D01*
+X006389Y004917D02*
+X006277Y004917D01*
+X006265Y004838D02*
+X006355Y004838D01*
+X006327Y004760D02*
+X006252Y004760D01*
+X006605Y004524D02*
+X006622Y004524D01*
+X007021Y004148D02*
+X007481Y003928D01*
+X007381Y003868D01*
+X007221Y003848D01*
+X007061Y003948D01*
+X007001Y004048D01*
+X007021Y004148D01*
+X007018Y004132D02*
+X007056Y004132D01*
+X007002Y004053D02*
+X007221Y004053D01*
+X007145Y003896D02*
+X007427Y003896D01*
+X007385Y003974D02*
+X007046Y003974D01*
+X007481Y004168D02*
+X007561Y004208D01*
+X007621Y004148D02*
+X007601Y004128D01*
+X007641Y004168D02*
+X007701Y004088D01*
+X007701Y004108D02*
+X007721Y004108D01*
+X007781Y004008D02*
+X007801Y003988D01*
+X007821Y004008D02*
+X007841Y004068D01*
+X007981Y003988D02*
+X007921Y003928D01*
+X007981Y003948D02*
+X007981Y003968D01*
+X008061Y003888D02*
+X008081Y003888D01*
+X008121Y003868D02*
+X008121Y003928D01*
+X008241Y003888D02*
+X008241Y003828D01*
+X008261Y003808D02*
+X008341Y003808D01*
+X008301Y003788D02*
+X008301Y003768D01*
+X008441Y003708D02*
+X008481Y003748D01*
+X008601Y003648D02*
+X008721Y003628D01*
+X008661Y003588D02*
+X008641Y003628D01*
+X008521Y003448D02*
+X008401Y003368D01*
+X008241Y003388D01*
+X008101Y003468D01*
+X008061Y003568D01*
+X008101Y003648D01*
+X008521Y003448D01*
+X008486Y003425D02*
+X008178Y003425D01*
+X008087Y003503D02*
+X008406Y003503D01*
+X008241Y003582D02*
+X008068Y003582D01*
+X007976Y003660D02*
+X007649Y003660D01*
+X007661Y003648D02*
+X007841Y003588D01*
+X007941Y003608D01*
+X007981Y003668D01*
+X007541Y003908D01*
+X007521Y003788D01*
+X007661Y003648D01*
+X007571Y003739D02*
+X007852Y003739D01*
+X007708Y003817D02*
+X007526Y003817D01*
+X007539Y003896D02*
+X007564Y003896D01*
+X007481Y004168D02*
+X007481Y004248D01*
+X005261Y004548D02*
+X005258Y004635D01*
+X005259Y004723D01*
+X005265Y004810D01*
+X005274Y004897D01*
+X005288Y004984D01*
+X005305Y005069D01*
+X005327Y005154D01*
+X005352Y005238D01*
+X005381Y005320D01*
+X005413Y005401D01*
+X005450Y005481D01*
+X005490Y005559D01*
+X005534Y005634D01*
+X005581Y005708D01*
+X005701Y005628D02*
+X005724Y005583D01*
+X005742Y005536D01*
+X005758Y005487D01*
+X005769Y005438D01*
+X005777Y005388D01*
+X005781Y005337D01*
+X005782Y005286D01*
+X005778Y005236D01*
+X005771Y005185D01*
+X005760Y005136D01*
+X005746Y005087D01*
+X005727Y005040D01*
+X005706Y004994D01*
+X005681Y004950D01*
+X005653Y004908D01*
+X005621Y004868D01*
+X005261Y004548D02*
+X005266Y004514D01*
+X005273Y004481D01*
+X005284Y004448D01*
+X005298Y004417D01*
+X005315Y004387D01*
+X005334Y004358D01*
+X005357Y004332D01*
+X005381Y004308D01*
+X005382Y004308D02*
+X005400Y004295D01*
+X005421Y004284D01*
+X005442Y004276D01*
+X005465Y004271D01*
+X005488Y004270D01*
+X005511Y004272D01*
+X005533Y004278D01*
+X005555Y004286D01*
+X005575Y004298D01*
+X005593Y004312D01*
+X005608Y004329D01*
+X005621Y004348D01*
+X004421Y004428D02*
+X004412Y004486D01*
+X004406Y004543D01*
+X004404Y004601D01*
+X004406Y004660D01*
+X004411Y004717D01*
+X004421Y004775D01*
+X004434Y004831D01*
+X004450Y004887D01*
+X004470Y004941D01*
+X004494Y004994D01*
+X004521Y005046D01*
+X004551Y005095D01*
+X004585Y005143D01*
+X004621Y005188D01*
+X004661Y005188D01*
+X004542Y005268D02*
+X004555Y005287D01*
+X004570Y005304D01*
+X004588Y005318D01*
+X004608Y005330D01*
+X004630Y005338D01*
+X004652Y005344D01*
+X004675Y005346D01*
+X004698Y005345D01*
+X004721Y005340D01*
+X004742Y005332D01*
+X004763Y005321D01*
+X004781Y005308D01*
+X005941Y005509D02*
+X005955Y005444D01*
+X005966Y005379D01*
+X005974Y005313D01*
+X005977Y005247D01*
+X005978Y005180D01*
+X005974Y005114D01*
+X005967Y005048D01*
+X005957Y004983D01*
+X005943Y004918D01*
+X005925Y004855D01*
+X005904Y004792D01*
+X005879Y004730D01*
+X005852Y004670D01*
+X005821Y004612D01*
+X005787Y004555D01*
+X005749Y004500D01*
+X005709Y004447D01*
+X005666Y004397D01*
+X005621Y004349D01*
+X004541Y005268D02*
+X004494Y005194D01*
+X004450Y005119D01*
+X004410Y005041D01*
+X004373Y004961D01*
+X004341Y004880D01*
+X004312Y004798D01*
+X004287Y004714D01*
+X004265Y004629D01*
+X004248Y004544D01*
+X004234Y004457D01*
+X004225Y004370D01*
+X004219Y004283D01*
+X004218Y004195D01*
+X004221Y004108D01*
+X004342Y003868D02*
+X004360Y003855D01*
+X004381Y003844D01*
+X004402Y003836D01*
+X004425Y003831D01*
+X004448Y003830D01*
+X004471Y003832D01*
+X004493Y003838D01*
+X004515Y003846D01*
+X004535Y003858D01*
+X004553Y003872D01*
+X004568Y003889D01*
+X004581Y003908D01*
+X004341Y003868D02*
+X004317Y003892D01*
+X004294Y003918D01*
+X004275Y003947D01*
+X004258Y003977D01*
+X004244Y004008D01*
+X004233Y004041D01*
+X004226Y004074D01*
+X004221Y004108D01*
+X004461Y004388D02*
+X004501Y004388D01*
+X004581Y004428D01*
+X004557Y004524D02*
+X004461Y004524D01*
+X004461Y004446D02*
+X004479Y004446D01*
+X004461Y004428D02*
+X004621Y004588D01*
+X004701Y004868D01*
+X004621Y005108D01*
+X004461Y004788D01*
+X004461Y004428D01*
+X004421Y004428D02*
+X004461Y004388D01*
+X004461Y004603D02*
+X004625Y004603D01*
+X004648Y004681D02*
+X004461Y004681D01*
+X004461Y004760D02*
+X004670Y004760D01*
+X004693Y004838D02*
+X004486Y004838D01*
+X004526Y004917D02*
+X004685Y004917D01*
+X004659Y004996D02*
+X004565Y004996D01*
+X004604Y005074D02*
+X004633Y005074D01*
+X004901Y005068D02*
+X004893Y005106D01*
+X004881Y005143D01*
+X004867Y005179D01*
+X004850Y005214D01*
+X004829Y005247D01*
+X004807Y005279D01*
+X004781Y005308D01*
+X004661Y005188D02*
+X004684Y005143D01*
+X004702Y005096D01*
+X004718Y005047D01*
+X004729Y004998D01*
+X004737Y004948D01*
+X004741Y004897D01*
+X004742Y004846D01*
+X004738Y004796D01*
+X004731Y004745D01*
+X004720Y004696D01*
+X004706Y004647D01*
+X004687Y004600D01*
+X004666Y004554D01*
+X004641Y004510D01*
+X004613Y004468D01*
+X004581Y004428D01*
+X004581Y003909D02*
+X004626Y003957D01*
+X004669Y004007D01*
+X004709Y004060D01*
+X004747Y004115D01*
+X004781Y004172D01*
+X004812Y004230D01*
+X004839Y004290D01*
+X004864Y004352D01*
+X004885Y004415D01*
+X004903Y004478D01*
+X004917Y004543D01*
+X004927Y004608D01*
+X004934Y004674D01*
+X004938Y004740D01*
+X004937Y004807D01*
+X004934Y004873D01*
+X004926Y004939D01*
+X004915Y005004D01*
+X004901Y005069D01*
+X003821Y005538D02*
+X004061Y007188D01*
+X004221Y007948D01*
+X007701Y009748D01*
+X008981Y008908D01*
+X009008Y009032D02*
+X009075Y009025D01*
+X009135Y009031D01*
+X009192Y009048D01*
+X009245Y009076D01*
+X009291Y009114D01*
+X009329Y009160D01*
+X009357Y009213D01*
+X009374Y009270D01*
+X009380Y009330D01*
+X008728Y009330D01*
+X008728Y009547D01*
+X008293Y009547D01*
+X008301Y009656D01*
+X008327Y009762D01*
+X008369Y009863D01*
+X008426Y009956D01*
+X008497Y010039D01*
+X008580Y010110D01*
+X008673Y010167D01*
+X008774Y010209D01*
+X008880Y010234D01*
+X008989Y010243D01*
+X009293Y010243D01*
+X009554Y010199D01*
+X009771Y010112D01*
+X009771Y009808D01*
+X009554Y009938D01*
+X009293Y009982D01*
+X009119Y009982D01*
+X009051Y009976D01*
+X008985Y009958D01*
+X008923Y009929D01*
+X008867Y009890D01*
+X008819Y009842D01*
+X008780Y009786D01*
+X008751Y009724D01*
+X008734Y009658D01*
+X008728Y009590D01*
+X009858Y009590D01*
+X009858Y009503D01*
+X009848Y009381D01*
+X009820Y009262D01*
+X009773Y009148D01*
+X009709Y009043D01*
+X009629Y008950D01*
+X009536Y008870D01*
+X009431Y008806D01*
+X009317Y008759D01*
+X009198Y008730D01*
+X009075Y008721D01*
+X009032Y008721D01*
+X008916Y008730D01*
+X008804Y008757D01*
+X008696Y008801D01*
+X008598Y008862D01*
+X008509Y008937D01*
+X008434Y009026D01*
+X008373Y009124D01*
+X008329Y009232D01*
+X008302Y009344D01*
+X008293Y009460D01*
+X008293Y009547D01*
+X008728Y009547D01*
+X008728Y009373D01*
+X008734Y009305D01*
+X008754Y009240D01*
+X008786Y009180D01*
+X008830Y009127D01*
+X008882Y009084D01*
+X008942Y009052D01*
+X009008Y009032D01*
+X008890Y009080D02*
+X008401Y009080D01*
+X008359Y009158D02*
+X008804Y009158D01*
+X008756Y009237D02*
+X008328Y009237D01*
+X008309Y009315D02*
+X008733Y009315D01*
+X008728Y009394D02*
+X009849Y009394D01*
+X009856Y009472D02*
+X008728Y009472D01*
+X008293Y009472D01*
+X008298Y009394D02*
+X008728Y009394D01*
+X008731Y009630D02*
+X008299Y009630D01*
+X008293Y009551D02*
+X009858Y009551D01*
+X010162Y009547D02*
+X010119Y009808D01*
+X010206Y010025D01*
+X010336Y010156D01*
+X010510Y010199D01*
+X010858Y010199D01*
+X010989Y010156D01*
+X011163Y009982D01*
+X011163Y010199D01*
+X011467Y010199D01*
+X011597Y010199D01*
+X011597Y009199D01*
+X011554Y009112D01*
+X011467Y008982D01*
+X011336Y008851D01*
+X011206Y008764D01*
+X011032Y008721D01*
+X010684Y008721D01*
+X010510Y008764D01*
+X010249Y008851D01*
+X010249Y009112D01*
+X010380Y009069D01*
+X010554Y009025D01*
+X010989Y009025D01*
+X011076Y009069D01*
+X011163Y009156D01*
+X011163Y009286D01*
+X010728Y009286D01*
+X010467Y009330D01*
+X010293Y009416D01*
+X010162Y009547D01*
+X010162Y009551D02*
+X010680Y009551D01*
+X010684Y009547D02*
+X011163Y009547D01*
+X011467Y010199D01*
+X011163Y009590D01*
+X011163Y009764D01*
+X010989Y009938D01*
+X010858Y009982D01*
+X010728Y009982D01*
+X010597Y009895D01*
+X010554Y009764D01*
+X010597Y009634D01*
+X010684Y009547D01*
+X010602Y009630D02*
+X010149Y009630D01*
+X010136Y009708D02*
+X010572Y009708D01*
+X010561Y009787D02*
+X010123Y009787D01*
+X010142Y009865D02*
+X010587Y009865D01*
+X010671Y009944D02*
+X010173Y009944D01*
+X010205Y010022D02*
+X011122Y010022D01*
+X011163Y010022D02*
+X011378Y010022D01*
+X011384Y010022D02*
+X011597Y010022D01*
+X011597Y009944D02*
+X011348Y009944D01*
+X011339Y009944D02*
+X010972Y009944D01*
+X011062Y009865D02*
+X011300Y009865D01*
+X011311Y009865D02*
+X011597Y009865D01*
+X011597Y009787D02*
+X011274Y009787D01*
+X011261Y009787D02*
+X011140Y009787D01*
+X011163Y009708D02*
+X011221Y009708D01*
+X011238Y009708D02*
+X011597Y009708D01*
+X011597Y009630D02*
+X011201Y009630D01*
+X011182Y009630D02*
+X011163Y009630D01*
+X011164Y009551D02*
+X011597Y009551D01*
+X011597Y009472D02*
+X010237Y009472D01*
+X010338Y009394D02*
+X011597Y009394D01*
+X011597Y009315D02*
+X010552Y009315D01*
+X010347Y009080D02*
+X010249Y009080D01*
+X010249Y009001D02*
+X011480Y009001D01*
+X011532Y009080D02*
+X011087Y009080D01*
+X011163Y009158D02*
+X011577Y009158D01*
+X011597Y009237D02*
+X011163Y009237D01*
+X011408Y008923D02*
+X010249Y008923D01*
+X010271Y008844D02*
+X011326Y008844D01*
+X011208Y008766D02*
+X010506Y008766D01*
+X008941Y008749D02*
+X008933Y008677D01*
+X008929Y008604D01*
+X008928Y008532D01*
+X008932Y008459D01*
+X008940Y008387D01*
+X008952Y008316D01*
+X008967Y008245D01*
+X008986Y008175D01*
+X009010Y008106D01*
+X009036Y008039D01*
+X009067Y007973D01*
+X009101Y007909D01*
+X009661Y008988D02*
+X009722Y008973D01*
+X009782Y008955D01*
+X009841Y008933D01*
+X009899Y008907D01*
+X009955Y008878D01*
+X010009Y008846D01*
+X010061Y008811D01*
+X010111Y008773D01*
+X010158Y008732D01*
+X010203Y008688D01*
+X010245Y008641D01*
+X010285Y008592D01*
+X010322Y008541D01*
+X010355Y008488D01*
+X010385Y008433D01*
+X010412Y008376D01*
+X010436Y008318D01*
+X010456Y008258D01*
+X010472Y008197D01*
+X010485Y008136D01*
+X010494Y008073D01*
+X010499Y008011D01*
+X010501Y007948D01*
+X010541Y007948D02*
+X011381Y007428D01*
+X011381Y004988D01*
+X011341Y004268D01*
+X011301Y003908D01*
+X011181Y003548D01*
+X011061Y003428D01*
+X010901Y003388D01*
+X009981Y004308D02*
+X010021Y004388D01*
+X010021Y004508D01*
+X010037Y004524D02*
+X010085Y004524D01*
+X010003Y004760D02*
+X009867Y004760D01*
+X009909Y004838D02*
+X010012Y004838D01*
+X010021Y004917D02*
+X009917Y004917D01*
+X009925Y004996D02*
+X010030Y004996D01*
+X009966Y005467D02*
+X009472Y005467D01*
+X009445Y005467D02*
+X009441Y005467D01*
+X009529Y005545D02*
+X009346Y005545D01*
+X009541Y005748D02*
+X009741Y005908D01*
+X009701Y006068D01*
+X009741Y006228D01*
+X010221Y006708D01*
+X011061Y007428D01*
+X011461Y007668D01*
+X011701Y007788D01*
+X012101Y007828D01*
+X012341Y007788D01*
+X012421Y007668D01*
+X012461Y007468D01*
+X012421Y007268D01*
+X012261Y007028D01*
+X011861Y006708D01*
+X011381Y006308D01*
+X010861Y005948D01*
+X010381Y005668D01*
+X010221Y005628D01*
+X009981Y005668D01*
+X009821Y005748D01*
+X009741Y005908D01*
+X009734Y005938D02*
+X010844Y005938D01*
+X010960Y006017D02*
+X009714Y006017D01*
+X009708Y006095D02*
+X011073Y006095D01*
+X011187Y006174D02*
+X009727Y006174D01*
+X009765Y006252D02*
+X011300Y006252D01*
+X011408Y006331D02*
+X009844Y006331D01*
+X009922Y006409D02*
+X011502Y006409D01*
+X011597Y006488D02*
+X010001Y006488D01*
+X010079Y006566D02*
+X011691Y006566D01*
+X011785Y006645D02*
+X010158Y006645D01*
+X010239Y006723D02*
+X011880Y006723D01*
+X011978Y006802D02*
+X010330Y006802D01*
+X010422Y006881D02*
+X012076Y006881D01*
+X012175Y006959D02*
+X010514Y006959D01*
+X010605Y007038D02*
+X012267Y007038D01*
+X012320Y007116D02*
+X010697Y007116D01*
+X010789Y007195D02*
+X012372Y007195D01*
+X012422Y007273D02*
+X010880Y007273D01*
+X010972Y007352D02*
+X012438Y007352D01*
+X012454Y007430D02*
+X011065Y007430D01*
+X011195Y007509D02*
+X012453Y007509D01*
+X012437Y007587D02*
+X011326Y007587D01*
+X011457Y007666D02*
+X012422Y007666D01*
+X012370Y007745D02*
+X011614Y007745D01*
+X012048Y007823D02*
+X012133Y007823D01*
+X012076Y008764D02*
+X012510Y008764D01*
+X012510Y008982D01*
+X012597Y008895D01*
+X012728Y008808D01*
+X012902Y008764D01*
+X013032Y008764D01*
+X013206Y008808D01*
+X013336Y008895D01*
+X013423Y008982D01*
+X013510Y008982D01*
+X013597Y008851D01*
+X013728Y008764D01*
+X014119Y008764D01*
+X014206Y008808D01*
+X014337Y008938D01*
+X014380Y009069D01*
+X014380Y010199D01*
+X013989Y010199D01*
+X013989Y009199D01*
+X013902Y009112D01*
+X013815Y009069D01*
+X013684Y009069D01*
+X013554Y009112D01*
+X013467Y009286D01*
+X013467Y010199D01*
+X013032Y010199D01*
+X013032Y009199D01*
+X012945Y009112D01*
+X012858Y009069D01*
+X012684Y009069D01*
+X012597Y009112D01*
+X012510Y009286D01*
+X012510Y010199D01*
+X012076Y010199D01*
+X012076Y008764D01*
+X012076Y008766D02*
+X012510Y008766D01*
+X012510Y008844D02*
+X012076Y008844D01*
+X012076Y008923D02*
+X012510Y008923D01*
+X012569Y008923D02*
+X013364Y008923D01*
+X013261Y008844D02*
+X012673Y008844D01*
+X012662Y009080D02*
+X012076Y009080D01*
+X012076Y009158D02*
+X012574Y009158D01*
+X012535Y009237D02*
+X012076Y009237D01*
+X012076Y009315D02*
+X012510Y009315D01*
+X012510Y009394D02*
+X012076Y009394D01*
+X012076Y009472D02*
+X012510Y009472D01*
+X012510Y009551D02*
+X012076Y009551D01*
+X012076Y009630D02*
+X012510Y009630D01*
+X012510Y009708D02*
+X012076Y009708D01*
+X012076Y009787D02*
+X012510Y009787D01*
+X012510Y009865D02*
+X012076Y009865D01*
+X012076Y009944D02*
+X012510Y009944D01*
+X012510Y010022D02*
+X012076Y010022D01*
+X012076Y010101D02*
+X012510Y010101D01*
+X012510Y010179D02*
+X012076Y010179D01*
+X011597Y010179D02*
+X011458Y010179D01*
+X011457Y010179D02*
+X011163Y010179D01*
+X011163Y010101D02*
+X011418Y010101D01*
+X011421Y010101D02*
+X011597Y010101D01*
+X011043Y010101D02*
+X010282Y010101D01*
+X010431Y010179D02*
+X010917Y010179D01*
+X009833Y009315D02*
+X009378Y009315D01*
+X009364Y009237D02*
+X009810Y009237D01*
+X009777Y009158D02*
+X009327Y009158D01*
+X009249Y009080D02*
+X009731Y009080D01*
+X009673Y009001D02*
+X008455Y009001D01*
+X008526Y008923D02*
+X009597Y008923D01*
+X009493Y008844D02*
+X008627Y008844D01*
+X008783Y008766D02*
+X009333Y008766D01*
+X009101Y007908D02*
+X009124Y007855D01*
+X009151Y007803D01*
+X009181Y007753D01*
+X009215Y007706D01*
+X009252Y007661D01*
+X009291Y007618D01*
+X009334Y007579D01*
+X009379Y007542D01*
+X009426Y007508D01*
+X009476Y007478D01*
+X009528Y007451D01*
+X009581Y007428D01*
+X009627Y007407D01*
+X009674Y007389D01*
+X009722Y007375D01*
+X009771Y007365D01*
+X009821Y007359D01*
+X009871Y007357D01*
+X009921Y007359D01*
+X009971Y007365D01*
+X010020Y007375D01*
+X010068Y007388D01*
+X010115Y007406D01*
+X010160Y007427D01*
+X010204Y007451D01*
+X010246Y007479D01*
+X010285Y007511D01*
+X010321Y007545D01*
+X010355Y007582D01*
+X010386Y007622D01*
+X010413Y007664D01*
+X010437Y007708D01*
+X010458Y007753D01*
+X010474Y007800D01*
+X010487Y007849D01*
+X010497Y007898D01*
+X010502Y007948D01*
+X012076Y009001D02*
+X014358Y009001D01*
+X014380Y009080D02*
+X013837Y009080D01*
+X013948Y009158D02*
+X014380Y009158D01*
+X014380Y009237D02*
+X013989Y009237D01*
+X013989Y009315D02*
+X014380Y009315D01*
+X014380Y009394D02*
+X013989Y009394D01*
+X013989Y009472D02*
+X014380Y009472D01*
+X014380Y009551D02*
+X013989Y009551D01*
+X013989Y009630D02*
+X014380Y009630D01*
+X014380Y009708D02*
+X013989Y009708D01*
+X013989Y009787D02*
+X014380Y009787D01*
+X014380Y009865D02*
+X013989Y009865D01*
+X013989Y009944D02*
+X014380Y009944D01*
+X014380Y010022D02*
+X013989Y010022D01*
+X013989Y010101D02*
+X014380Y010101D01*
+X014380Y010179D02*
+X013989Y010179D01*
+X013467Y010179D02*
+X013032Y010179D01*
+X013032Y010101D02*
+X013467Y010101D01*
+X013467Y010022D02*
+X013032Y010022D01*
+X013032Y009944D02*
+X013467Y009944D01*
+X013467Y009865D02*
+X013032Y009865D01*
+X013032Y009787D02*
+X013467Y009787D01*
+X013467Y009708D02*
+X013032Y009708D01*
+X013032Y009630D02*
+X013467Y009630D01*
+X013467Y009551D02*
+X013032Y009551D01*
+X013032Y009472D02*
+X013467Y009472D01*
+X013467Y009394D02*
+X013032Y009394D01*
+X013032Y009315D02*
+X013467Y009315D01*
+X013492Y009237D02*
+X013032Y009237D01*
+X012991Y009158D02*
+X013531Y009158D01*
+X013651Y009080D02*
+X012880Y009080D01*
+X012896Y008766D02*
+X013037Y008766D01*
+X013550Y008923D02*
+X014321Y008923D01*
+X014242Y008844D02*
+X013608Y008844D01*
+X013726Y008766D02*
+X014122Y008766D01*
+X016026Y009568D02*
+X016276Y009568D01*
+X010709Y005859D02*
+X009766Y005859D01*
+X009805Y005781D02*
+X010574Y005781D01*
+X010440Y005702D02*
+X009913Y005702D01*
+X009897Y005545D02*
+X009904Y005545D01*
+X009861Y005508D02*
+X010101Y005708D01*
+X009537Y005781D02*
+X006969Y005781D01*
+X007100Y005859D02*
+X009429Y005859D01*
+X009245Y005938D02*
+X007290Y005938D01*
+X005102Y007829D02*
+X005012Y007726D01*
+X004926Y007620D01*
+X004847Y007510D01*
+X004772Y007396D01*
+X004703Y007279D01*
+X004639Y007158D01*
+X004582Y007035D01*
+X004530Y006909D01*
+X004484Y006780D01*
+X004445Y006650D01*
+X004411Y006518D01*
+X004384Y006385D01*
+X004364Y006250D01*
+X004349Y006115D01*
+X004342Y005979D01*
+X003821Y005538D02*
+X003621Y004388D01*
+X003621Y003988D01*
+X003641Y003808D01*
+X003661Y003748D01*
+X003741Y003668D01*
+X003901Y003528D01*
+X006641Y005545D02*
+X007264Y005545D01*
+X007239Y005545D02*
+X007155Y005545D01*
+X007181Y005788D02*
+X007141Y005988D01*
+X007181Y006668D01*
+X007261Y007268D01*
+X007461Y008268D01*
+X007380Y008634D02*
+X006728Y008634D01*
+X006728Y008286D01*
+X008467Y008286D01*
+X008467Y008634D01*
+X007815Y008634D01*
+X007815Y010199D01*
+X007380Y010199D01*
+X007380Y008634D01*
+X007380Y008687D02*
+X007815Y008687D01*
+X007815Y008766D02*
+X007380Y008766D01*
+X007380Y008844D02*
+X007815Y008844D01*
+X007815Y008923D02*
+X007380Y008923D01*
+X007380Y009001D02*
+X007815Y009001D01*
+X007815Y009080D02*
+X007380Y009080D01*
+X007380Y009158D02*
+X007815Y009158D01*
+X007815Y009237D02*
+X007380Y009237D01*
+X007380Y009315D02*
+X007815Y009315D01*
+X007815Y009394D02*
+X007380Y009394D01*
+X007380Y009472D02*
+X007815Y009472D01*
+X007815Y009551D02*
+X007380Y009551D01*
+X007380Y009630D02*
+X007815Y009630D01*
+X007815Y009708D02*
+X007380Y009708D01*
+X007380Y009787D02*
+X007815Y009787D01*
+X007815Y009865D02*
+X007380Y009865D01*
+X007380Y009944D02*
+X007815Y009944D01*
+X007815Y010022D02*
+X007380Y010022D01*
+X007380Y010101D02*
+X007815Y010101D01*
+X007815Y010179D02*
+X007380Y010179D01*
+X006433Y009827D02*
+X006458Y009732D01*
+X006467Y009634D01*
+X006467Y009590D01*
+X006461Y009522D01*
+X006443Y009457D01*
+X006414Y009395D01*
+X006375Y009339D01*
+X006327Y009291D01*
+X006271Y009252D01*
+X006209Y009223D01*
+X006143Y009205D01*
+X006075Y009199D01*
+X006135Y009193D01*
+X006192Y009176D01*
+X006244Y009148D01*
+X006291Y009110D01*
+X006328Y009064D01*
+X006357Y009011D01*
+X006374Y008954D01*
+X006380Y008895D01*
+X006380Y008634D01*
+X006368Y008562D01*
+X006343Y008494D01*
+X006305Y008432D01*
+X006256Y008379D01*
+X006197Y008336D01*
+X006131Y008306D01*
+X006061Y008289D01*
+X005988Y008286D01*
+X005293Y008286D01*
+X005293Y008590D01*
+X005771Y008590D01*
+X005810Y008595D01*
+X005846Y008608D01*
+X005879Y008628D01*
+X005907Y008656D01*
+X005928Y008689D01*
+X005941Y008726D01*
+X005945Y008764D01*
+X005945Y008808D01*
+X005941Y008850D01*
+X005928Y008891D01*
+X005908Y008929D01*
+X005881Y008962D01*
+X005848Y008989D01*
+X005811Y009009D01*
+X005770Y009021D01*
+X005728Y009025D01*
+X005293Y009025D01*
+X005293Y009330D01*
+X005727Y009330D01*
+X005778Y009335D01*
+X005827Y009349D01*
+X005872Y009374D01*
+X005912Y009406D01*
+X005944Y009445D01*
+X005969Y009491D01*
+X005983Y009540D01*
+X005988Y009590D01*
+X005988Y009634D01*
+X005983Y009685D01*
+X005969Y009734D01*
+X005944Y009779D01*
+X005912Y009818D01*
+X005872Y009851D01*
+X005827Y009875D01*
+X005778Y009890D01*
+X005728Y009895D01*
+X005293Y009895D01*
+X005293Y010199D01*
+X005901Y010199D01*
+X006000Y010191D01*
+X006095Y010165D01*
+X006184Y010123D01*
+X006265Y010067D01*
+X006334Y009997D01*
+X006391Y009916D01*
+X006433Y009827D01*
+X006443Y009787D02*
+X005938Y009787D01*
+X005976Y009708D02*
+X006460Y009708D01*
+X006467Y009630D02*
+X005988Y009630D01*
+X005984Y009551D02*
+X006463Y009551D01*
+X006447Y009472D02*
+X005959Y009472D01*
+X005897Y009394D02*
+X006414Y009394D01*
+X006352Y009315D02*
+X005293Y009315D01*
+X004858Y009315D01*
+X004858Y009237D02*
+X005293Y009237D01*
+X006240Y009237D01*
+X006225Y009158D02*
+X005293Y009158D01*
+X004858Y009158D01*
+X004858Y009080D02*
+X005293Y009080D01*
+X006315Y009080D01*
+X006360Y009001D02*
+X005825Y009001D01*
+X005911Y008923D02*
+X006377Y008923D01*
+X006380Y008844D02*
+X005941Y008844D01*
+X005945Y008766D02*
+X006380Y008766D01*
+X006380Y008687D02*
+X005927Y008687D01*
+X005848Y008609D02*
+X006376Y008609D01*
+X006356Y008530D02*
+X005293Y008530D01*
+X004858Y008530D01*
+X004858Y008609D02*
+X005293Y008609D01*
+X005293Y008687D02*
+X004858Y008687D01*
+X004858Y008766D02*
+X005293Y008766D01*
+X005293Y008844D02*
+X004858Y008844D01*
+X004858Y008923D02*
+X005293Y008923D01*
+X005293Y009001D02*
+X004858Y009001D01*
+X004858Y009394D02*
+X005293Y009394D01*
+X005293Y009472D02*
+X004858Y009472D01*
+X004858Y009551D02*
+X005293Y009551D01*
+X005293Y009630D02*
+X004858Y009630D01*
+X004858Y009708D02*
+X005293Y009708D01*
+X005293Y009787D02*
+X004858Y009787D01*
+X004858Y009865D02*
+X005293Y009865D01*
+X005293Y009944D02*
+X006372Y009944D01*
+X006415Y009865D02*
+X005846Y009865D01*
+X006041Y010179D02*
+X005293Y010179D01*
+X004858Y010179D01*
+X004858Y010199D02*
+X005293Y010199D01*
+X005293Y008286D01*
+X004858Y008286D01*
+X004858Y010199D01*
+X004858Y010101D02*
+X005293Y010101D01*
+X006216Y010101D01*
+X006309Y010022D02*
+X005293Y010022D01*
+X004858Y010022D01*
+X004858Y009944D02*
+X005293Y009944D01*
+X004329Y009332D02*
+X004373Y009264D01*
+X004405Y009190D01*
+X004423Y009112D01*
+X004423Y008721D01*
+X004412Y008642D01*
+X004388Y008566D01*
+X004351Y008495D01*
+X004302Y008432D01*
+X004243Y008379D01*
+X004176Y008336D01*
+X004102Y008306D01*
+X004024Y008289D01*
+X003945Y008286D01*
+X003336Y008286D01*
+X003336Y008590D01*
+X003727Y008590D01*
+X003787Y008596D01*
+X003844Y008614D01*
+X003896Y008642D01*
+X003943Y008680D01*
+X003980Y008726D01*
+X004009Y008778D01*
+X004026Y008835D01*
+X004032Y008895D01*
+X004032Y008938D01*
+X004027Y008989D01*
+X004012Y009038D01*
+X003988Y009083D01*
+X003955Y009123D01*
+X003916Y009155D01*
+X003871Y009179D01*
+X003822Y009194D01*
+X003771Y009199D01*
+X003336Y009199D01*
+X003336Y009503D01*
+X003901Y009503D01*
+X003982Y009508D01*
+X004061Y009498D01*
+X004138Y009475D01*
+X004210Y009439D01*
+X004274Y009390D01*
+X004329Y009332D01*
+X004340Y009315D02*
+X003336Y009315D01*
+X002901Y009315D01*
+X002901Y009237D02*
+X003336Y009237D01*
+X004385Y009237D01*
+X004412Y009158D02*
+X003910Y009158D01*
+X003990Y009080D02*
+X004423Y009080D01*
+X004423Y009001D02*
+X004023Y009001D01*
+X004032Y008923D02*
+X004423Y008923D01*
+X004423Y008844D02*
+X004027Y008844D01*
+X004002Y008766D02*
+X004423Y008766D01*
+X004419Y008687D02*
+X003949Y008687D01*
+X003827Y008609D02*
+X004402Y008609D01*
+X004369Y008530D02*
+X003336Y008530D01*
+X002901Y008530D01*
+X002901Y008609D02*
+X003336Y008609D01*
+X003336Y008687D02*
+X002901Y008687D01*
+X002901Y008766D02*
+X003336Y008766D01*
+X003336Y008844D02*
+X002901Y008844D01*
+X002901Y008923D02*
+X003336Y008923D01*
+X003336Y009001D02*
+X002901Y009001D01*
+X002901Y009080D02*
+X003336Y009080D01*
+X003336Y009158D02*
+X002901Y009158D01*
+X002901Y009394D02*
+X003336Y009394D01*
+X004270Y009394D01*
+X004143Y009472D02*
+X003336Y009472D01*
+X002901Y009472D01*
+X002901Y009551D02*
+X003336Y009551D01*
+X003336Y009630D02*
+X002901Y009630D01*
+X002901Y009708D02*
+X003336Y009708D01*
+X003336Y009787D02*
+X002901Y009787D01*
+X002901Y009865D02*
+X003336Y009865D01*
+X003336Y009944D02*
+X002901Y009944D01*
+X002901Y010022D02*
+X003336Y010022D01*
+X003336Y010101D02*
+X002901Y010101D01*
+X002901Y010179D02*
+X003336Y010179D01*
+X003336Y010199D02*
+X002901Y010199D01*
+X002901Y008286D01*
+X003336Y008286D01*
+X003336Y010199D01*
+X002597Y010199D02*
+X001858Y008286D01*
+X001293Y008286D01*
+X000553Y010199D01*
+X000988Y010199D01*
+X001119Y009851D01*
+X002032Y009851D01*
+X002162Y010199D01*
+X002597Y010199D01*
+X002589Y010179D02*
+X002155Y010179D01*
+X002125Y010101D02*
+X002559Y010101D01*
+X002529Y010022D02*
+X002096Y010022D01*
+X002066Y009944D02*
+X002498Y009944D01*
+X002468Y009865D02*
+X002037Y009865D01*
+X002407Y009708D02*
+X000743Y009708D01*
+X000773Y009630D02*
+X002377Y009630D01*
+X002347Y009551D02*
+X000804Y009551D01*
+X000834Y009472D02*
+X001261Y009472D01*
+X001249Y009503D02*
+X001553Y008721D01*
+X001293Y008286D01*
+X001597Y008721D01*
+X001901Y009503D01*
+X001249Y009503D01*
+X001292Y009394D02*
+X000865Y009394D01*
+X000895Y009315D02*
+X001322Y009315D01*
+X001353Y009237D02*
+X000925Y009237D01*
+X000956Y009158D02*
+X001383Y009158D01*
+X001414Y009080D02*
+X000986Y009080D01*
+X001016Y009001D02*
+X001444Y009001D01*
+X001475Y008923D02*
+X001047Y008923D01*
+X001077Y008844D02*
+X001505Y008844D01*
+X001536Y008766D02*
+X001107Y008766D01*
+X001138Y008687D02*
+X001533Y008687D01*
+X001573Y008687D02*
+X002013Y008687D01*
+X002043Y008766D02*
+X001614Y008766D01*
+X001645Y008844D02*
+X002073Y008844D01*
+X002104Y008923D02*
+X001675Y008923D01*
+X001706Y009001D02*
+X002134Y009001D01*
+X002164Y009080D02*
+X001736Y009080D01*
+X001767Y009158D02*
+X002195Y009158D01*
+X002225Y009237D02*
+X001798Y009237D01*
+X001828Y009315D02*
+X002256Y009315D01*
+X002286Y009394D02*
+X001859Y009394D01*
+X001889Y009472D02*
+X002316Y009472D01*
+X002438Y009787D02*
+X000713Y009787D01*
+X000682Y009865D02*
+X001113Y009865D01*
+X001084Y009944D02*
+X000652Y009944D01*
+X000622Y010022D02*
+X001054Y010022D01*
+X001025Y010101D02*
+X000591Y010101D01*
+X000561Y010179D02*
+X000996Y010179D01*
+X001168Y008609D02*
+X001486Y008609D01*
+X001518Y008609D02*
+X001982Y008609D01*
+X001952Y008530D02*
+X001463Y008530D01*
+X001439Y008530D02*
+X001198Y008530D01*
+X001229Y008451D02*
+X001392Y008451D01*
+X001408Y008451D02*
+X001922Y008451D01*
+X001891Y008373D02*
+X001353Y008373D01*
+X001345Y008373D02*
+X001259Y008373D01*
+X001289Y008294D02*
+X001298Y008294D01*
+X001861Y008294D01*
+X002901Y008294D02*
+X003336Y008294D01*
+X004048Y008294D01*
+X004234Y008373D02*
+X003336Y008373D01*
+X002901Y008373D01*
+X002901Y008451D02*
+X003336Y008451D01*
+X004317Y008451D01*
+X004858Y008451D02*
+X005293Y008451D01*
+X006317Y008451D01*
+X006248Y008373D02*
+X005293Y008373D01*
+X004858Y008373D01*
+X004858Y008294D02*
+X005293Y008294D01*
+X006084Y008294D01*
+X006728Y008294D02*
+X008467Y008294D01*
+X008467Y008373D02*
+X006728Y008373D01*
+X006728Y008451D02*
+X008467Y008451D01*
+X008467Y008530D02*
+X006728Y008530D01*
+X006728Y008609D02*
+X008467Y008609D01*
+X008314Y009708D02*
+X008747Y009708D01*
+X008780Y009787D02*
+X008337Y009787D01*
+X008370Y009865D02*
+X008842Y009865D01*
+X008954Y009944D02*
+X008418Y009944D01*
+X008482Y010022D02*
+X009771Y010022D01*
+X009771Y009944D02*
+X009521Y009944D01*
+X009676Y009865D02*
+X009771Y009865D01*
+X009771Y010101D02*
+X008569Y010101D01*
+X008703Y010179D02*
+X009603Y010179D01*
+X006741Y007388D02*
+X006716Y007447D01*
+X006688Y007504D01*
+X006656Y007559D01*
+X006621Y007612D01*
+X006583Y007663D01*
+X006542Y007712D01*
+X006498Y007758D01*
+X006451Y007801D01*
+X006402Y007842D01*
+X006350Y007879D01*
+X006296Y007913D01*
+X006240Y007944D01*
+X006183Y007971D01*
+X006124Y007995D01*
+X006063Y008015D01*
+X006002Y008032D01*
+X005939Y008045D01*
+X005876Y008054D01*
+X005813Y008059D01*
+X005749Y008060D01*
+X005685Y008057D01*
+X005622Y008051D01*
+X005559Y008041D01*
+X005497Y008027D01*
+X005436Y008009D01*
+X005376Y007987D01*
+X005317Y007962D01*
+X005260Y007934D01*
+X005205Y007902D01*
+X005152Y007866D01*
+X005101Y007828D01*
+X007578Y006017D02*
+X009062Y006017D01*
+X008754Y006095D02*
+X007955Y006095D01*
+X007949Y005702D02*
+X006838Y005702D01*
+X006730Y005624D02*
+X007526Y005624D01*
+X008541Y005228D02*
+X008541Y005068D01*
+X008567Y005231D02*
+X008624Y005231D01*
+X009541Y004748D02*
+X009541Y004588D01*
+X009441Y004508D01*
+X009741Y004348D01*
+X009441Y004508D02*
+X009341Y004428D01*
+D11*
+X014611Y005524D02*
+X014654Y005481D01*
+X014828Y005654D01*
+X014871Y005611D01*
+X014871Y005524D01*
+X014828Y005481D01*
+X014654Y005481D01*
+X014611Y005524D02*
+X014611Y005611D01*
+X014654Y005654D01*
+X014828Y005654D01*
+X014828Y005758D02*
+X014871Y005758D01*
+X014871Y005802D01*
+X014828Y005802D01*
+X014828Y005758D01*
+X014828Y005906D02*
+X014871Y005906D01*
+X014871Y005949D01*
+X014828Y005949D01*
+X014828Y005906D01*
+X014654Y006070D02*
+X014828Y006244D01*
+X014871Y006244D01*
+X014828Y006365D02*
+X014654Y006365D01*
+X014611Y006408D01*
+X014611Y006538D01*
+X014871Y006538D01*
+X014871Y006408D01*
+X014828Y006365D01*
+X014611Y006244D02*
+X014611Y006070D01*
+X014654Y006070D01*
+X014654Y009151D02*
+X014698Y009151D01*
+X014741Y009194D01*
+X014741Y009324D01*
+X014611Y009324D02*
+X014611Y009194D01*
+X014654Y009151D01*
+X014741Y009194D02*
+X014784Y009151D01*
+X014828Y009151D01*
+X014871Y009194D01*
+X014871Y009324D01*
+X014611Y009324D01*
+X014611Y009445D02*
+X014871Y009445D01*
+X014784Y009532D01*
+X014871Y009619D01*
+X014611Y009619D01*
+X014611Y009740D02*
+X014871Y009740D01*
+X014741Y009740D02*
+X014741Y009913D01*
+X014871Y009913D02*
+X014611Y009913D01*
+X014611Y010320D02*
+X014784Y010320D01*
+X014871Y010407D01*
+X014784Y010494D01*
+X014611Y010494D01*
+X014611Y010615D02*
+X014611Y010788D01*
+X014741Y010788D01*
+X014698Y010702D01*
+X014698Y010658D01*
+X014741Y010615D01*
+X014828Y010615D01*
+X014871Y010658D01*
+X014871Y010745D01*
+X014828Y010788D01*
+X012614Y010745D02*
+X012614Y010571D01*
+X012440Y010745D01*
+X012483Y010788D01*
+X012570Y010788D01*
+X012614Y010745D01*
+X012614Y010571D02*
+X012570Y010528D01*
+X012483Y010528D01*
+X012440Y010571D01*
+X012440Y010745D01*
+X012336Y010745D02*
+X012336Y010788D01*
+X012293Y010788D01*
+X012293Y010745D01*
+X012336Y010745D01*
+X012189Y010745D02*
+X012189Y010788D01*
+X012145Y010788D01*
+X012145Y010745D01*
+X012189Y010745D01*
+X012024Y010571D02*
+X011851Y010745D01*
+X011851Y010788D01*
+X011730Y010745D02*
+X011686Y010788D01*
+X011556Y010788D01*
+X011556Y010528D01*
+X011686Y010528D01*
+X011730Y010571D01*
+X011730Y010615D01*
+X011686Y010658D01*
+X011556Y010658D01*
+X011686Y010658D02*
+X011730Y010702D01*
+X011730Y010745D01*
+X011851Y010528D02*
+X012024Y010528D01*
+X012024Y010571D01*
+X007899Y010528D02*
+X007899Y010702D01*
+X007813Y010788D01*
+X007726Y010702D01*
+X007726Y010528D01*
+X007605Y010528D02*
+X007431Y010528D01*
+X007431Y010658D01*
+X007518Y010615D01*
+X007561Y010615D01*
+X007605Y010658D01*
+X007605Y010745D01*
+X007561Y010788D01*
+X007475Y010788D01*
+X007431Y010745D01*
+X007069Y010745D02*
+X007069Y010571D01*
+X007026Y010528D01*
+X006895Y010528D01*
+X006895Y010788D01*
+X007026Y010788D01*
+X007069Y010745D01*
+X006774Y010788D02*
+X006774Y010528D01*
+X006601Y010528D02*
+X006601Y010788D01*
+X006480Y010745D02*
+X006480Y010658D01*
+X006393Y010658D01*
+X006480Y010571D02*
+X006436Y010528D01*
+X006350Y010528D01*
+X006306Y010571D01*
+X006306Y010745D01*
+X006350Y010788D01*
+X006436Y010788D01*
+X006480Y010745D01*
+X006601Y010528D02*
+X006774Y010788D01*
+X004578Y010571D02*
+X004404Y010745D01*
+X004404Y010788D01*
+X004300Y010788D02*
+X004257Y010788D01*
+X004257Y010745D01*
+X004300Y010745D01*
+X004300Y010788D01*
+X004153Y010788D02*
+X004110Y010788D01*
+X004110Y010745D01*
+X004153Y010745D01*
+X004153Y010788D01*
+X003945Y010788D02*
+X003945Y010528D01*
+X003815Y010658D01*
+X003989Y010658D01*
+X004404Y010528D02*
+X004578Y010528D01*
+X004578Y010571D01*
+X003399Y010571D02*
+X003356Y010528D01*
+X003269Y010528D01*
+X003226Y010571D01*
+X003105Y010571D02*
+X003061Y010528D01*
+X002975Y010528D01*
+X002931Y010571D01*
+X002931Y010745D01*
+X002975Y010788D01*
+X003061Y010788D01*
+X003105Y010745D01*
+X003226Y010788D02*
+X003399Y010615D01*
+X003399Y010571D01*
+X003399Y010788D02*
+X003226Y010788D01*
+X000899Y010702D02*
+X000899Y010528D01*
+X000726Y010528D02*
+X000726Y010702D01*
+X000813Y010788D01*
+X000899Y010702D01*
+X000605Y010658D02*
+X000605Y010745D01*
+X000561Y010788D01*
+X000475Y010788D01*
+X000431Y010745D01*
+X000431Y010658D02*
+X000518Y010615D01*
+X000561Y010615D01*
+X000605Y010658D01*
+X000605Y010528D02*
+X000431Y010528D01*
+X000431Y010658D01*
+X014611Y001995D02*
+X014611Y001908D01*
+X014654Y001865D01*
+X014741Y001865D02*
+X014741Y001952D01*
+X014741Y001865D02*
+X014828Y001865D01*
+X014871Y001908D01*
+X014871Y001995D01*
+X014828Y002038D01*
+X014654Y002038D01*
+X014611Y001995D01*
+X014611Y001744D02*
+X014871Y001570D01*
+X014611Y001570D01*
+X014611Y001449D02*
+X014611Y001319D01*
+X014654Y001276D01*
+X014828Y001276D01*
+X014871Y001319D01*
+X014871Y001449D01*
+X014611Y001449D01*
+X014611Y001744D02*
+X014871Y001744D01*
+M02*
diff --git a/digital/cms-intro/pcb/orders/eurocircuits_2011-05-11/cms_intro.GBS b/digital/cms-intro/pcb/orders/eurocircuits_2011-05-11/cms_intro.GBS
new file mode 100644
index 00000000..4d72b614
--- /dev/null
+++ b/digital/cms-intro/pcb/orders/eurocircuits_2011-05-11/cms_intro.GBS
@@ -0,0 +1,66 @@
+G75*
+G70*
+%OFA0B0*%
+%FSLAX24Y24*%
+%IPPOS*%
+%LPD*%
+%AMOC8*
+5,1,8,0,0,1.08239X$1,22.5*
+%
+%ADD10OC8,0.0720*%
+D10*
+X000651Y011568D03*
+X001651Y011568D03*
+X002651Y011568D03*
+X003651Y011568D03*
+X004651Y011568D03*
+X005651Y011568D03*
+X006651Y011568D03*
+X007651Y011568D03*
+X008651Y011568D03*
+X009651Y011568D03*
+X010651Y011568D03*
+X011651Y011568D03*
+X012651Y011568D03*
+X013651Y011568D03*
+X014651Y011568D03*
+X015651Y011568D03*
+X016651Y011568D03*
+X016651Y010568D03*
+X015651Y010568D03*
+X015651Y009568D03*
+X016651Y009568D03*
+X016651Y008568D03*
+X015651Y008568D03*
+X015651Y007568D03*
+X016651Y007568D03*
+X016651Y006568D03*
+X015651Y006568D03*
+X015651Y005568D03*
+X016651Y005568D03*
+X016651Y004568D03*
+X015651Y004568D03*
+X015651Y003568D03*
+X016651Y003568D03*
+X016651Y002568D03*
+X015651Y002568D03*
+X015651Y001568D03*
+X016651Y001568D03*
+X016651Y012568D03*
+X015651Y012568D03*
+X014651Y012568D03*
+X013651Y012568D03*
+X012651Y012568D03*
+X011651Y012568D03*
+X010651Y012568D03*
+X009651Y012568D03*
+X008651Y012568D03*
+X007651Y012568D03*
+X006651Y012568D03*
+X005651Y012568D03*
+X004651Y012568D03*
+X003651Y012568D03*
+X002651Y012568D03*
+X001651Y012568D03*
+X000651Y012568D03*
+M02*
diff --git a/digital/cms-intro/pcb/orders/eurocircuits_2011-05-11/cms_intro.GTL b/digital/cms-intro/pcb/orders/eurocircuits_2011-05-11/cms_intro.GTL
new file mode 100644
index 00000000..2ae21b29
--- /dev/null
+++ b/digital/cms-intro/pcb/orders/eurocircuits_2011-05-11/cms_intro.GTL
@@ -0,0 +1,3546 @@
+G75*
+G70*
+%OFA0B0*%
+%FSLAX24Y24*%
+%IPPOS*%
+%LPD*%
+%AMOC8*
+5,1,8,0,0,1.08239X$1,22.5*
+%
+%ADD10C,0.0000*%
+%ADD11C,0.0060*%
+%ADD12R,0.0210X0.0500*%
+%ADD13R,0.0500X0.0210*%
+%ADD14R,0.0394X0.0433*%
+%ADD15R,0.0433X0.0394*%
+%ADD16R,0.2000X0.0700*%
+%ADD17OC8,0.0640*%
+%ADD18R,0.0138X0.0551*%
+%ADD19R,0.0709X0.0748*%
+%ADD20R,0.0827X0.0630*%
+%ADD21C,0.0100*%
+%ADD22C,0.0436*%
+%ADD23C,0.0400*%
+%ADD24C,0.0080*%
+D10*
+X000151Y001068D02*
+X000151Y013068D01*
+X017151Y013068D01*
+X017151Y001068D01*
+X000151Y001068D01*
+D11*
+X000956Y007323D02*
+X001136Y007323D01*
+X001136Y007443D02*
+X000956Y007443D01*
+X000956Y007323D02*
+X001136Y007443D01*
+X001106Y007713D02*
+X001136Y007743D01*
+X001136Y007803D01*
+X001106Y007833D01*
+X000986Y007833D01*
+X000956Y007803D01*
+X000956Y007743D01*
+X000986Y007713D01*
+X001046Y007713D01*
+X001046Y007773D01*
+X001136Y008083D02*
+X000956Y008083D01*
+X000986Y008333D02*
+X000956Y008363D01*
+X000956Y008423D01*
+X000986Y008453D01*
+X001046Y008423D02*
+X001046Y008363D01*
+X001016Y008333D01*
+X000986Y008333D01*
+X001046Y008423D02*
+X001076Y008453D01*
+X001106Y008453D01*
+X001136Y008423D01*
+X001136Y008363D01*
+X001106Y008333D01*
+X001136Y008703D02*
+X001136Y008823D01*
+X000956Y008823D01*
+X000956Y008703D01*
+X001046Y008763D02*
+X001046Y008823D01*
+X000986Y009063D02*
+X001106Y009063D01*
+X001136Y009093D01*
+X001136Y009183D01*
+X000956Y009183D01*
+X000956Y009093D01*
+X000986Y009063D01*
+X011431Y009356D02*
+X011431Y009529D01*
+X011431Y009443D02*
+X011691Y009443D01*
+X011605Y009529D01*
+X011431Y009651D02*
+X011431Y009824D01*
+X011431Y009737D02*
+X011691Y009737D01*
+X011605Y009824D01*
+X011648Y009945D02*
+X011475Y010119D01*
+X011431Y010075D01*
+X011431Y009989D01*
+X011475Y009945D01*
+X011648Y009945D01*
+X011691Y009989D01*
+X011691Y010075D01*
+X011648Y010119D01*
+X011475Y010119D01*
+X011431Y010240D02*
+X011431Y010413D01*
+X011605Y010240D01*
+X011648Y010240D01*
+X011691Y010283D01*
+X011691Y010370D01*
+X011648Y010413D01*
+X011931Y010370D02*
+X011931Y010240D01*
+X011931Y010119D02*
+X012105Y010119D01*
+X012105Y010075D01*
+X012061Y010032D01*
+X012105Y009989D01*
+X012061Y009945D01*
+X011931Y009945D01*
+X011931Y010032D02*
+X012061Y010032D01*
+X012061Y009824D02*
+X012105Y009781D01*
+X012105Y009651D01*
+X012018Y009694D02*
+X011975Y009651D01*
+X011931Y009694D01*
+X011931Y009824D01*
+X012018Y009781D02*
+X012061Y009824D01*
+X012018Y009781D02*
+X012018Y009694D01*
+X012061Y009529D02*
+X012061Y009356D01*
+X012105Y009235D02*
+X012105Y009191D01*
+X011931Y009191D01*
+X011931Y009148D02*
+X011931Y009235D01*
+X011931Y009038D02*
+X012105Y009038D01*
+X012105Y008908D01*
+X012061Y008865D01*
+X011931Y008865D01*
+X011975Y008700D02*
+X011931Y008657D01*
+X011975Y008700D02*
+X012148Y008700D01*
+X012105Y008657D02*
+X012105Y008744D01*
+X012105Y008547D02*
+X011931Y008547D01*
+X012018Y008547D02*
+X012105Y008461D01*
+X012105Y008417D01*
+X012061Y008302D02*
+X011975Y008302D01*
+X011931Y008258D01*
+X011931Y008172D01*
+X011975Y008128D01*
+X012061Y008128D01*
+X012105Y008172D01*
+X012105Y008258D01*
+X012061Y008302D01*
+X012431Y008345D02*
+X012431Y008515D01*
+X012488Y008572D01*
+X012545Y008515D01*
+X012545Y008345D01*
+X012601Y008345D02*
+X012431Y008345D01*
+X012431Y008204D02*
+X012658Y008204D01*
+X012658Y008147D01*
+X012601Y008090D01*
+X012658Y008033D01*
+X012601Y007977D01*
+X012431Y007977D01*
+X012431Y008090D02*
+X012601Y008090D01*
+X012601Y008345D02*
+X012658Y008402D01*
+X012658Y008515D01*
+X012601Y008713D02*
+X012545Y008713D01*
+X012545Y008940D01*
+X012601Y008940D02*
+X012658Y008883D01*
+X012658Y008770D01*
+X012601Y008713D01*
+X012431Y008770D02*
+X012431Y008883D01*
+X012488Y008940D01*
+X012601Y008940D01*
+X012771Y009082D02*
+X012771Y009308D01*
+X012771Y009195D02*
+X012431Y009195D01*
+X012235Y009191D02*
+X012191Y009191D01*
+X012488Y009450D02*
+X012431Y009507D01*
+X012431Y009677D01*
+X012771Y009677D01*
+X012771Y009507D01*
+X012715Y009450D01*
+X012658Y009450D01*
+X012601Y009507D01*
+X012601Y009677D01*
+X012601Y009818D02*
+X012545Y009875D01*
+X012545Y010045D01*
+X012431Y010045D02*
+X012771Y010045D01*
+X012771Y009875D01*
+X012715Y009818D01*
+X012601Y009818D01*
+X012601Y009507D02*
+X012545Y009450D01*
+X012488Y009450D01*
+X012431Y010186D02*
+X012658Y010186D01*
+X012771Y010300D01*
+X012658Y010413D01*
+X012431Y010413D01*
+X012601Y010413D02*
+X012601Y010186D01*
+X012105Y010240D02*
+X012105Y010370D01*
+X012061Y010413D01*
+X011975Y010413D01*
+X011931Y010370D01*
+D12*
+X010754Y008258D03*
+X010439Y008258D03*
+X010124Y008258D03*
+X009809Y008258D03*
+X009494Y008258D03*
+X009179Y008258D03*
+X008864Y008258D03*
+X008549Y008258D03*
+X008549Y004878D03*
+X008864Y004878D03*
+X009179Y004878D03*
+X009494Y004878D03*
+X009809Y004878D03*
+X010124Y004878D03*
+X010439Y004878D03*
+X010754Y004878D03*
+D13*
+X011341Y005466D03*
+X011341Y005781D03*
+X011341Y006096D03*
+X011341Y006411D03*
+X011341Y006726D03*
+X011341Y007041D03*
+X011341Y007356D03*
+X011341Y007671D03*
+X007961Y007671D03*
+X007961Y007356D03*
+X007961Y007041D03*
+X007961Y006726D03*
+X007961Y006411D03*
+X007961Y006096D03*
+X007961Y005781D03*
+X007961Y005466D03*
+D14*
+X006151Y002903D03*
+X006151Y002234D03*
+X013151Y002234D03*
+X013151Y002903D03*
+D15*
+X006486Y005568D03*
+X005817Y005568D03*
+X005817Y007568D03*
+X006486Y007568D03*
+X003151Y006453D03*
+X003151Y005784D03*
+X002151Y005784D03*
+X002151Y006453D03*
+D16*
+X007751Y002568D03*
+X011551Y002568D03*
+D17*
+X015651Y002568D03*
+X016651Y002568D03*
+X016651Y001568D03*
+X015651Y001568D03*
+X015651Y003568D03*
+X016651Y003568D03*
+X016651Y004568D03*
+X015651Y004568D03*
+X015651Y005568D03*
+X016651Y005568D03*
+X016651Y006568D03*
+X015651Y006568D03*
+X015651Y007568D03*
+X016651Y007568D03*
+X016651Y008568D03*
+X015651Y008568D03*
+X015651Y009568D03*
+X016651Y009568D03*
+X016651Y010568D03*
+X015651Y010568D03*
+X015651Y011568D03*
+X016651Y011568D03*
+X016651Y012568D03*
+X015651Y012568D03*
+X014651Y012568D03*
+X013651Y012568D03*
+X012651Y012568D03*
+X011651Y012568D03*
+X010651Y012568D03*
+X009651Y012568D03*
+X008651Y012568D03*
+X007651Y012568D03*
+X006651Y012568D03*
+X005651Y012568D03*
+X004651Y012568D03*
+X003651Y012568D03*
+X002651Y012568D03*
+X001651Y012568D03*
+X000651Y012568D03*
+X000651Y011568D03*
+X001651Y011568D03*
+X002651Y011568D03*
+X003651Y011568D03*
+X004651Y011568D03*
+X005651Y011568D03*
+X006651Y011568D03*
+X007651Y011568D03*
+X008651Y011568D03*
+X009651Y011568D03*
+X010651Y011568D03*
+X011651Y011568D03*
+X012651Y011568D03*
+X013651Y011568D03*
+X014651Y011568D03*
+D18*
+X003157Y002604D03*
+X002901Y002604D03*
+X002645Y002604D03*
+X002389Y002604D03*
+X002133Y002604D03*
+D19*
+X001070Y001560D03*
+X004220Y001560D03*
+D20*
+X003866Y002564D03*
+X001425Y002564D03*
+D21*
+X001695Y003029D02*
+X000949Y003029D01*
+X000861Y002941D01*
+X000301Y002941D01*
+X000301Y003039D02*
+X001685Y003039D01*
+X001695Y003029D02*
+X001654Y003070D01*
+X001601Y003199D01*
+X001601Y003338D01*
+X001654Y003467D01*
+X001751Y003563D01*
+X001751Y004485D01*
+X000301Y005936D01*
+X000301Y001218D01*
+X000566Y001218D01*
+X000566Y001997D01*
+X000654Y002084D01*
+X001301Y002084D01*
+X001301Y002099D01*
+X000949Y002099D01*
+X000861Y002187D01*
+X000861Y002941D01*
+X000861Y002842D02*
+X000301Y002842D01*
+X000301Y002744D02*
+X000861Y002744D01*
+X000861Y002645D02*
+X000301Y002645D01*
+X000301Y002546D02*
+X000861Y002546D01*
+X000861Y002448D02*
+X000301Y002448D01*
+X000301Y002349D02*
+X000861Y002349D01*
+X000861Y002251D02*
+X000301Y002251D01*
+X000301Y002152D02*
+X000896Y002152D01*
+X000623Y002054D02*
+X000301Y002054D01*
+X000301Y001955D02*
+X000566Y001955D01*
+X000566Y001857D02*
+X000301Y001857D01*
+X000301Y001758D02*
+X000566Y001758D01*
+X000566Y001660D02*
+X000301Y001660D01*
+X000301Y001561D02*
+X000566Y001561D01*
+X000566Y001463D02*
+X000301Y001463D01*
+X000301Y001364D02*
+X000566Y001364D01*
+X000566Y001265D02*
+X000301Y001265D01*
+X002133Y002604D02*
+X002133Y003086D01*
+X001951Y003268D01*
+X001951Y004568D01*
+X000451Y006068D01*
+X000451Y011218D01*
+X000651Y011418D01*
+X000651Y011568D01*
+X001151Y012068D01*
+X007151Y012068D01*
+X007651Y011568D01*
+X008151Y012068D01*
+X015951Y012068D01*
+X016151Y011868D01*
+X016151Y011068D01*
+X015651Y010568D01*
+X015251Y010304D02*
+X015456Y010098D01*
+X015846Y010098D01*
+X016121Y010374D01*
+X016121Y010755D01*
+X016234Y010868D01*
+X016351Y010985D01*
+X016351Y011204D01*
+X016456Y011098D01*
+X016601Y011098D01*
+X016601Y011518D01*
+X016701Y011518D01*
+X016701Y011098D01*
+X016846Y011098D01*
+X017001Y011254D01*
+X017001Y010883D01*
+X016846Y011038D01*
+X016701Y011038D01*
+X016701Y010619D01*
+X016601Y010619D01*
+X016601Y011038D01*
+X016456Y011038D01*
+X016181Y010763D01*
+X016181Y010618D01*
+X016601Y010618D01*
+X016601Y010518D01*
+X016701Y010518D01*
+X016701Y010098D01*
+X016846Y010098D01*
+X017001Y010254D01*
+X017001Y009883D01*
+X016846Y010038D01*
+X016701Y010038D01*
+X016701Y009619D01*
+X016601Y009619D01*
+X016601Y010038D01*
+X016456Y010038D01*
+X016181Y009763D01*
+X016181Y009618D01*
+X016601Y009618D01*
+X016601Y009518D01*
+X016701Y009518D01*
+X016701Y009098D01*
+X016846Y009098D01*
+X017001Y009254D01*
+X017001Y008883D01*
+X016846Y009038D01*
+X016701Y009038D01*
+X016701Y008619D01*
+X016601Y008619D01*
+X016601Y009038D01*
+X016456Y009038D01*
+X016181Y008763D01*
+X016181Y008618D01*
+X016601Y008618D01*
+X016601Y008518D01*
+X016701Y008518D01*
+X016701Y008098D01*
+X016846Y008098D01*
+X017001Y008254D01*
+X017001Y007883D01*
+X016846Y008038D01*
+X016701Y008038D01*
+X016701Y007619D01*
+X016601Y007619D01*
+X016601Y008038D01*
+X016456Y008038D01*
+X016181Y007763D01*
+X016181Y007618D01*
+X016601Y007618D01*
+X016601Y007518D01*
+X016701Y007518D01*
+X016701Y007098D01*
+X016846Y007098D01*
+X017001Y007254D01*
+X017001Y006883D01*
+X016846Y007038D01*
+X016701Y007038D01*
+X016701Y006619D01*
+X016601Y006619D01*
+X016601Y007038D01*
+X016456Y007038D01*
+X016181Y006763D01*
+X016181Y006618D01*
+X016601Y006618D01*
+X016601Y006518D01*
+X016701Y006518D01*
+X016701Y006098D01*
+X016846Y006098D01*
+X017001Y006254D01*
+X017001Y005883D01*
+X016846Y006038D01*
+X016701Y006038D01*
+X016701Y005619D01*
+X016601Y005619D01*
+X016601Y006038D01*
+X016456Y006038D01*
+X016181Y005763D01*
+X016181Y005618D01*
+X016601Y005618D01*
+X016601Y005518D01*
+X016701Y005518D01*
+X016701Y005098D01*
+X016846Y005098D01*
+X017001Y005254D01*
+X017001Y004883D01*
+X016846Y005038D01*
+X016701Y005038D01*
+X016701Y004619D01*
+X016601Y004619D01*
+X016601Y005038D01*
+X016456Y005038D01*
+X016181Y004763D01*
+X016181Y004618D01*
+X016601Y004618D01*
+X016601Y004518D01*
+X016701Y004518D01*
+X016701Y004098D01*
+X016846Y004098D01*
+X017001Y004254D01*
+X017001Y003883D01*
+X016846Y004038D01*
+X016701Y004038D01*
+X016701Y003619D01*
+X016601Y003619D01*
+X016601Y004038D01*
+X016456Y004038D01*
+X016181Y003763D01*
+X016181Y003618D01*
+X016601Y003618D01*
+X016601Y003518D01*
+X016701Y003518D01*
+X016701Y003098D01*
+X016846Y003098D01*
+X017001Y003254D01*
+X017001Y002883D01*
+X016846Y003038D01*
+X016701Y003038D01*
+X016701Y002619D01*
+X016601Y002619D01*
+X016601Y003038D01*
+X016456Y003038D01*
+X016181Y002763D01*
+X016181Y002618D01*
+X016601Y002618D01*
+X016601Y002518D01*
+X016701Y002518D01*
+X016701Y002098D01*
+X016846Y002098D01*
+X017001Y002254D01*
+X017001Y001883D01*
+X016846Y002038D01*
+X016701Y002038D01*
+X016701Y001619D01*
+X016601Y001619D01*
+X016601Y002038D01*
+X016456Y002038D01*
+X016181Y001763D01*
+X016181Y001618D01*
+X016601Y001618D01*
+X016601Y001518D01*
+X016181Y001518D01*
+X016181Y001374D01*
+X016337Y001218D01*
+X015966Y001218D01*
+X016121Y001374D01*
+X016121Y001518D01*
+X015701Y001518D01*
+X015701Y001618D01*
+X016121Y001618D01*
+X016121Y001763D01*
+X015846Y002038D01*
+X015701Y002038D01*
+X015701Y001619D01*
+X015601Y001619D01*
+X015601Y002038D01*
+X015456Y002038D01*
+X015181Y001763D01*
+X015181Y001618D01*
+X015601Y001618D01*
+X015601Y001518D01*
+X015181Y001518D01*
+X015181Y001374D01*
+X015337Y001218D01*
+X004724Y001218D01*
+X004724Y001997D01*
+X004637Y002084D01*
+X004001Y002084D01*
+X004001Y002099D01*
+X004341Y002099D01*
+X004429Y002187D01*
+X004429Y002941D01*
+X006102Y002941D01*
+X006102Y002951D02*
+X006102Y002854D01*
+X005804Y002854D01*
+X005804Y002667D01*
+X005815Y002629D01*
+X005834Y002594D01*
+X005860Y002568D01*
+X005804Y002512D01*
+X005804Y001955D01*
+X005892Y001867D01*
+X006410Y001867D01*
+X006498Y001955D01*
+X006498Y002298D01*
+X006569Y002368D01*
+X006601Y002368D01*
+X006601Y002156D01*
+X006689Y002068D01*
+X008813Y002068D01*
+X008901Y002156D01*
+X008901Y002936D01*
+X009351Y002485D01*
+X009468Y002368D01*
+X010401Y002368D01*
+X010401Y002156D01*
+X010489Y002068D01*
+X012613Y002068D01*
+X012701Y002156D01*
+X012701Y002368D01*
+X012734Y002368D01*
+X012804Y002298D01*
+X012804Y001955D01*
+X012892Y001867D01*
+X013410Y001867D01*
+X013498Y001955D01*
+X013498Y002512D01*
+X013442Y002568D01*
+X013468Y002594D01*
+X013488Y002629D01*
+X013498Y002667D01*
+X013498Y002854D01*
+X013200Y002854D01*
+X013200Y002951D01*
+X013498Y002951D01*
+X013498Y003139D01*
+X013488Y003177D01*
+X013468Y003212D01*
+X013440Y003240D01*
+X013406Y003259D01*
+X013368Y003269D01*
+X013200Y003269D01*
+X013200Y002952D01*
+X013103Y002952D01*
+X013103Y003269D01*
+X012935Y003269D01*
+X012896Y003259D01*
+X012862Y003240D01*
+X012834Y003212D01*
+X012815Y003177D01*
+X012804Y003139D01*
+X012804Y002951D01*
+X013102Y002951D01*
+X013102Y002854D01*
+X012804Y002854D01*
+X012804Y002768D01*
+X012734Y002768D01*
+X012701Y002768D01*
+X012701Y002980D01*
+X012613Y003068D01*
+X010489Y003068D01*
+X010401Y002980D01*
+X010401Y002768D01*
+X009634Y002768D01*
+X009064Y003339D01*
+X009064Y004478D01*
+X009176Y004478D01*
+X009176Y004876D01*
+X009181Y004876D01*
+X009181Y004478D01*
+X009303Y004478D01*
+X009322Y004483D01*
+X009327Y004478D01*
+X009641Y004478D01*
+X009924Y004478D01*
+X009924Y004313D01*
+X010251Y003985D01*
+X010368Y003868D01*
+X011018Y003868D01*
+X011184Y003868D01*
+X011634Y004318D01*
+X014268Y004318D01*
+X014901Y003685D01*
+X014901Y003201D01*
+X014901Y003035D01*
+X015181Y002755D01*
+X015181Y002374D01*
+X015456Y002098D01*
+X015846Y002098D01*
+X016121Y002374D01*
+X016121Y002763D01*
+X015846Y003038D01*
+X015464Y003038D01*
+X015301Y003201D01*
+X015301Y003254D01*
+X015456Y003098D01*
+X015846Y003098D01*
+X016121Y003374D01*
+X016121Y003763D01*
+X015846Y004038D01*
+X015664Y004038D01*
+X015604Y004098D01*
+X015846Y004098D01*
+X016121Y004374D01*
+X016121Y004763D01*
+X015846Y005038D01*
+X015456Y005038D01*
+X015360Y004942D01*
+X015036Y005266D01*
+X015289Y005266D01*
+X015456Y005098D01*
+X015846Y005098D01*
+X016121Y005374D01*
+X016121Y005763D01*
+X015846Y006038D01*
+X015456Y006038D01*
+X015181Y005763D01*
+X015181Y005666D01*
+X015032Y005666D01*
+X015464Y006098D01*
+X015846Y006098D01*
+X016121Y006374D01*
+X016121Y006763D01*
+X015846Y007038D01*
+X015456Y007038D01*
+X015301Y006883D01*
+X015301Y006935D01*
+X015464Y007098D01*
+X015846Y007098D01*
+X016121Y007374D01*
+X016121Y007763D01*
+X015846Y008038D01*
+X015456Y008038D01*
+X015181Y007763D01*
+X015181Y007381D01*
+X015001Y007201D01*
+X015001Y007635D01*
+X015464Y008098D01*
+X015846Y008098D01*
+X016121Y008374D01*
+X016121Y008763D01*
+X015846Y009038D01*
+X015456Y009038D01*
+X015181Y008763D01*
+X015181Y008381D01*
+X014701Y007901D01*
+X014701Y008335D01*
+X015464Y009098D01*
+X015846Y009098D01*
+X016121Y009374D01*
+X016121Y009763D01*
+X015846Y010038D01*
+X015456Y010038D01*
+X015181Y009763D01*
+X015181Y009381D01*
+X014401Y008601D01*
+X014401Y009135D01*
+X015134Y009868D01*
+X015251Y009985D01*
+X015251Y010304D01*
+X015251Y010233D02*
+X015322Y010233D01*
+X015251Y010134D02*
+X015421Y010134D01*
+X015454Y010036D02*
+X015251Y010036D01*
+X015203Y009937D02*
+X015355Y009937D01*
+X015257Y009839D02*
+X015104Y009839D01*
+X015181Y009740D02*
+X015006Y009740D01*
+X014907Y009642D02*
+X015181Y009642D01*
+X015181Y009543D02*
+X014809Y009543D01*
+X014710Y009445D02*
+X015181Y009445D01*
+X015146Y009346D02*
+X014612Y009346D01*
+X014513Y009247D02*
+X015047Y009247D01*
+X014949Y009149D02*
+X014415Y009149D01*
+X014401Y009050D02*
+X014850Y009050D01*
+X014752Y008952D02*
+X014401Y008952D01*
+X014401Y008853D02*
+X014653Y008853D01*
+X014555Y008755D02*
+X014401Y008755D01*
+X014401Y008656D02*
+X014456Y008656D01*
+X014501Y008418D02*
+X015651Y009568D01*
+X015947Y009937D02*
+X016355Y009937D01*
+X016257Y009839D02*
+X016045Y009839D01*
+X016121Y009740D02*
+X016181Y009740D01*
+X016181Y009642D02*
+X016121Y009642D01*
+X016121Y009543D02*
+X016601Y009543D01*
+X016601Y009518D02*
+X016181Y009518D01*
+X016181Y009374D01*
+X016456Y009098D01*
+X016601Y009098D01*
+X016601Y009518D01*
+X016601Y009445D02*
+X016701Y009445D01*
+X016701Y009346D02*
+X016601Y009346D01*
+X016601Y009247D02*
+X016701Y009247D01*
+X016701Y009149D02*
+X016601Y009149D01*
+X016406Y009149D02*
+X015896Y009149D01*
+X015995Y009247D02*
+X016307Y009247D01*
+X016209Y009346D02*
+X016093Y009346D01*
+X016121Y009445D02*
+X016181Y009445D01*
+X016601Y009642D02*
+X016701Y009642D01*
+X016701Y009740D02*
+X016601Y009740D01*
+X016601Y009839D02*
+X016701Y009839D01*
+X016701Y009937D02*
+X016601Y009937D01*
+X016601Y010036D02*
+X016701Y010036D01*
+X016701Y010134D02*
+X016601Y010134D01*
+X016601Y010098D02*
+X016456Y010098D01*
+X016181Y010374D01*
+X016181Y010518D01*
+X016601Y010518D01*
+X016601Y010098D01*
+X016601Y010233D02*
+X016701Y010233D01*
+X016701Y010331D02*
+X016601Y010331D01*
+X016601Y010430D02*
+X016701Y010430D01*
+X016601Y010529D02*
+X016121Y010529D01*
+X016121Y010627D02*
+X016181Y010627D01*
+X016181Y010726D02*
+X016121Y010726D01*
+X016190Y010824D02*
+X016242Y010824D01*
+X016288Y010923D02*
+X016341Y010923D01*
+X016351Y011021D02*
+X016439Y011021D01*
+X016435Y011120D02*
+X016351Y011120D01*
+X016601Y011120D02*
+X016701Y011120D01*
+X016701Y011218D02*
+X016601Y011218D01*
+X016601Y011317D02*
+X016701Y011317D01*
+X016701Y011415D02*
+X016601Y011415D01*
+X016601Y011514D02*
+X016701Y011514D01*
+X016701Y011619D02*
+X016601Y011619D01*
+X016601Y012038D01*
+X016456Y012038D01*
+X016351Y011933D01*
+X016351Y011951D01*
+X016151Y012151D01*
+X016034Y012268D01*
+X016016Y012268D01*
+X016121Y012374D01*
+X016121Y012518D01*
+X015701Y012518D01*
+X015701Y012618D01*
+X016121Y012618D01*
+X016121Y012763D01*
+X015966Y012918D01*
+X016337Y012918D01*
+X016181Y012763D01*
+X016181Y012618D01*
+X016601Y012618D01*
+X016601Y012518D01*
+X016701Y012518D01*
+X016701Y012098D01*
+X016846Y012098D01*
+X017001Y012254D01*
+X017001Y011883D01*
+X016846Y012038D01*
+X016701Y012038D01*
+X016701Y011619D01*
+X016701Y011711D02*
+X016601Y011711D01*
+X016601Y011810D02*
+X016701Y011810D01*
+X016701Y011908D02*
+X016601Y011908D01*
+X016601Y012007D02*
+X016701Y012007D01*
+X016701Y012105D02*
+X016601Y012105D01*
+X016601Y012098D02*
+X016601Y012518D01*
+X016181Y012518D01*
+X016181Y012374D01*
+X016456Y012098D01*
+X016601Y012098D01*
+X016601Y012204D02*
+X016701Y012204D01*
+X016701Y012302D02*
+X016601Y012302D01*
+X016601Y012401D02*
+X016701Y012401D01*
+X016701Y012499D02*
+X016601Y012499D01*
+X016601Y012598D02*
+X015701Y012598D01*
+X015601Y012598D02*
+X014701Y012598D01*
+X014701Y012618D02*
+X015121Y012618D01*
+X015121Y012763D01*
+X014966Y012918D01*
+X015337Y012918D01*
+X015181Y012763D01*
+X015181Y012618D01*
+X015601Y012618D01*
+X015601Y012518D01*
+X015181Y012518D01*
+X015181Y012374D01*
+X015287Y012268D01*
+X015016Y012268D01*
+X015121Y012374D01*
+X015121Y012518D01*
+X014701Y012518D01*
+X014701Y012618D01*
+X014601Y012618D02*
+X014601Y012518D01*
+X014181Y012518D01*
+X014181Y012374D01*
+X014287Y012268D01*
+X014016Y012268D01*
+X014121Y012374D01*
+X014121Y012518D01*
+X013701Y012518D01*
+X013701Y012618D01*
+X014121Y012618D01*
+X014121Y012763D01*
+X013966Y012918D01*
+X014337Y012918D01*
+X014181Y012763D01*
+X014181Y012618D01*
+X014601Y012618D01*
+X014601Y012598D02*
+X013701Y012598D01*
+X013601Y012598D02*
+X012701Y012598D01*
+X012701Y012618D02*
+X013121Y012618D01*
+X013121Y012763D01*
+X012966Y012918D01*
+X013337Y012918D01*
+X013181Y012763D01*
+X013181Y012618D01*
+X013601Y012618D01*
+X013601Y012518D01*
+X013181Y012518D01*
+X013181Y012374D01*
+X013287Y012268D01*
+X013016Y012268D01*
+X013121Y012374D01*
+X013121Y012518D01*
+X012701Y012518D01*
+X012701Y012618D01*
+X012601Y012618D02*
+X012601Y012518D01*
+X012181Y012518D01*
+X012181Y012374D01*
+X012287Y012268D01*
+X012016Y012268D01*
+X012121Y012374D01*
+X012121Y012518D01*
+X011701Y012518D01*
+X011701Y012618D01*
+X012121Y012618D01*
+X012121Y012763D01*
+X011966Y012918D01*
+X012337Y012918D01*
+X012181Y012763D01*
+X012181Y012618D01*
+X012601Y012618D01*
+X012601Y012598D02*
+X011701Y012598D01*
+X011601Y012598D02*
+X010701Y012598D01*
+X010701Y012618D02*
+X011121Y012618D01*
+X011121Y012763D01*
+X010966Y012918D01*
+X011337Y012918D01*
+X011181Y012763D01*
+X011181Y012618D01*
+X011601Y012618D01*
+X011601Y012518D01*
+X011181Y012518D01*
+X011181Y012374D01*
+X011287Y012268D01*
+X011016Y012268D01*
+X011121Y012374D01*
+X011121Y012518D01*
+X010701Y012518D01*
+X010701Y012618D01*
+X010601Y012618D02*
+X010601Y012518D01*
+X010181Y012518D01*
+X010181Y012374D01*
+X010287Y012268D01*
+X010016Y012268D01*
+X010121Y012374D01*
+X010121Y012518D01*
+X009701Y012518D01*
+X009701Y012618D01*
+X010121Y012618D01*
+X010121Y012763D01*
+X009966Y012918D01*
+X010337Y012918D01*
+X010181Y012763D01*
+X010181Y012618D01*
+X010601Y012618D01*
+X010601Y012598D02*
+X009701Y012598D01*
+X009601Y012598D02*
+X008701Y012598D01*
+X008701Y012618D02*
+X009121Y012618D01*
+X009121Y012763D01*
+X008966Y012918D01*
+X009337Y012918D01*
+X009181Y012763D01*
+X009181Y012618D01*
+X009601Y012618D01*
+X009601Y012518D01*
+X009181Y012518D01*
+X009181Y012374D01*
+X009287Y012268D01*
+X009016Y012268D01*
+X009121Y012374D01*
+X009121Y012518D01*
+X008701Y012518D01*
+X008701Y012618D01*
+X008601Y012618D02*
+X008601Y012518D01*
+X008181Y012518D01*
+X008181Y012374D01*
+X008287Y012268D01*
+X008234Y012268D01*
+X008068Y012268D01*
+X007838Y012038D01*
+X007464Y012038D01*
+X007351Y012151D01*
+X007234Y012268D01*
+X007016Y012268D01*
+X007121Y012374D01*
+X007121Y012518D01*
+X006701Y012518D01*
+X006701Y012618D01*
+X007121Y012618D01*
+X007121Y012763D01*
+X006966Y012918D01*
+X007337Y012918D01*
+X007181Y012763D01*
+X007181Y012618D01*
+X007601Y012618D01*
+X007601Y012518D01*
+X007701Y012518D01*
+X007701Y012098D01*
+X007846Y012098D01*
+X008121Y012374D01*
+X008121Y012518D01*
+X007701Y012518D01*
+X007701Y012618D01*
+X008121Y012618D01*
+X008121Y012763D01*
+X007966Y012918D01*
+X008337Y012918D01*
+X008181Y012763D01*
+X008181Y012618D01*
+X008601Y012618D01*
+X008601Y012598D02*
+X007701Y012598D01*
+X007701Y012499D02*
+X007601Y012499D01*
+X007601Y012518D02*
+X007601Y012098D01*
+X007456Y012098D01*
+X007181Y012374D01*
+X007181Y012518D01*
+X007601Y012518D01*
+X007601Y012598D02*
+X006701Y012598D01*
+X006601Y012598D02*
+X005701Y012598D01*
+X005701Y012618D02*
+X006121Y012618D01*
+X006121Y012763D01*
+X005966Y012918D01*
+X006337Y012918D01*
+X006181Y012763D01*
+X006181Y012618D01*
+X006601Y012618D01*
+X006601Y012518D01*
+X006181Y012518D01*
+X006181Y012374D01*
+X006287Y012268D01*
+X006016Y012268D01*
+X006121Y012374D01*
+X006121Y012518D01*
+X005701Y012518D01*
+X005701Y012618D01*
+X005601Y012618D02*
+X005601Y012518D01*
+X005181Y012518D01*
+X005181Y012374D01*
+X005287Y012268D01*
+X005016Y012268D01*
+X005121Y012374D01*
+X005121Y012518D01*
+X004701Y012518D01*
+X004701Y012618D01*
+X005121Y012618D01*
+X005121Y012763D01*
+X004966Y012918D01*
+X005337Y012918D01*
+X005181Y012763D01*
+X005181Y012618D01*
+X005601Y012618D01*
+X005601Y012598D02*
+X004701Y012598D01*
+X004601Y012598D02*
+X003701Y012598D01*
+X003701Y012618D02*
+X004121Y012618D01*
+X004121Y012763D01*
+X003966Y012918D01*
+X004337Y012918D01*
+X004181Y012763D01*
+X004181Y012618D01*
+X004601Y012618D01*
+X004601Y012518D01*
+X004181Y012518D01*
+X004181Y012374D01*
+X004287Y012268D01*
+X004016Y012268D01*
+X004121Y012374D01*
+X004121Y012518D01*
+X003701Y012518D01*
+X003701Y012618D01*
+X003601Y012618D02*
+X003601Y012518D01*
+X003181Y012518D01*
+X003181Y012374D01*
+X003287Y012268D01*
+X003016Y012268D01*
+X003121Y012374D01*
+X003121Y012518D01*
+X002701Y012518D01*
+X002701Y012618D01*
+X003121Y012618D01*
+X003121Y012763D01*
+X002966Y012918D01*
+X003337Y012918D01*
+X003181Y012763D01*
+X003181Y012618D01*
+X003601Y012618D01*
+X003601Y012598D02*
+X002701Y012598D01*
+X002601Y012598D02*
+X001701Y012598D01*
+X001701Y012618D02*
+X002121Y012618D01*
+X002121Y012763D01*
+X001966Y012918D01*
+X002337Y012918D01*
+X002181Y012763D01*
+X002181Y012618D01*
+X002601Y012618D01*
+X002601Y012518D01*
+X002181Y012518D01*
+X002181Y012374D01*
+X002287Y012268D01*
+X002016Y012268D01*
+X002121Y012374D01*
+X002121Y012518D01*
+X001701Y012518D01*
+X001701Y012618D01*
+X001601Y012618D02*
+X001601Y012518D01*
+X001181Y012518D01*
+X001181Y012374D01*
+X001287Y012268D01*
+X001068Y012268D01*
+X000951Y012151D01*
+X000838Y012038D01*
+X000456Y012038D01*
+X000301Y011883D01*
+X000301Y012254D01*
+X000456Y012098D01*
+X000601Y012098D01*
+X000601Y012518D01*
+X000701Y012518D01*
+X000701Y012098D01*
+X000846Y012098D01*
+X001121Y012374D01*
+X001121Y012518D01*
+X000701Y012518D01*
+X000701Y012618D01*
+X001121Y012618D01*
+X001121Y012763D01*
+X000966Y012918D01*
+X001337Y012918D01*
+X001181Y012763D01*
+X001181Y012618D01*
+X001601Y012618D01*
+X001601Y012598D02*
+X000701Y012598D01*
+X000701Y012499D02*
+X000601Y012499D01*
+X000601Y012401D02*
+X000701Y012401D01*
+X000701Y012302D02*
+X000601Y012302D01*
+X000601Y012204D02*
+X000701Y012204D01*
+X000701Y012105D02*
+X000601Y012105D01*
+X000450Y012105D02*
+X000301Y012105D01*
+X000301Y012007D02*
+X000425Y012007D01*
+X000326Y011908D02*
+X000301Y011908D01*
+X000301Y012204D02*
+X000351Y012204D01*
+X000853Y012105D02*
+X000905Y012105D01*
+X000951Y012151D02*
+X000951Y012151D01*
+X000951Y012204D02*
+X001004Y012204D01*
+X001050Y012302D02*
+X001253Y012302D01*
+X001181Y012401D02*
+X001121Y012401D01*
+X001121Y012499D02*
+X001181Y012499D01*
+X001181Y012696D02*
+X001121Y012696D01*
+X001089Y012795D02*
+X001213Y012795D01*
+X001312Y012894D02*
+X000991Y012894D01*
+X001991Y012894D02*
+X002312Y012894D01*
+X002213Y012795D02*
+X002089Y012795D01*
+X002121Y012696D02*
+X002181Y012696D01*
+X002181Y012499D02*
+X002121Y012499D01*
+X002121Y012401D02*
+X002181Y012401D01*
+X002253Y012302D02*
+X002050Y012302D01*
+X001287Y011868D02*
+X001181Y011763D01*
+X001181Y011374D01*
+X001456Y011098D01*
+X001838Y011098D01*
+X002551Y010385D01*
+X002668Y010268D01*
+X004468Y010268D01*
+X004951Y009785D01*
+X005068Y009668D01*
+X006433Y009668D01*
+X006433Y009645D01*
+X006489Y009510D01*
+X006593Y009406D01*
+X006728Y009350D01*
+X006874Y009350D01*
+X007010Y009406D01*
+X007101Y009498D01*
+X007101Y007751D01*
+X007084Y007768D01*
+X006918Y007768D01*
+X006852Y007768D01*
+X006852Y007827D01*
+X006764Y007915D01*
+X006207Y007915D01*
+X006151Y007859D01*
+X006125Y007885D01*
+X006091Y007905D01*
+X006053Y007915D01*
+X005865Y007915D01*
+X005865Y007617D01*
+X005768Y007617D01*
+X005768Y007915D01*
+X005580Y007915D01*
+X005542Y007905D01*
+X005508Y007885D01*
+X005480Y007857D01*
+X005460Y007823D01*
+X005450Y007785D01*
+X005450Y007617D01*
+X005768Y007617D01*
+X005768Y007520D01*
+X005450Y007520D01*
+X005450Y007352D01*
+X005460Y007314D01*
+X005480Y007279D01*
+X005508Y007251D01*
+X005542Y007232D01*
+X005580Y007221D01*
+X005768Y007221D01*
+X005768Y007520D01*
+X005865Y007520D01*
+X005865Y007221D01*
+X006053Y007221D01*
+X006091Y007232D01*
+X006125Y007251D01*
+X006151Y007277D01*
+X006207Y007221D01*
+X006764Y007221D01*
+X006852Y007309D01*
+X006852Y007368D01*
+X006918Y007368D01*
+X007446Y006841D01*
+X007561Y006841D01*
+X007561Y006728D01*
+X007958Y006728D01*
+X007958Y006723D01*
+X007561Y006723D01*
+X007561Y006618D01*
+X003518Y006618D01*
+X003518Y006712D01*
+X003430Y006800D01*
+X002872Y006800D01*
+X002785Y006712D01*
+X002785Y006318D01*
+X002584Y006318D01*
+X002518Y006385D01*
+X002518Y006712D01*
+X002430Y006800D01*
+X001872Y006800D01*
+X001785Y006712D01*
+X001785Y006194D01*
+X001860Y006118D01*
+X001785Y006043D01*
+X001785Y005525D01*
+X001872Y005437D01*
+X002189Y005437D01*
+X002189Y003525D01*
+X002151Y003563D01*
+X002151Y004485D01*
+X002151Y004651D01*
+X000651Y006151D01*
+X000651Y011098D01*
+X000846Y011098D01*
+X001121Y011374D01*
+X001121Y011756D01*
+X001234Y011868D01*
+X001287Y011868D01*
+X001228Y011810D02*
+X001175Y011810D01*
+X001181Y011711D02*
+X001121Y011711D01*
+X001121Y011612D02*
+X001181Y011612D01*
+X001181Y011514D02*
+X001121Y011514D01*
+X001121Y011415D02*
+X001181Y011415D01*
+X001238Y011317D02*
+X001064Y011317D01*
+X000966Y011218D02*
+X001337Y011218D01*
+X001435Y011120D02*
+X000867Y011120D01*
+X000651Y011021D02*
+X001915Y011021D01*
+X002014Y010923D02*
+X000651Y010923D01*
+X000651Y010824D02*
+X002113Y010824D01*
+X002211Y010726D02*
+X000651Y010726D01*
+X000651Y010627D02*
+X001211Y010627D01*
+X001217Y010633D02*
+X001106Y010522D01*
+X001106Y009363D01*
+X001062Y009363D01*
+X001031Y009363D01*
+X000882Y009363D01*
+X000776Y009258D01*
+X000776Y009094D01*
+X000776Y009019D01*
+X000776Y009019D01*
+X000776Y009019D01*
+X000806Y008989D01*
+X000806Y008989D01*
+X000837Y008958D01*
+X000776Y008898D01*
+X000776Y008629D01*
+X000842Y008563D01*
+X000776Y008498D01*
+X000776Y008362D01*
+X000776Y008289D01*
+X000776Y008289D01*
+X000776Y008289D01*
+X000806Y008259D01*
+X000806Y008259D01*
+X000842Y008223D01*
+X000776Y008158D01*
+X000776Y008009D01*
+X000842Y007943D01*
+X000776Y007878D01*
+X000776Y007744D01*
+X000776Y007669D01*
+X000776Y007669D01*
+X000776Y007669D01*
+X000806Y007639D01*
+X000806Y007639D01*
+X000852Y007593D01*
+X000776Y007518D01*
+X000776Y007398D01*
+X000776Y007341D01*
+X000765Y007285D01*
+X000776Y007269D01*
+X000776Y007249D01*
+X000816Y007209D01*
+X000848Y007161D01*
+X000867Y007157D01*
+X000882Y007143D01*
+X000938Y007143D01*
+X000994Y007132D01*
+X001011Y007143D01*
+X001188Y007143D01*
+X001217Y007113D01*
+X001375Y007113D01*
+X001421Y007160D01*
+X001427Y007153D01*
+X001437Y007153D01*
+X001438Y007153D01*
+X001487Y007103D01*
+X001497Y007103D01*
+X001505Y007097D01*
+X001575Y007103D01*
+X001587Y007103D01*
+X001646Y007092D01*
+X001664Y007103D01*
+X001685Y007103D01*
+X001727Y007146D01*
+X001755Y007164D01*
+X001789Y007178D01*
+X001886Y007138D01*
+X002031Y007198D01*
+X002093Y007345D01*
+X002116Y007364D01*
+X002122Y007415D01*
+X002142Y007463D01*
+X002136Y007477D01*
+X002136Y007512D01*
+X002152Y007546D01*
+X002140Y007578D01*
+X002142Y007596D01*
+X002151Y007613D01*
+X002136Y007661D01*
+X002136Y007712D01*
+X002114Y007734D01*
+X002114Y007736D01*
+X002120Y007759D01*
+X002092Y007809D01*
+X002080Y007848D01*
+X002092Y007856D01*
+X002116Y008012D01*
+X001954Y008234D01*
+X002043Y008332D01*
+X002096Y008385D01*
+X002096Y008389D01*
+X002099Y008393D01*
+X002096Y008467D01*
+X002096Y008514D01*
+X002102Y008521D01*
+X002096Y008591D01*
+X002096Y008662D01*
+X002090Y008668D01*
+X002089Y008678D01*
+X002060Y008702D01*
+X002083Y008755D01*
+X002106Y008774D01*
+X002112Y008825D01*
+X002113Y008828D01*
+X002173Y007760D01*
+X002163Y007742D01*
+X002171Y007710D01*
+X002162Y007679D01*
+X002179Y007649D01*
+X002181Y007614D01*
+X002200Y007597D01*
+X002202Y007590D01*
+X002217Y007581D01*
+X002239Y007541D01*
+X002273Y007532D01*
+X002298Y007509D01*
+X002335Y007511D01*
+X002337Y007510D01*
+X002345Y007512D01*
+X002345Y007512D01*
+X002391Y007499D01*
+X002421Y007516D01*
+X002455Y007518D01*
+X002481Y007547D01*
+X002490Y007549D01*
+X002495Y007558D01*
+X003127Y007914D01*
+X003137Y007903D01*
+X003155Y007903D01*
+X003170Y007893D01*
+X003211Y007900D01*
+X003252Y007891D01*
+X003272Y007903D01*
+X003295Y007903D01*
+X003307Y007916D01*
+X003325Y007919D01*
+X003349Y007953D01*
+X004492Y008684D01*
+X004516Y008684D01*
+X004533Y008701D01*
+X004557Y008707D01*
+X004575Y008737D01*
+X004605Y008756D01*
+X004610Y008779D01*
+X004627Y008796D01*
+X004627Y008820D01*
+X004639Y008841D01*
+X004631Y008875D01*
+X004639Y008909D01*
+X004626Y008930D01*
+X004625Y008954D01*
+X004608Y008971D01*
+X004603Y008994D01*
+X004573Y009012D01*
+X004554Y009042D01*
+X004530Y009047D01*
+X004513Y009064D01*
+X004489Y009064D01*
+X003888Y009432D01*
+X003890Y009440D01*
+X003876Y009464D01*
+X003876Y009492D01*
+X003855Y009513D01*
+X003846Y009542D01*
+X003824Y009554D01*
+X003811Y009576D01*
+X003785Y009584D01*
+X003765Y009603D01*
+X003735Y009603D01*
+X002526Y010264D01*
+X002515Y010284D01*
+X002488Y010291D01*
+X002469Y010312D01*
+X002437Y010312D01*
+X002408Y010328D01*
+X002386Y010321D01*
+X002364Y010328D01*
+X002339Y010314D01*
+X002312Y010315D01*
+X002288Y010293D01*
+X002257Y010283D01*
+X002246Y010263D01*
+X002226Y010252D01*
+X002218Y010225D01*
+X002198Y010206D01*
+X002197Y010174D01*
+X002182Y010145D01*
+X002188Y010123D01*
+X002182Y010101D01*
+X002195Y010076D01*
+X002178Y009301D01*
+X002159Y009295D01*
+X002140Y009261D01*
+X002109Y009238D01*
+X002106Y009217D01*
+X002092Y009201D01*
+X002082Y009219D01*
+X002066Y009273D01*
+X002056Y009278D01*
+X002056Y009292D01*
+X002018Y009330D01*
+X001992Y009376D01*
+X001965Y009383D01*
+X001945Y009403D01*
+X001892Y009403D01*
+X001840Y009417D01*
+X001825Y009409D01*
+X001816Y009415D01*
+X001757Y009403D01*
+X001697Y009403D01*
+X001682Y009388D01*
+X001662Y009384D01*
+X001656Y009376D01*
+X001656Y009513D01*
+X002005Y009513D01*
+X002116Y009625D01*
+X002116Y009675D01*
+X002116Y009832D01*
+X002116Y009882D01*
+X002100Y009898D01*
+X002116Y009915D01*
+X002116Y010265D01*
+X002116Y010325D01*
+X002116Y010482D01*
+X002116Y010532D01*
+X002005Y010643D01*
+X001795Y010643D01*
+X001637Y010643D01*
+X001545Y010643D01*
+X001387Y010643D01*
+X001376Y010632D01*
+X001375Y010633D01*
+X001217Y010633D01*
+X001113Y010529D02*
+X000651Y010529D01*
+X000651Y010430D02*
+X001106Y010430D01*
+X001106Y010331D02*
+X000651Y010331D01*
+X000651Y010233D02*
+X001106Y010233D01*
+X001106Y010134D02*
+X000651Y010134D01*
+X000651Y010036D02*
+X001106Y010036D01*
+X001106Y009937D02*
+X000651Y009937D01*
+X000651Y009839D02*
+X001106Y009839D01*
+X001106Y009740D02*
+X000651Y009740D01*
+X000651Y009642D02*
+X001106Y009642D01*
+X001106Y009543D02*
+X000651Y009543D01*
+X000651Y009445D02*
+X001106Y009445D01*
+X000864Y009346D02*
+X000651Y009346D01*
+X000651Y009247D02*
+X000776Y009247D01*
+X000776Y009149D02*
+X000651Y009149D01*
+X000651Y009050D02*
+X000776Y009050D01*
+X000830Y008952D02*
+X000651Y008952D01*
+X000651Y008853D02*
+X000776Y008853D01*
+X000776Y008755D02*
+X000651Y008755D01*
+X000651Y008656D02*
+X000776Y008656D01*
+X000836Y008558D02*
+X000651Y008558D01*
+X000651Y008459D02*
+X000776Y008459D01*
+X000776Y008361D02*
+X000651Y008361D01*
+X000651Y008262D02*
+X000803Y008262D01*
+X000782Y008163D02*
+X000651Y008163D01*
+X000651Y008065D02*
+X000776Y008065D01*
+X000819Y007966D02*
+X000651Y007966D01*
+X000651Y007868D02*
+X000776Y007868D01*
+X000776Y007769D02*
+X000651Y007769D01*
+X000651Y007671D02*
+X000776Y007671D01*
+X000831Y007572D02*
+X000651Y007572D01*
+X000651Y007474D02*
+X000776Y007474D01*
+X000776Y007375D02*
+X000651Y007375D01*
+X000651Y007277D02*
+X000771Y007277D01*
+X000837Y007178D02*
+X000651Y007178D01*
+X000651Y007079D02*
+X007207Y007079D01*
+X007306Y006981D02*
+X000651Y006981D01*
+X000651Y006882D02*
+X007404Y006882D01*
+X007561Y006784D02*
+X003446Y006784D01*
+X003518Y006685D02*
+X007561Y006685D01*
+X007961Y006726D02*
+X008594Y006726D01*
+X008601Y006718D01*
+X008361Y006723D02*
+X007964Y006723D01*
+X007964Y006728D01*
+X008361Y006728D01*
+X008361Y006851D01*
+X008356Y006869D01*
+X008361Y006874D01*
+X008361Y007208D01*
+X008361Y007523D01*
+X008361Y007576D01*
+X009609Y006328D01*
+X009609Y005444D01*
+X009501Y005551D01*
+X009384Y005668D01*
+X008361Y005668D01*
+X008361Y005948D01*
+X008361Y006263D01*
+X008361Y006578D01*
+X008356Y006583D01*
+X008361Y006601D01*
+X008361Y006723D01*
+X008361Y006685D02*
+X009251Y006685D01*
+X009153Y006784D02*
+X008361Y006784D01*
+X008361Y006882D02*
+X009054Y006882D01*
+X008956Y006981D02*
+X008361Y006981D01*
+X008361Y007079D02*
+X008857Y007079D01*
+X008759Y007178D02*
+X008361Y007178D01*
+X008361Y007277D02*
+X008660Y007277D01*
+X008562Y007375D02*
+X008361Y007375D01*
+X008361Y007474D02*
+X008463Y007474D01*
+X008364Y007572D02*
+X008361Y007572D01*
+X007961Y007671D02*
+X007799Y007671D01*
+X007601Y007868D01*
+X007601Y010118D01*
+X007251Y010468D01*
+X005351Y010468D01*
+X004751Y011068D01*
+X004151Y011068D01*
+X003651Y011568D01*
+X003253Y012302D02*
+X003050Y012302D01*
+X003121Y012401D02*
+X003181Y012401D01*
+X003181Y012499D02*
+X003121Y012499D01*
+X003121Y012696D02*
+X003181Y012696D01*
+X003213Y012795D02*
+X003089Y012795D01*
+X002991Y012894D02*
+X003312Y012894D01*
+X003991Y012894D02*
+X004312Y012894D01*
+X004213Y012795D02*
+X004089Y012795D01*
+X004121Y012696D02*
+X004181Y012696D01*
+X004181Y012499D02*
+X004121Y012499D01*
+X004121Y012401D02*
+X004181Y012401D01*
+X004253Y012302D02*
+X004050Y012302D01*
+X004651Y011568D02*
+X005451Y010768D01*
+X008451Y010768D01*
+X008864Y010356D01*
+X008864Y008258D01*
+X009179Y008258D02*
+X009179Y010541D01*
+X008651Y011068D01*
+X006151Y011068D01*
+X005651Y011568D01*
+X006121Y011612D02*
+X006601Y011612D01*
+X006601Y011618D02*
+X006601Y011518D01*
+X006181Y011518D01*
+X006181Y011374D01*
+X006287Y011268D01*
+X006234Y011268D01*
+X006121Y011381D01*
+X006121Y011763D01*
+X006016Y011868D01*
+X006287Y011868D01*
+X006181Y011763D01*
+X006181Y011618D01*
+X006601Y011618D01*
+X006701Y011618D02*
+X007121Y011618D01*
+X007121Y011763D01*
+X007016Y011868D01*
+X007068Y011868D01*
+X007181Y011755D01*
+X007181Y011374D01*
+X007287Y011268D01*
+X007016Y011268D01*
+X007121Y011374D01*
+X007121Y011518D01*
+X006701Y011518D01*
+X006701Y011618D01*
+X006701Y011612D02*
+X007181Y011612D01*
+X007181Y011514D02*
+X007121Y011514D01*
+X007121Y011415D02*
+X007181Y011415D01*
+X007238Y011317D02*
+X007064Y011317D01*
+X007121Y011711D02*
+X007181Y011711D01*
+X007127Y011810D02*
+X007075Y011810D01*
+X007397Y012105D02*
+X007450Y012105D01*
+X007351Y012204D02*
+X007299Y012204D01*
+X007253Y012302D02*
+X007050Y012302D01*
+X007121Y012401D02*
+X007181Y012401D01*
+X007181Y012499D02*
+X007121Y012499D01*
+X007121Y012696D02*
+X007181Y012696D01*
+X007213Y012795D02*
+X007089Y012795D01*
+X006991Y012894D02*
+X007312Y012894D01*
+X007601Y012401D02*
+X007701Y012401D01*
+X007701Y012302D02*
+X007601Y012302D01*
+X007601Y012204D02*
+X007701Y012204D01*
+X007701Y012105D02*
+X007601Y012105D01*
+X007853Y012105D02*
+X007905Y012105D01*
+X007951Y012204D02*
+X008004Y012204D01*
+X008050Y012302D02*
+X008253Y012302D01*
+X008181Y012401D02*
+X008121Y012401D01*
+X008121Y012499D02*
+X008181Y012499D01*
+X008181Y012696D02*
+X008121Y012696D01*
+X008089Y012795D02*
+X008213Y012795D01*
+X008312Y012894D02*
+X007991Y012894D01*
+X008991Y012894D02*
+X009312Y012894D01*
+X009213Y012795D02*
+X009089Y012795D01*
+X009121Y012696D02*
+X009181Y012696D01*
+X009181Y012499D02*
+X009121Y012499D01*
+X009121Y012401D02*
+X009181Y012401D01*
+X009253Y012302D02*
+X009050Y012302D01*
+X008651Y011568D02*
+X009494Y010726D01*
+X009494Y008258D01*
+X009809Y008258D02*
+X009809Y011411D01*
+X009651Y011568D01*
+X010050Y012302D02*
+X010253Y012302D01*
+X010181Y012401D02*
+X010121Y012401D01*
+X010121Y012499D02*
+X010181Y012499D01*
+X010181Y012696D02*
+X010121Y012696D01*
+X010089Y012795D02*
+X010213Y012795D01*
+X010312Y012894D02*
+X009991Y012894D01*
+X010991Y012894D02*
+X011312Y012894D01*
+X011213Y012795D02*
+X011089Y012795D01*
+X011121Y012696D02*
+X011181Y012696D01*
+X011181Y012499D02*
+X011121Y012499D01*
+X011121Y012401D02*
+X011181Y012401D01*
+X011253Y012302D02*
+X011050Y012302D01*
+X010651Y011568D02*
+X010551Y011468D01*
+X010551Y011168D01*
+X010124Y010741D01*
+X010124Y008258D01*
+X010439Y008258D02*
+X010439Y010556D01*
+X010951Y011068D01*
+X011151Y011068D01*
+X011651Y011568D01*
+X011851Y010768D02*
+X012651Y011568D01*
+X012253Y012302D02*
+X012050Y012302D01*
+X012121Y012401D02*
+X012181Y012401D01*
+X012181Y012499D02*
+X012121Y012499D01*
+X012121Y012696D02*
+X012181Y012696D01*
+X012213Y012795D02*
+X012089Y012795D01*
+X011991Y012894D02*
+X012312Y012894D01*
+X012991Y012894D02*
+X013312Y012894D01*
+X013213Y012795D02*
+X013089Y012795D01*
+X013121Y012696D02*
+X013181Y012696D01*
+X013181Y012499D02*
+X013121Y012499D01*
+X013121Y012401D02*
+X013181Y012401D01*
+X013253Y012302D02*
+X013050Y012302D01*
+X013651Y011568D02*
+X013601Y011518D01*
+X013601Y007868D01*
+X013404Y007671D01*
+X011341Y007671D01*
+X011341Y007356D02*
+X013639Y007356D01*
+X013901Y007618D01*
+X013901Y010018D01*
+X014651Y010768D01*
+X014651Y011568D01*
+X015051Y010968D02*
+X015651Y011568D01*
+X016296Y012007D02*
+X016425Y012007D01*
+X016450Y012105D02*
+X016197Y012105D01*
+X016099Y012204D02*
+X016351Y012204D01*
+X016253Y012302D02*
+X016050Y012302D01*
+X016121Y012401D02*
+X016181Y012401D01*
+X016181Y012499D02*
+X016121Y012499D01*
+X016121Y012696D02*
+X016181Y012696D01*
+X016213Y012795D02*
+X016089Y012795D01*
+X015991Y012894D02*
+X016312Y012894D01*
+X016951Y012204D02*
+X017001Y012204D01*
+X017001Y012105D02*
+X016853Y012105D01*
+X016877Y012007D02*
+X017001Y012007D01*
+X017001Y011908D02*
+X016976Y011908D01*
+X016966Y011218D02*
+X017001Y011218D01*
+X017001Y011120D02*
+X016867Y011120D01*
+X016863Y011021D02*
+X017001Y011021D01*
+X017001Y010923D02*
+X016961Y010923D01*
+X016701Y010923D02*
+X016601Y010923D01*
+X016601Y011021D02*
+X016701Y011021D01*
+X016701Y010824D02*
+X016601Y010824D01*
+X016601Y010726D02*
+X016701Y010726D01*
+X016701Y010627D02*
+X016601Y010627D01*
+X016181Y010430D02*
+X016121Y010430D01*
+X016079Y010331D02*
+X016223Y010331D01*
+X016322Y010233D02*
+X015980Y010233D01*
+X015882Y010134D02*
+X016421Y010134D01*
+X016454Y010036D02*
+X015848Y010036D01*
+X015051Y010068D02*
+X015051Y010968D01*
+X015051Y010068D02*
+X014201Y009218D01*
+X014201Y007368D01*
+X013874Y007041D01*
+X011341Y007041D01*
+X011341Y006726D02*
+X014109Y006726D01*
+X014501Y007118D01*
+X014501Y008418D01*
+X014726Y008361D02*
+X015161Y008361D01*
+X015181Y008459D02*
+X014825Y008459D01*
+X014923Y008558D02*
+X015181Y008558D01*
+X015181Y008656D02*
+X015022Y008656D01*
+X015120Y008755D02*
+X015181Y008755D01*
+X015219Y008853D02*
+X015271Y008853D01*
+X015317Y008952D02*
+X015370Y008952D01*
+X015416Y009050D02*
+X017001Y009050D01*
+X017001Y008952D02*
+X016932Y008952D01*
+X016701Y008952D02*
+X016601Y008952D01*
+X016601Y008853D02*
+X016701Y008853D01*
+X016701Y008755D02*
+X016601Y008755D01*
+X016601Y008656D02*
+X016701Y008656D01*
+X016601Y008558D02*
+X016121Y008558D01*
+X016181Y008518D02*
+X016181Y008374D01*
+X016456Y008098D01*
+X016601Y008098D01*
+X016601Y008518D01*
+X016181Y008518D01*
+X016181Y008459D02*
+X016121Y008459D01*
+X016108Y008361D02*
+X016194Y008361D01*
+X016293Y008262D02*
+X016009Y008262D01*
+X015911Y008163D02*
+X016391Y008163D01*
+X016601Y008163D02*
+X016701Y008163D01*
+X016701Y008262D02*
+X016601Y008262D01*
+X016601Y008361D02*
+X016701Y008361D01*
+X016701Y008459D02*
+X016601Y008459D01*
+X016911Y008163D02*
+X017001Y008163D01*
+X017001Y008065D02*
+X015431Y008065D01*
+X015385Y007966D02*
+X015332Y007966D01*
+X015286Y007868D02*
+X015234Y007868D01*
+X015187Y007769D02*
+X015135Y007769D01*
+X015181Y007671D02*
+X015036Y007671D01*
+X015001Y007572D02*
+X015181Y007572D01*
+X015181Y007474D02*
+X015001Y007474D01*
+X015001Y007375D02*
+X015175Y007375D01*
+X015077Y007277D02*
+X015001Y007277D01*
+X015101Y007018D02*
+X015651Y007568D01*
+X016024Y007277D02*
+X016278Y007277D01*
+X016181Y007374D02*
+X016456Y007098D01*
+X016601Y007098D01*
+X016601Y007518D01*
+X016181Y007518D01*
+X016181Y007374D01*
+X016181Y007375D02*
+X016121Y007375D01*
+X016121Y007474D02*
+X016181Y007474D01*
+X016121Y007572D02*
+X016601Y007572D01*
+X016601Y007474D02*
+X016701Y007474D01*
+X016701Y007375D02*
+X016601Y007375D01*
+X016601Y007277D02*
+X016701Y007277D01*
+X016701Y007178D02*
+X016601Y007178D01*
+X016377Y007178D02*
+X015926Y007178D01*
+X015903Y006981D02*
+X016399Y006981D01*
+X016301Y006882D02*
+X016002Y006882D01*
+X016100Y006784D02*
+X016202Y006784D01*
+X016181Y006685D02*
+X016121Y006685D01*
+X016121Y006587D02*
+X016601Y006587D01*
+X016601Y006518D02*
+X016181Y006518D01*
+X016181Y006374D01*
+X016456Y006098D01*
+X016601Y006098D01*
+X016601Y006518D01*
+X016601Y006488D02*
+X016701Y006488D01*
+X016701Y006390D02*
+X016601Y006390D01*
+X016601Y006291D02*
+X016701Y006291D01*
+X016701Y006193D02*
+X016601Y006193D01*
+X016362Y006193D02*
+X015940Y006193D01*
+X016039Y006291D02*
+X016264Y006291D01*
+X016181Y006390D02*
+X016121Y006390D01*
+X016121Y006488D02*
+X016181Y006488D01*
+X016601Y006685D02*
+X016701Y006685D01*
+X016701Y006784D02*
+X016601Y006784D01*
+X016601Y006882D02*
+X016701Y006882D01*
+X016701Y006981D02*
+X016601Y006981D01*
+X016903Y006981D02*
+X017001Y006981D01*
+X017001Y007079D02*
+X015445Y007079D01*
+X015399Y006981D02*
+X015347Y006981D01*
+X015101Y007018D02*
+X015101Y006618D01*
+X014579Y006096D01*
+X011341Y006096D01*
+X011341Y006411D02*
+X014344Y006411D01*
+X014801Y006868D01*
+X014801Y007718D01*
+X015651Y008568D01*
+X016031Y008853D02*
+X016271Y008853D01*
+X016181Y008755D02*
+X016121Y008755D01*
+X016121Y008656D02*
+X016181Y008656D01*
+X016370Y008952D02*
+X015932Y008952D01*
+X015062Y008262D02*
+X014701Y008262D01*
+X014701Y008163D02*
+X014964Y008163D01*
+X014865Y008065D02*
+X014701Y008065D01*
+X014701Y007966D02*
+X014766Y007966D01*
+X015918Y007966D02*
+X016385Y007966D01*
+X016286Y007868D02*
+X016016Y007868D01*
+X016115Y007769D02*
+X016187Y007769D01*
+X016181Y007671D02*
+X016121Y007671D01*
+X016601Y007671D02*
+X016701Y007671D01*
+X016701Y007769D02*
+X016601Y007769D01*
+X016601Y007868D02*
+X016701Y007868D01*
+X016701Y007966D02*
+X016601Y007966D01*
+X016918Y007966D02*
+X017001Y007966D01*
+X017001Y007178D02*
+X016925Y007178D01*
+X016940Y006193D02*
+X017001Y006193D01*
+X017001Y006094D02*
+X015460Y006094D01*
+X015414Y005996D02*
+X015361Y005996D01*
+X015315Y005897D02*
+X015263Y005897D01*
+X015217Y005798D02*
+X015164Y005798D01*
+X015181Y005700D02*
+X015066Y005700D01*
+X014864Y005781D02*
+X015651Y006568D01*
+X015889Y005996D02*
+X016414Y005996D01*
+X016315Y005897D02*
+X015987Y005897D01*
+X016086Y005798D02*
+X016217Y005798D01*
+X016181Y005700D02*
+X016121Y005700D01*
+X016121Y005601D02*
+X016601Y005601D01*
+X016601Y005518D02*
+X016181Y005518D01*
+X016181Y005374D01*
+X016456Y005098D01*
+X016601Y005098D01*
+X016601Y005518D01*
+X016601Y005503D02*
+X016701Y005503D01*
+X016701Y005404D02*
+X016601Y005404D01*
+X016601Y005306D02*
+X016701Y005306D01*
+X016701Y005207D02*
+X016601Y005207D01*
+X016601Y005109D02*
+X016701Y005109D01*
+X016701Y005010D02*
+X016601Y005010D01*
+X016601Y004912D02*
+X016701Y004912D01*
+X016701Y004813D02*
+X016601Y004813D01*
+X016601Y004714D02*
+X016701Y004714D01*
+X016601Y004616D02*
+X016121Y004616D01*
+X016121Y004714D02*
+X016181Y004714D01*
+X016231Y004813D02*
+X016071Y004813D01*
+X015973Y004912D02*
+X016330Y004912D01*
+X016428Y005010D02*
+X015874Y005010D01*
+X015856Y005109D02*
+X016446Y005109D01*
+X016348Y005207D02*
+X015955Y005207D01*
+X016053Y005306D02*
+X016249Y005306D01*
+X016181Y005404D02*
+X016121Y005404D01*
+X016121Y005503D02*
+X016181Y005503D01*
+X016601Y005700D02*
+X016701Y005700D01*
+X016701Y005798D02*
+X016601Y005798D01*
+X016601Y005897D02*
+X016701Y005897D01*
+X016701Y005996D02*
+X016601Y005996D01*
+X016889Y005996D02*
+X017001Y005996D01*
+X016987Y005897D02*
+X017001Y005897D01*
+X017001Y005207D02*
+X016955Y005207D01*
+X017001Y005109D02*
+X016856Y005109D01*
+X016874Y005010D02*
+X017001Y005010D01*
+X017001Y004912D02*
+X016973Y004912D01*
+X016701Y004517D02*
+X016601Y004517D01*
+X016601Y004518D02*
+X016601Y004098D01*
+X016456Y004098D01*
+X016181Y004374D01*
+X016181Y004518D01*
+X016601Y004518D01*
+X016601Y004419D02*
+X016701Y004419D01*
+X016701Y004320D02*
+X016601Y004320D01*
+X016601Y004222D02*
+X016701Y004222D01*
+X016701Y004123D02*
+X016601Y004123D01*
+X016601Y004025D02*
+X016701Y004025D01*
+X016701Y003926D02*
+X016601Y003926D01*
+X016601Y003828D02*
+X016701Y003828D01*
+X016701Y003729D02*
+X016601Y003729D01*
+X016601Y003630D02*
+X016701Y003630D01*
+X016601Y003532D02*
+X016121Y003532D01*
+X016181Y003518D02*
+X016181Y003374D01*
+X016456Y003098D01*
+X016601Y003098D01*
+X016601Y003518D01*
+X016181Y003518D01*
+X016181Y003433D02*
+X016121Y003433D01*
+X016082Y003335D02*
+X016220Y003335D01*
+X016319Y003236D02*
+X015984Y003236D01*
+X015885Y003138D02*
+X016417Y003138D01*
+X016601Y003138D02*
+X016701Y003138D01*
+X016701Y003236D02*
+X016601Y003236D01*
+X016601Y003335D02*
+X016701Y003335D01*
+X016701Y003433D02*
+X016601Y003433D01*
+X016885Y003138D02*
+X017001Y003138D01*
+X017001Y003236D02*
+X016984Y003236D01*
+X017001Y003039D02*
+X015463Y003039D01*
+X015417Y003138D02*
+X015365Y003138D01*
+X015319Y003236D02*
+X015301Y003236D01*
+X015101Y003118D02*
+X015651Y002568D01*
+X015304Y002251D02*
+X013498Y002251D01*
+X013498Y002349D02*
+X015205Y002349D01*
+X015181Y002448D02*
+X013498Y002448D01*
+X013464Y002546D02*
+X015181Y002546D01*
+X015181Y002645D02*
+X013492Y002645D01*
+X013498Y002744D02*
+X015181Y002744D01*
+X015095Y002842D02*
+X013498Y002842D01*
+X013498Y003039D02*
+X014901Y003039D01*
+X014901Y003138D02*
+X013498Y003138D01*
+X013443Y003236D02*
+X014901Y003236D01*
+X014901Y003335D02*
+X009067Y003335D01*
+X009064Y003433D02*
+X014901Y003433D01*
+X014901Y003532D02*
+X009064Y003532D01*
+X009064Y003630D02*
+X014901Y003630D01*
+X014858Y003729D02*
+X009064Y003729D01*
+X009064Y003828D02*
+X014759Y003828D01*
+X014661Y003926D02*
+X011242Y003926D01*
+X011340Y004025D02*
+X014562Y004025D01*
+X014463Y004123D02*
+X011439Y004123D01*
+X011537Y004222D02*
+X014365Y004222D01*
+X014351Y004518D02*
+X015101Y003768D01*
+X015101Y003118D01*
+X014996Y002941D02*
+X013200Y002941D01*
+X013151Y002903D02*
+X013151Y003518D01*
+X013103Y003236D02*
+X013200Y003236D01*
+X013200Y003138D02*
+X013103Y003138D01*
+X013103Y003039D02*
+X013200Y003039D01*
+X013102Y002941D02*
+X012701Y002941D01*
+X012701Y002842D02*
+X012804Y002842D01*
+X012804Y003039D02*
+X012642Y003039D01*
+X012804Y003138D02*
+X009265Y003138D01*
+X009363Y003039D02*
+X010460Y003039D01*
+X010401Y002941D02*
+X009462Y002941D01*
+X009560Y002842D02*
+X010401Y002842D01*
+X010401Y002349D02*
+X008901Y002349D01*
+X008901Y002251D02*
+X010401Y002251D01*
+X010405Y002152D02*
+X008897Y002152D01*
+X008901Y002448D02*
+X009389Y002448D01*
+X009290Y002546D02*
+X008901Y002546D01*
+X008901Y002645D02*
+X009192Y002645D01*
+X009093Y002744D02*
+X008901Y002744D01*
+X008901Y002842D02*
+X008995Y002842D01*
+X008551Y002568D02*
+X007751Y002568D01*
+X006486Y002568D01*
+X006151Y002234D01*
+X005804Y002251D02*
+X004429Y002251D01*
+X004429Y002349D02*
+X005804Y002349D01*
+X005804Y002448D02*
+X004429Y002448D01*
+X004429Y002546D02*
+X005838Y002546D01*
+X005810Y002645D02*
+X004429Y002645D01*
+X004429Y002744D02*
+X005804Y002744D01*
+X005804Y002842D02*
+X004429Y002842D01*
+X004429Y002941D02*
+X004341Y003029D01*
+X003390Y003029D01*
+X003339Y002978D01*
+X003318Y002999D01*
+X003284Y003019D01*
+X003246Y003029D01*
+X003157Y003029D01*
+X003068Y003029D01*
+X003040Y003022D01*
+X003032Y003029D01*
+X002845Y003029D01*
+X002845Y003479D01*
+X002853Y003472D01*
+X002982Y003418D01*
+X003121Y003418D01*
+X003249Y003472D01*
+X003348Y003570D01*
+X003401Y003699D01*
+X003401Y003838D01*
+X003348Y003967D01*
+X003249Y004065D01*
+X003151Y004106D01*
+X003151Y004685D01*
+X003334Y004868D01*
+X006434Y004868D01*
+X006551Y004985D01*
+X006701Y005135D01*
+X006701Y005221D01*
+X006764Y005221D01*
+X006809Y005266D01*
+X007594Y005266D01*
+X007649Y005211D01*
+X008273Y005211D01*
+X008331Y005268D01*
+X008372Y005268D01*
+X008294Y005190D01*
+X008294Y004566D01*
+X008349Y004511D01*
+X008349Y003068D01*
+X006689Y003068D01*
+X006601Y002980D01*
+X006601Y002768D01*
+X006569Y002768D01*
+X006498Y002768D01*
+X006498Y002854D01*
+X006200Y002854D01*
+X006200Y002951D01*
+X006498Y002951D01*
+X006498Y003139D01*
+X006488Y003177D01*
+X006468Y003212D01*
+X006440Y003240D01*
+X006406Y003259D01*
+X006368Y003269D01*
+X006200Y003269D01*
+X006200Y002952D01*
+X006103Y002952D01*
+X006103Y003269D01*
+X005935Y003269D01*
+X005896Y003259D01*
+X005862Y003240D01*
+X005834Y003212D01*
+X005815Y003177D01*
+X005804Y003139D01*
+X005804Y002951D01*
+X006102Y002951D01*
+X006151Y002903D02*
+X006151Y003518D01*
+X006103Y003236D02*
+X006200Y003236D01*
+X006200Y003138D02*
+X006103Y003138D01*
+X006103Y003039D02*
+X006200Y003039D01*
+X006200Y002941D02*
+X006601Y002941D01*
+X006601Y002842D02*
+X006498Y002842D01*
+X006498Y003039D02*
+X006660Y003039D01*
+X006498Y003138D02*
+X008349Y003138D01*
+X008349Y003236D02*
+X006443Y003236D01*
+X005859Y003236D02*
+X002845Y003236D01*
+X002845Y003138D02*
+X005804Y003138D01*
+X005804Y003039D02*
+X002845Y003039D01*
+X002845Y003335D02*
+X008349Y003335D01*
+X008349Y003433D02*
+X003157Y003433D01*
+X003310Y003532D02*
+X008349Y003532D01*
+X008349Y003630D02*
+X003373Y003630D01*
+X003401Y003729D02*
+X008349Y003729D01*
+X008349Y003828D02*
+X003401Y003828D01*
+X003365Y003926D02*
+X008349Y003926D01*
+X008349Y004025D02*
+X003290Y004025D01*
+X003151Y004123D02*
+X008349Y004123D01*
+X008349Y004222D02*
+X003151Y004222D01*
+X003151Y004320D02*
+X008349Y004320D01*
+X008349Y004419D02*
+X003151Y004419D01*
+X003151Y004517D02*
+X008343Y004517D01*
+X008294Y004616D02*
+X003151Y004616D01*
+X003180Y004714D02*
+X008294Y004714D01*
+X008294Y004813D02*
+X003279Y004813D01*
+X003251Y005068D02*
+X002951Y004768D01*
+X002951Y003868D01*
+X003051Y003768D01*
+X002945Y003433D02*
+X002845Y003433D01*
+X003157Y003029D02*
+X003157Y002604D01*
+X003157Y002604D01*
+X003157Y003029D01*
+X003157Y002941D02*
+X003157Y002941D01*
+X003157Y002842D02*
+X003157Y002842D01*
+X003157Y002744D02*
+X003157Y002744D01*
+X003157Y002645D02*
+X003157Y002645D01*
+X002645Y002604D02*
+X002645Y005278D01*
+X003151Y005784D01*
+X003518Y005798D02*
+X005454Y005798D01*
+X005450Y005785D02*
+X005450Y005617D01*
+X005768Y005617D01*
+X005768Y005915D01*
+X005580Y005915D01*
+X005542Y005905D01*
+X005508Y005885D01*
+X005480Y005857D01*
+X005460Y005823D01*
+X005450Y005785D01*
+X005450Y005700D02*
+X003518Y005700D01*
+X003518Y005601D02*
+X005768Y005601D01*
+X005768Y005617D02*
+X005768Y005520D01*
+X005450Y005520D01*
+X005450Y005352D01*
+X005460Y005314D01*
+X005480Y005279D01*
+X005491Y005268D01*
+X003334Y005268D01*
+X003168Y005268D01*
+X002868Y004968D01*
+X002845Y004945D01*
+X002845Y005195D01*
+X003087Y005437D01*
+X003430Y005437D01*
+X003518Y005525D01*
+X003518Y005918D01*
+X007561Y005918D01*
+X007561Y005666D01*
+X006852Y005666D01*
+X006852Y005827D01*
+X006764Y005915D01*
+X006207Y005915D01*
+X006151Y005859D01*
+X006125Y005885D01*
+X006091Y005905D01*
+X006053Y005915D01*
+X005865Y005915D01*
+X005865Y005617D01*
+X005768Y005617D01*
+X005817Y005568D02*
+X005301Y005568D01*
+X005450Y005503D02*
+X003496Y005503D01*
+X003107Y005207D02*
+X002857Y005207D01*
+X002845Y005109D02*
+X003009Y005109D01*
+X002910Y005010D02*
+X002845Y005010D01*
+X002956Y005306D02*
+X005465Y005306D01*
+X005450Y005404D02*
+X003055Y005404D01*
+X003251Y005068D02*
+X006351Y005068D01*
+X006501Y005218D01*
+X006501Y005553D01*
+X006486Y005568D01*
+X006501Y005553D02*
+X006588Y005466D01*
+X007961Y005466D01*
+X007964Y005468D01*
+X009301Y005468D01*
+X009494Y005276D01*
+X009494Y004878D01*
+X009809Y004878D02*
+X009809Y006411D01*
+X007901Y008318D01*
+X007901Y010118D01*
+X008101Y010318D01*
+X007301Y009868D02*
+X007001Y010168D01*
+X005251Y010168D01*
+X004651Y010768D01*
+X003451Y010768D01*
+X002651Y011568D01*
+X001651Y011568D02*
+X002751Y010468D01*
+X004551Y010468D01*
+X005151Y009868D01*
+X006651Y009868D01*
+X006801Y009718D01*
+X006554Y009445D02*
+X003887Y009445D01*
+X003845Y009543D02*
+X006475Y009543D01*
+X006434Y009642D02*
+X003665Y009642D01*
+X003484Y009740D02*
+X004996Y009740D01*
+X004898Y009839D02*
+X003304Y009839D01*
+X003123Y009937D02*
+X004799Y009937D01*
+X004701Y010036D02*
+X002943Y010036D01*
+X002762Y010134D02*
+X004602Y010134D01*
+X004504Y010233D02*
+X002582Y010233D01*
+X002605Y010331D02*
+X002116Y010331D01*
+X002116Y010233D02*
+X002220Y010233D01*
+X002185Y010134D02*
+X002116Y010134D01*
+X002116Y010036D02*
+X002194Y010036D01*
+X002192Y009937D02*
+X002116Y009937D01*
+X002116Y009839D02*
+X002190Y009839D01*
+X002188Y009740D02*
+X002116Y009740D01*
+X002116Y009642D02*
+X002186Y009642D01*
+X002184Y009543D02*
+X002035Y009543D01*
+X002182Y009445D02*
+X001656Y009445D01*
+X002009Y009346D02*
+X002179Y009346D01*
+X002122Y009247D02*
+X002073Y009247D01*
+X002092Y009201D02*
+X002092Y009201D01*
+X002083Y008755D02*
+X002117Y008755D01*
+X002123Y008656D02*
+X002096Y008656D01*
+X002099Y008558D02*
+X002128Y008558D01*
+X002134Y008459D02*
+X002097Y008459D01*
+X002072Y008361D02*
+X002139Y008361D01*
+X002145Y008262D02*
+X001979Y008262D01*
+X002005Y008163D02*
+X002150Y008163D01*
+X002156Y008065D02*
+X002077Y008065D01*
+X002109Y007966D02*
+X002161Y007966D01*
+X002167Y007868D02*
+X002094Y007868D01*
+X002114Y007769D02*
+X002172Y007769D01*
+X002166Y007671D02*
+X002136Y007671D01*
+X002142Y007572D02*
+X002222Y007572D01*
+X002137Y007474D02*
+X005450Y007474D01*
+X005450Y007375D02*
+X002117Y007375D01*
+X002064Y007277D02*
+X005483Y007277D01*
+X005768Y007277D02*
+X005865Y007277D01*
+X005865Y007375D02*
+X005768Y007375D01*
+X005768Y007474D02*
+X005865Y007474D01*
+X005817Y007568D02*
+X005301Y007568D01*
+X005450Y007671D02*
+X002695Y007671D01*
+X002870Y007769D02*
+X005450Y007769D01*
+X005491Y007868D02*
+X003044Y007868D01*
+X003370Y007966D02*
+X007101Y007966D01*
+X007101Y007868D02*
+X006812Y007868D01*
+X006852Y007769D02*
+X007101Y007769D01*
+X007301Y007668D02*
+X007301Y009868D01*
+X007101Y009445D02*
+X007048Y009445D01*
+X007101Y009346D02*
+X004029Y009346D01*
+X004190Y009247D02*
+X007101Y009247D01*
+X007101Y009149D02*
+X004350Y009149D01*
+X004527Y009050D02*
+X007101Y009050D01*
+X007101Y008952D02*
+X004626Y008952D01*
+X004636Y008853D02*
+X007101Y008853D01*
+X007101Y008755D02*
+X004603Y008755D01*
+X004449Y008656D02*
+X007101Y008656D01*
+X007101Y008558D02*
+X004295Y008558D01*
+X004141Y008459D02*
+X007101Y008459D01*
+X007101Y008361D02*
+X003987Y008361D01*
+X003833Y008262D02*
+X007101Y008262D01*
+X007101Y008163D02*
+X003679Y008163D01*
+X003524Y008065D02*
+X007101Y008065D01*
+X007301Y007668D02*
+X007614Y007356D01*
+X007961Y007356D01*
+X007961Y007041D02*
+X007529Y007041D01*
+X007001Y007568D01*
+X006486Y007568D01*
+X006820Y007277D02*
+X007010Y007277D01*
+X007109Y007178D02*
+X001984Y007178D01*
+X001857Y006784D02*
+X000651Y006784D01*
+X000651Y006685D02*
+X001785Y006685D01*
+X001785Y006587D02*
+X000651Y006587D01*
+X000651Y006488D02*
+X001785Y006488D01*
+X001785Y006390D02*
+X000651Y006390D01*
+X000651Y006291D02*
+X001785Y006291D01*
+X001786Y006193D02*
+X000651Y006193D01*
+X000708Y006094D02*
+X001836Y006094D01*
+X001785Y005996D02*
+X000807Y005996D01*
+X000905Y005897D02*
+X001785Y005897D01*
+X001785Y005798D02*
+X001004Y005798D01*
+X001102Y005700D02*
+X001785Y005700D01*
+X001785Y005601D02*
+X001201Y005601D01*
+X001300Y005503D02*
+X001807Y005503D01*
+X001595Y005207D02*
+X002189Y005207D01*
+X002189Y005109D02*
+X001694Y005109D01*
+X001792Y005010D02*
+X002189Y005010D01*
+X002189Y004912D02*
+X001891Y004912D01*
+X001989Y004813D02*
+X002189Y004813D01*
+X002189Y004714D02*
+X002088Y004714D01*
+X002151Y004616D02*
+X002189Y004616D01*
+X002189Y004517D02*
+X002151Y004517D01*
+X002151Y004419D02*
+X002189Y004419D01*
+X002189Y004320D02*
+X002151Y004320D01*
+X002151Y004222D02*
+X002189Y004222D01*
+X002189Y004123D02*
+X002151Y004123D01*
+X002151Y004025D02*
+X002189Y004025D01*
+X002189Y003926D02*
+X002151Y003926D01*
+X002151Y003828D02*
+X002189Y003828D01*
+X002189Y003729D02*
+X002151Y003729D01*
+X002151Y003630D02*
+X002189Y003630D01*
+X002183Y003532D02*
+X002189Y003532D01*
+X001751Y003630D02*
+X000301Y003630D01*
+X000301Y003532D02*
+X001720Y003532D01*
+X001641Y003433D02*
+X000301Y003433D01*
+X000301Y003335D02*
+X001601Y003335D01*
+X001601Y003236D02*
+X000301Y003236D01*
+X000301Y003138D02*
+X001626Y003138D01*
+X001751Y003729D02*
+X000301Y003729D01*
+X000301Y003828D02*
+X001751Y003828D01*
+X001751Y003926D02*
+X000301Y003926D01*
+X000301Y004025D02*
+X001751Y004025D01*
+X001751Y004123D02*
+X000301Y004123D01*
+X000301Y004222D02*
+X001751Y004222D01*
+X001751Y004320D02*
+X000301Y004320D01*
+X000301Y004419D02*
+X001751Y004419D01*
+X001719Y004517D02*
+X000301Y004517D01*
+X000301Y004616D02*
+X001621Y004616D01*
+X001522Y004714D02*
+X000301Y004714D01*
+X000301Y004813D02*
+X001424Y004813D01*
+X001325Y004912D02*
+X000301Y004912D01*
+X000301Y005010D02*
+X001227Y005010D01*
+X001128Y005109D02*
+X000301Y005109D01*
+X000301Y005207D02*
+X001029Y005207D01*
+X000931Y005306D02*
+X000301Y005306D01*
+X000301Y005404D02*
+X000832Y005404D01*
+X000734Y005503D02*
+X000301Y005503D01*
+X000301Y005601D02*
+X000635Y005601D01*
+X000537Y005700D02*
+X000301Y005700D01*
+X000301Y005798D02*
+X000438Y005798D01*
+X000340Y005897D02*
+X000301Y005897D01*
+X001398Y005404D02*
+X002189Y005404D01*
+X002189Y005306D02*
+X001497Y005306D01*
+X002151Y005784D02*
+X002389Y005546D01*
+X002389Y002604D01*
+X004394Y002152D02*
+X005804Y002152D01*
+X005804Y002054D02*
+X004667Y002054D01*
+X004724Y001955D02*
+X005804Y001955D01*
+X006498Y001955D02*
+X012804Y001955D01*
+X012804Y002054D02*
+X006498Y002054D01*
+X006498Y002152D02*
+X006605Y002152D01*
+X006601Y002251D02*
+X006498Y002251D01*
+X006550Y002349D02*
+X006601Y002349D01*
+X004724Y001857D02*
+X015275Y001857D01*
+X015181Y001758D02*
+X004724Y001758D01*
+X004724Y001660D02*
+X015181Y001660D01*
+X015181Y001463D02*
+X004724Y001463D01*
+X004724Y001561D02*
+X015601Y001561D01*
+X015601Y001660D02*
+X015701Y001660D01*
+X015701Y001758D02*
+X015601Y001758D01*
+X015601Y001857D02*
+X015701Y001857D01*
+X015701Y001955D02*
+X015601Y001955D01*
+X015929Y001955D02*
+X016373Y001955D01*
+X016275Y001857D02*
+X016027Y001857D01*
+X016121Y001758D02*
+X016181Y001758D01*
+X016181Y001660D02*
+X016121Y001660D01*
+X016121Y001463D02*
+X016181Y001463D01*
+X016191Y001364D02*
+X016111Y001364D01*
+X016013Y001265D02*
+X016289Y001265D01*
+X016601Y001561D02*
+X015701Y001561D01*
+X015289Y001265D02*
+X004724Y001265D01*
+X004724Y001364D02*
+X015191Y001364D01*
+X015373Y001955D02*
+X013498Y001955D01*
+X013498Y002054D02*
+X017001Y002054D01*
+X017001Y002152D02*
+X016900Y002152D01*
+X016998Y002251D02*
+X017001Y002251D01*
+X016701Y002251D02*
+X016601Y002251D01*
+X016601Y002349D02*
+X016701Y002349D01*
+X016701Y002448D02*
+X016601Y002448D01*
+X016601Y002518D02*
+X016601Y002098D01*
+X016456Y002098D01*
+X016181Y002374D01*
+X016181Y002518D01*
+X016601Y002518D01*
+X016601Y002546D02*
+X016121Y002546D01*
+X016121Y002448D02*
+X016181Y002448D01*
+X016205Y002349D02*
+X016097Y002349D01*
+X015998Y002251D02*
+X016304Y002251D01*
+X016403Y002152D02*
+X015900Y002152D01*
+X015403Y002152D02*
+X013498Y002152D01*
+X013151Y002234D02*
+X012817Y002568D01*
+X011551Y002568D01*
+X009551Y002568D01*
+X008864Y003256D01*
+X008864Y004878D01*
+X008549Y004878D02*
+X008549Y002571D01*
+X008551Y002568D01*
+X009166Y003236D02*
+X012859Y003236D01*
+X012753Y002349D02*
+X012701Y002349D01*
+X012701Y002251D02*
+X012804Y002251D01*
+X012804Y002152D02*
+X012697Y002152D01*
+X011101Y004068D02*
+X010451Y004068D01*
+X010124Y004396D01*
+X010124Y004878D01*
+X010439Y004878D02*
+X010439Y004531D01*
+X010601Y004368D01*
+X010951Y004368D01*
+X011401Y004818D01*
+X014601Y004818D01*
+X015651Y003768D01*
+X015651Y003568D01*
+X015958Y003926D02*
+X016344Y003926D01*
+X016246Y003828D02*
+X016057Y003828D01*
+X016121Y003729D02*
+X016181Y003729D01*
+X016181Y003630D02*
+X016121Y003630D01*
+X015859Y004025D02*
+X016443Y004025D01*
+X016432Y004123D02*
+X015871Y004123D01*
+X015969Y004222D02*
+X016333Y004222D01*
+X016235Y004320D02*
+X016068Y004320D01*
+X016121Y004419D02*
+X016181Y004419D01*
+X016181Y004517D02*
+X016121Y004517D01*
+X015651Y004568D02*
+X015451Y004568D01*
+X014901Y005118D01*
+X010901Y005118D01*
+X010754Y004971D01*
+X010754Y004878D01*
+X011341Y005466D02*
+X015549Y005466D01*
+X015651Y005568D01*
+X015348Y005207D02*
+X015095Y005207D01*
+X015194Y005109D02*
+X015446Y005109D01*
+X015428Y005010D02*
+X015292Y005010D01*
+X014351Y004518D02*
+X011551Y004518D01*
+X011101Y004068D01*
+X010311Y003926D02*
+X009064Y003926D01*
+X009064Y004025D02*
+X010212Y004025D01*
+X010113Y004123D02*
+X009064Y004123D01*
+X009064Y004222D02*
+X010015Y004222D01*
+X009924Y004320D02*
+X009064Y004320D01*
+X009064Y004419D02*
+X009924Y004419D01*
+X009351Y004218D02*
+X009179Y004391D01*
+X009179Y004878D01*
+X009176Y004813D02*
+X009181Y004813D01*
+X009176Y004714D02*
+X009181Y004714D01*
+X009176Y004616D02*
+X009181Y004616D01*
+X009176Y004517D02*
+X009181Y004517D01*
+X008294Y004912D02*
+X006477Y004912D01*
+X006576Y005010D02*
+X008294Y005010D01*
+X008294Y005109D02*
+X006674Y005109D01*
+X006701Y005207D02*
+X008311Y005207D01*
+X007961Y005466D02*
+X007961Y005781D01*
+X007961Y006096D02*
+X007939Y006118D01*
+X002501Y006118D01*
+X002167Y006453D01*
+X002151Y006453D01*
+X002518Y006488D02*
+X002785Y006488D01*
+X002785Y006390D02*
+X002518Y006390D01*
+X002518Y006587D02*
+X002785Y006587D01*
+X002785Y006685D02*
+X002518Y006685D01*
+X002446Y006784D02*
+X002857Y006784D01*
+X003151Y006453D02*
+X003217Y006453D01*
+X003251Y006418D01*
+X007954Y006418D01*
+X007961Y006411D01*
+X008361Y006390D02*
+X009547Y006390D01*
+X009609Y006291D02*
+X008361Y006291D01*
+X008361Y006193D02*
+X009609Y006193D01*
+X009609Y006094D02*
+X008361Y006094D01*
+X008361Y005996D02*
+X009609Y005996D01*
+X009609Y005897D02*
+X008361Y005897D01*
+X008361Y005798D02*
+X009609Y005798D01*
+X009609Y005700D02*
+X008361Y005700D01*
+X007561Y005700D02*
+X006852Y005700D01*
+X006852Y005798D02*
+X007561Y005798D01*
+X007561Y005897D02*
+X006783Y005897D01*
+X006189Y005897D02*
+X006105Y005897D01*
+X005865Y005897D02*
+X005768Y005897D01*
+X005768Y005798D02*
+X005865Y005798D01*
+X005865Y005700D02*
+X005768Y005700D01*
+X005528Y005897D02*
+X003518Y005897D01*
+X002520Y007572D02*
+X005768Y007572D01*
+X005768Y007671D02*
+X005865Y007671D01*
+X005865Y007769D02*
+X005768Y007769D01*
+X005768Y007868D02*
+X005865Y007868D01*
+X006143Y007868D02*
+X006160Y007868D01*
+X006150Y007277D02*
+X006152Y007277D01*
+X008357Y006587D02*
+X009350Y006587D01*
+X009448Y006488D02*
+X008361Y006488D01*
+X009451Y005601D02*
+X009609Y005601D01*
+X009609Y005503D02*
+X009550Y005503D01*
+X011341Y005781D02*
+X014864Y005781D01*
+X016969Y004222D02*
+X017001Y004222D01*
+X017001Y004123D02*
+X016871Y004123D01*
+X016859Y004025D02*
+X017001Y004025D01*
+X017001Y003926D02*
+X016958Y003926D01*
+X016943Y002941D02*
+X017001Y002941D01*
+X016701Y002941D02*
+X016601Y002941D01*
+X016601Y002842D02*
+X016701Y002842D01*
+X016701Y002744D02*
+X016601Y002744D01*
+X016601Y002645D02*
+X016701Y002645D01*
+X016359Y002941D02*
+X015943Y002941D01*
+X016042Y002842D02*
+X016260Y002842D01*
+X016181Y002744D02*
+X016121Y002744D01*
+X016121Y002645D02*
+X016181Y002645D01*
+X016601Y002152D02*
+X016701Y002152D01*
+X016701Y001955D02*
+X016601Y001955D01*
+X016601Y001857D02*
+X016701Y001857D01*
+X016701Y001758D02*
+X016601Y001758D01*
+X016601Y001660D02*
+X016701Y001660D01*
+X016929Y001955D02*
+X017001Y001955D01*
+X010754Y008258D02*
+X010754Y010371D01*
+X011151Y010768D01*
+X011851Y010768D01*
+X014050Y012302D02*
+X014253Y012302D01*
+X014181Y012401D02*
+X014121Y012401D01*
+X014121Y012499D02*
+X014181Y012499D01*
+X014181Y012696D02*
+X014121Y012696D01*
+X014089Y012795D02*
+X014213Y012795D01*
+X014312Y012894D02*
+X013991Y012894D01*
+X014991Y012894D02*
+X015312Y012894D01*
+X015213Y012795D02*
+X015089Y012795D01*
+X015121Y012696D02*
+X015181Y012696D01*
+X015181Y012499D02*
+X015121Y012499D01*
+X015121Y012401D02*
+X015181Y012401D01*
+X015253Y012302D02*
+X015050Y012302D01*
+X016980Y010233D02*
+X017001Y010233D01*
+X017001Y010134D02*
+X016882Y010134D01*
+X016848Y010036D02*
+X017001Y010036D01*
+X017001Y009937D02*
+X016947Y009937D01*
+X016995Y009247D02*
+X017001Y009247D01*
+X017001Y009149D02*
+X016896Y009149D01*
+X006238Y011317D02*
+X006185Y011317D01*
+X006181Y011415D02*
+X006121Y011415D01*
+X006121Y011514D02*
+X006181Y011514D01*
+X006181Y011711D02*
+X006121Y011711D01*
+X006075Y011810D02*
+X006228Y011810D01*
+X006253Y012302D02*
+X006050Y012302D01*
+X006121Y012401D02*
+X006181Y012401D01*
+X006181Y012499D02*
+X006121Y012499D01*
+X006121Y012696D02*
+X006181Y012696D01*
+X006213Y012795D02*
+X006089Y012795D01*
+X005991Y012894D02*
+X006312Y012894D01*
+X005312Y012894D02*
+X004991Y012894D01*
+X005089Y012795D02*
+X005213Y012795D01*
+X005181Y012696D02*
+X005121Y012696D01*
+X005121Y012499D02*
+X005181Y012499D01*
+X005181Y012401D02*
+X005121Y012401D01*
+X005050Y012302D02*
+X005253Y012302D01*
+X002507Y010430D02*
+X002116Y010430D01*
+X002116Y010529D02*
+X002408Y010529D01*
+X002310Y010627D02*
+X002021Y010627D01*
+D22*
+X005301Y007568D03*
+X005301Y005568D03*
+X006151Y003518D03*
+X009351Y004218D03*
+X008601Y006718D03*
+X006801Y009718D03*
+X008101Y010318D03*
+X001501Y003668D03*
+X013151Y003518D03*
+D23*
+X003051Y003768D03*
+X001951Y003268D03*
+D24*
+X001606Y007293D02*
+X001666Y007333D01*
+X001696Y007403D01*
+X001726Y007503D01*
+X001756Y007633D01*
+X001806Y007693D01*
+X001826Y007703D01*
+X001876Y007683D01*
+X001916Y007633D01*
+X001946Y007553D01*
+X001946Y007633D01*
+X001916Y007733D01*
+X001876Y007803D01*
+X001786Y007803D01*
+X001746Y007743D01*
+X001786Y007743D01*
+X001866Y007753D01*
+X001746Y007743D02*
+X001716Y007613D01*
+X001666Y007463D01*
+X001616Y007413D01*
+X001536Y007413D01*
+X001476Y007493D01*
+X001466Y007523D02*
+X001476Y007423D01*
+X001506Y007343D01*
+X001506Y007373D01*
+X001526Y007373D01*
+X001626Y007363D01*
+X001606Y007293D02*
+X001566Y007293D01*
+X001506Y007343D01*
+X001466Y007523D02*
+X001466Y007643D01*
+X001486Y007723D01*
+X001516Y007783D01*
+X001916Y007963D02*
+X001726Y008223D01*
+X001686Y008223D01*
+X001476Y008223D01*
+X001476Y008323D01*
+X001686Y008323D01*
+X001906Y008583D01*
+X001906Y008463D01*
+X001716Y008256D01*
+X001716Y008263D01*
+X001696Y008263D01*
+X001506Y008273D01*
+X001686Y008223D02*
+X001716Y008256D01*
+X001596Y008703D02*
+X001656Y008743D01*
+X001686Y008813D01*
+X001716Y008913D01*
+X001746Y009043D01*
+X001796Y009103D01*
+X001816Y009113D01*
+X001866Y009093D01*
+X001906Y009043D01*
+X001936Y008963D01*
+X001934Y008944D01*
+X001934Y008943D01*
+X001936Y008943D01*
+X001936Y009043D01*
+X001906Y009143D01*
+X001866Y009213D01*
+X001776Y009213D01*
+X001756Y009183D01*
+X001756Y009153D01*
+X001776Y009153D01*
+X001856Y009163D01*
+X001756Y009183D02*
+X001736Y009153D01*
+X001706Y009023D01*
+X001656Y008873D01*
+X001606Y008823D01*
+X001526Y008823D01*
+X001466Y008903D01*
+X001456Y008933D02*
+X001466Y008833D01*
+X001496Y008753D01*
+X001516Y008753D01*
+X001516Y008783D01*
+X001616Y008773D01*
+X001596Y008703D02*
+X001556Y008703D01*
+X001496Y008753D01*
+X001456Y008933D02*
+X001456Y009053D01*
+X001476Y009133D01*
+X001506Y009193D01*
+X001466Y009353D02*
+X001466Y009703D01*
+X001466Y009753D01*
+X001926Y009753D01*
+X001926Y009703D01*
+X001466Y009703D01*
+X001466Y009753D02*
+X001466Y009803D01*
+X001926Y009803D01*
+X001926Y009753D01*
+X001926Y009993D02*
+X001926Y010343D01*
+X001466Y010343D01*
+X001466Y010403D01*
+X001926Y010403D01*
+X001926Y010453D01*
+X001716Y010453D01*
+X001716Y009993D01*
+X001466Y009993D02*
+X001466Y010343D01*
+X001466Y010403D02*
+X001466Y010453D01*
+X001716Y010453D01*
+X001926Y010403D02*
+X001926Y010343D01*
+X002386Y010123D02*
+X002996Y009013D01*
+X003216Y009143D02*
+X003216Y008863D01*
+X004436Y008873D01*
+X003216Y008093D01*
+X003146Y008143D01*
+X002366Y007703D01*
+X002286Y009133D01*
+X002366Y009193D01*
+X002386Y010123D01*
+X003686Y009413D01*
+X003686Y009333D01*
+X004436Y008873D01*
+X003686Y009413D02*
+X002766Y008883D01*
+X002976Y008743D02*
+X002366Y007713D01*
+X001946Y007553D02*
+X001946Y007533D01*
+X001946Y007553D02*
+X001936Y007463D01*
+X001886Y007343D01*
+X001296Y007303D02*
+X001296Y010443D01*
+X002286Y009133D02*
+X002976Y008743D01*
+X003206Y008613D01*
+X003216Y008863D02*
+X003216Y008093D01*
+X001876Y008753D02*
+X001926Y008873D01*
+X001934Y008944D01*
+M02*
diff --git a/digital/cms-intro/pcb/orders/eurocircuits_2011-05-11/cms_intro.GTO b/digital/cms-intro/pcb/orders/eurocircuits_2011-05-11/cms_intro.GTO
new file mode 100644
index 00000000..58dee794
--- /dev/null
+++ b/digital/cms-intro/pcb/orders/eurocircuits_2011-05-11/cms_intro.GTO
@@ -0,0 +1,244 @@
+G75*
+G70*
+%OFA0B0*%
+%FSLAX24Y24*%
+%IPPOS*%
+%LPD*%
+%AMOC8*
+5,1,8,0,0,1.08239X$1,22.5*
+%
+%ADD10C,0.0060*%
+%ADD11C,0.0080*%
+D10*
+X000475Y010598D02*
+X000431Y010642D01*
+X000475Y010598D02*
+X000561Y010598D01*
+X000605Y010642D01*
+X000605Y010728D01*
+X000561Y010772D01*
+X000518Y010772D01*
+X000431Y010728D01*
+X000431Y010859D01*
+X000605Y010859D01*
+X000726Y010859D02*
+X000726Y010685D01*
+X000813Y010598D01*
+X000899Y010685D01*
+X000899Y010859D01*
+X002931Y010815D02*
+X002931Y010642D01*
+X002975Y010598D01*
+X003061Y010598D01*
+X003105Y010642D01*
+X003226Y010598D02*
+X003399Y010772D01*
+X003399Y010815D01*
+X003356Y010859D01*
+X003269Y010859D01*
+X003226Y010815D01*
+X003105Y010815D02*
+X003061Y010859D01*
+X002975Y010859D01*
+X002931Y010815D01*
+X003226Y010598D02*
+X003399Y010598D01*
+X003815Y010728D02*
+X003989Y010728D01*
+X003945Y010598D02*
+X003945Y010859D01*
+X003815Y010728D01*
+X004110Y010642D02*
+X004153Y010642D01*
+X004153Y010598D01*
+X004110Y010598D01*
+X004110Y010642D01*
+X004257Y010642D02*
+X004300Y010642D01*
+X004300Y010598D01*
+X004257Y010598D01*
+X004257Y010642D01*
+X004404Y010642D02*
+X004404Y010598D01*
+X004404Y010642D02*
+X004578Y010815D01*
+X004578Y010859D01*
+X004404Y010859D01*
+X006306Y010815D02*
+X006306Y010642D01*
+X006350Y010598D01*
+X006436Y010598D01*
+X006480Y010642D01*
+X006480Y010728D01*
+X006393Y010728D01*
+X006480Y010815D02*
+X006436Y010859D01*
+X006350Y010859D01*
+X006306Y010815D01*
+X006601Y010859D02*
+X006601Y010598D01*
+X006774Y010598D02*
+X006774Y010859D01*
+X006895Y010859D02*
+X007026Y010859D01*
+X007069Y010815D01*
+X007069Y010642D01*
+X007026Y010598D01*
+X006895Y010598D01*
+X006895Y010859D01*
+X006774Y010598D02*
+X006601Y010859D01*
+X007431Y010859D02*
+X007431Y010728D01*
+X007518Y010772D01*
+X007561Y010772D01*
+X007605Y010728D01*
+X007605Y010642D01*
+X007561Y010598D01*
+X007475Y010598D01*
+X007431Y010642D01*
+X007726Y010685D02*
+X007813Y010598D01*
+X007899Y010685D01*
+X007899Y010859D01*
+X007726Y010859D02*
+X007726Y010685D01*
+X007605Y010859D02*
+X007431Y010859D01*
+X011556Y010859D02*
+X011556Y010598D01*
+X011686Y010598D01*
+X011730Y010642D01*
+X011730Y010685D01*
+X011686Y010728D01*
+X011556Y010728D01*
+X011686Y010728D02*
+X011730Y010772D01*
+X011730Y010815D01*
+X011686Y010859D01*
+X011556Y010859D01*
+X011851Y010859D02*
+X012024Y010859D01*
+X012024Y010815D01*
+X011851Y010642D01*
+X011851Y010598D01*
+X012145Y010598D02*
+X012189Y010598D01*
+X012189Y010642D01*
+X012145Y010642D01*
+X012145Y010598D01*
+X012293Y010598D02*
+X012336Y010598D01*
+X012336Y010642D01*
+X012293Y010642D01*
+X012293Y010598D01*
+X012440Y010642D02*
+X012614Y010815D01*
+X012614Y010642D01*
+X012570Y010598D01*
+X012483Y010598D01*
+X012440Y010642D01*
+X012440Y010815D01*
+X012483Y010859D01*
+X012570Y010859D01*
+X012614Y010815D01*
+X014681Y010745D02*
+X014681Y010658D01*
+X014725Y010615D01*
+X014811Y010615D01*
+X014855Y010658D01*
+X014855Y010702D01*
+X014811Y010788D01*
+X014941Y010788D01*
+X014941Y010615D01*
+X014941Y010494D02*
+X014768Y010494D01*
+X014681Y010407D01*
+X014768Y010320D01*
+X014941Y010320D01*
+X014941Y009913D02*
+X014681Y009913D01*
+X014811Y009913D02*
+X014811Y009740D01*
+X014941Y009740D02*
+X014681Y009740D01*
+X014681Y009619D02*
+X014768Y009532D01*
+X014681Y009445D01*
+X014941Y009445D01*
+X014941Y009324D02*
+X014681Y009324D01*
+X014681Y009194D01*
+X014725Y009151D01*
+X014768Y009151D01*
+X014811Y009194D01*
+X014811Y009324D01*
+X014811Y009194D02*
+X014855Y009151D01*
+X014898Y009151D01*
+X014941Y009194D01*
+X014941Y009324D01*
+X014941Y009619D02*
+X014681Y009619D01*
+X014681Y010745D02*
+X014725Y010788D01*
+X014681Y006538D02*
+X014681Y006408D01*
+X014725Y006365D01*
+X014898Y006365D01*
+X014941Y006408D01*
+X014941Y006538D01*
+X014681Y006538D01*
+X014681Y006244D02*
+X014725Y006244D01*
+X014898Y006070D01*
+X014941Y006070D01*
+X014941Y006244D01*
+X014725Y005949D02*
+X014725Y005906D01*
+X014681Y005906D01*
+X014681Y005949D01*
+X014725Y005949D01*
+X014725Y005802D02*
+X014725Y005758D01*
+X014681Y005758D01*
+X014681Y005802D01*
+X014725Y005802D01*
+X014725Y005654D02*
+X014898Y005481D01*
+X014725Y005481D01*
+X014681Y005524D01*
+X014681Y005611D01*
+X014725Y005654D01*
+X014898Y005654D01*
+X014941Y005611D01*
+X014941Y005524D01*
+X014898Y005481D01*
+X014898Y002038D02*
+X014725Y002038D01*
+X014681Y001995D01*
+X014681Y001908D01*
+X014725Y001865D01*
+X014811Y001865D01*
+X014811Y001952D01*
+X014898Y002038D02*
+X014941Y001995D01*
+X014941Y001908D01*
+X014898Y001865D01*
+X014941Y001744D02*
+X014681Y001744D01*
+X014681Y001570D02*
+X014941Y001570D01*
+X014941Y001449D02*
+X014681Y001449D01*
+X014681Y001319D01*
+X014725Y001276D01*
+X014898Y001276D01*
+X014941Y001319D01*
+X014941Y001449D01*
+X014681Y001570D02*
+X014941Y001744D01*
+D11*
+X016026Y009568D02*
+X016276Y009568D01*
+M02*
diff --git a/digital/cms-intro/pcb/orders/eurocircuits_2011-05-11/cms_intro.GTS b/digital/cms-intro/pcb/orders/eurocircuits_2011-05-11/cms_intro.GTS
new file mode 100644
index 00000000..69dc6d3c
--- /dev/null
+++ b/digital/cms-intro/pcb/orders/eurocircuits_2011-05-11/cms_intro.GTS
@@ -0,0 +1,137 @@
+G75*
+G70*
+%OFA0B0*%
+%FSLAX24Y24*%
+%IPPOS*%
+%LPD*%
+%AMOC8*
+5,1,8,0,0,1.08239X$1,22.5*
+%
+%ADD10R,0.0290X0.0580*%
+%ADD11R,0.0580X0.0290*%
+%ADD12R,0.0474X0.0513*%
+%ADD13R,0.0513X0.0474*%
+%ADD14R,0.2080X0.0780*%
+%ADD15OC8,0.0720*%
+%ADD16R,0.0218X0.0631*%
+%ADD17R,0.0789X0.0828*%
+%ADD18R,0.0907X0.0710*%
+D10*
+X008549Y004878D03*
+X008864Y004878D03*
+X009179Y004878D03*
+X009494Y004878D03*
+X009809Y004878D03*
+X010124Y004878D03*
+X010439Y004878D03*
+X010754Y004878D03*
+X010754Y008258D03*
+X010439Y008258D03*
+X010124Y008258D03*
+X009809Y008258D03*
+X009494Y008258D03*
+X009179Y008258D03*
+X008864Y008258D03*
+X008549Y008258D03*
+D11*
+X007961Y007671D03*
+X007961Y007356D03*
+X007961Y007041D03*
+X007961Y006726D03*
+X007961Y006411D03*
+X007961Y006096D03*
+X007961Y005781D03*
+X007961Y005466D03*
+X011341Y005466D03*
+X011341Y005781D03*
+X011341Y006096D03*
+X011341Y006411D03*
+X011341Y006726D03*
+X011341Y007041D03*
+X011341Y007356D03*
+X011341Y007671D03*
+D12*
+X013151Y002903D03*
+X013151Y002234D03*
+X006151Y002234D03*
+X006151Y002903D03*
+D13*
+X005817Y005568D03*
+X006486Y005568D03*
+X006486Y007568D03*
+X005817Y007568D03*
+X003151Y006453D03*
+X003151Y005784D03*
+X002151Y005784D03*
+X002151Y006453D03*
+D14*
+X007751Y002568D03*
+X011551Y002568D03*
+D15*
+X015651Y002568D03*
+X016651Y002568D03*
+X016651Y001568D03*
+X015651Y001568D03*
+X015651Y003568D03*
+X016651Y003568D03*
+X016651Y004568D03*
+X015651Y004568D03*
+X015651Y005568D03*
+X016651Y005568D03*
+X016651Y006568D03*
+X015651Y006568D03*
+X015651Y007568D03*
+X016651Y007568D03*
+X016651Y008568D03*
+X015651Y008568D03*
+X015651Y009568D03*
+X016651Y009568D03*
+X016651Y010568D03*
+X015651Y010568D03*
+X015651Y011568D03*
+X016651Y011568D03*
+X016651Y012568D03*
+X015651Y012568D03*
+X014651Y012568D03*
+X013651Y012568D03*
+X012651Y012568D03*
+X011651Y012568D03*
+X010651Y012568D03*
+X009651Y012568D03*
+X008651Y012568D03*
+X007651Y012568D03*
+X006651Y012568D03*
+X005651Y012568D03*
+X004651Y012568D03*
+X003651Y012568D03*
+X002651Y012568D03*
+X001651Y012568D03*
+X000651Y012568D03*
+X000651Y011568D03*
+X001651Y011568D03*
+X002651Y011568D03*
+X003651Y011568D03*
+X004651Y011568D03*
+X005651Y011568D03*
+X006651Y011568D03*
+X007651Y011568D03*
+X008651Y011568D03*
+X009651Y011568D03*
+X010651Y011568D03*
+X011651Y011568D03*
+X012651Y011568D03*
+X013651Y011568D03*
+X014651Y011568D03*
+D16*
+X003157Y002604D03*
+X002901Y002604D03*
+X002645Y002604D03*
+X002389Y002604D03*
+X002133Y002604D03*
+D17*
+X001070Y001560D03*
+X004220Y001560D03*
+D18*
+X003866Y002564D03*
+X001425Y002564D03*
+M02*
diff --git a/digital/cms-intro/pcb/orders/eurocircuits_2011-05-11/cms_intro.TXT b/digital/cms-intro/pcb/orders/eurocircuits_2011-05-11/cms_intro.TXT
new file mode 100644
index 00000000..7723a9ac
--- /dev/null
+++ b/digital/cms-intro/pcb/orders/eurocircuits_2011-05-11/cms_intro.TXT
@@ -0,0 +1,76 @@
+%
+M48
+M72
+T01C0.0200
+T02C0.0236
+T03C0.0400
+%
+T01
+X1951Y3268
+X3051Y3768
+T02
+X1501Y3668
+X5301Y5568
+X5301Y7568
+X6801Y9718
+X8101Y10318
+X8601Y6718
+X9351Y4218
+X6151Y3518
+X13151Y3518
+T03
+X15651Y3568
+X16651Y3568
+X16651Y2568
+X15651Y2568
+X15651Y1568
+X16651Y1568
+X16651Y4568
+X15651Y4568
+X15651Y5568
+X16651Y5568
+X16651Y6568
+X15651Y6568
+X15651Y7568
+X16651Y7568
+X16651Y8568
+X15651Y8568
+X15651Y9568
+X16651Y9568
+X16651Y10568
+X15651Y10568
+X15651Y11568
+X16651Y11568
+X16651Y12568
+X15651Y12568
+X14651Y12568
+X13651Y12568
+X12651Y12568
+X11651Y12568
+X10651Y12568
+X9651Y12568
+X8651Y12568
+X7651Y12568
+X6651Y12568
+X5651Y12568
+X4651Y12568
+X3651Y12568
+X2651Y12568
+X1651Y12568
+X651Y12568
+X651Y11568
+X1651Y11568
+X2651Y11568
+X3651Y11568
+X4651Y11568
+X5651Y11568
+X6651Y11568
+X7651Y11568
+X8651Y11568
+X9651Y11568
+X10651Y11568
+X11651Y11568
+X12651Y11568
+X13651Y11568
+X14651Y11568
+M30
diff --git a/digital/cms-intro/pcb/orders/eurocircuits_2011-05-11/cms_intro.brd b/digital/cms-intro/pcb/orders/eurocircuits_2011-05-11/cms_intro.brd
new file mode 100644
index 00000000..164d5e8c
--- /dev/null
+++ b/digital/cms-intro/pcb/orders/eurocircuits_2011-05-11/cms_intro.brd
Binary files differ
diff --git a/digital/cms-intro/pcb/orders/eurocircuits_2011-05-11/cms_intro.sch b/digital/cms-intro/pcb/orders/eurocircuits_2011-05-11/cms_intro.sch
new file mode 100644
index 00000000..e051c246
--- /dev/null
+++ b/digital/cms-intro/pcb/orders/eurocircuits_2011-05-11/cms_intro.sch
Binary files differ
diff --git a/digital/dev2/src/usb_gpio/avrconfig.h b/digital/dev2/src/usb_gpio/avrconfig.h
index 0a90876d..eb780e77 100644
--- a/digital/dev2/src/usb_gpio/avrconfig.h
+++ b/digital/dev2/src/usb_gpio/avrconfig.h
@@ -28,6 +28,7 @@
/* utils */
/** AVR Frequency : 1000000, 1843200, 2000000, 3686400, 4000000, 7372800,
* 8000000, 11059200, 14745600, 16000000, 18432000, 20000000. */
+#error "please check frequency"
#define AC_FREQ 8000000
/* usb */
diff --git a/digital/dev2/src/usb_serial_isp/avrconfig.h b/digital/dev2/src/usb_serial_isp/avrconfig.h
index 1dfd63d2..60ddf99b 100644
--- a/digital/dev2/src/usb_serial_isp/avrconfig.h
+++ b/digital/dev2/src/usb_serial_isp/avrconfig.h
@@ -28,6 +28,7 @@
/* utils */
/** AVR Frequency : 1000000, 1843200, 2000000, 3686400, 4000000, 7372800,
* 8000000, 11059200, 14745600, 16000000, 18432000, 20000000. */
+#error "please check frequency"
#define AC_FREQ 8000000
/* uart - UART module. */
diff --git a/digital/dev2/src/usb_twi/avrconfig.h b/digital/dev2/src/usb_twi/avrconfig.h
index 5c2d92ce..83482f75 100644
--- a/digital/dev2/src/usb_twi/avrconfig.h
+++ b/digital/dev2/src/usb_twi/avrconfig.h
@@ -28,6 +28,7 @@
/* utils */
/** AVR Frequency : 1000000, 1843200, 2000000, 3686400, 4000000, 7372800,
* 8000000, 11059200, 14745600, 16000000, 18432000, 20000000. */
+#error "please check frequency"
#define AC_FREQ 8000000
/* twi - TWI module. */
diff --git a/digital/io-hub/src/common/contact.avr.c b/digital/io-hub/src/common/contact.avr.c
index 9f6869b4..d6692566 100644
--- a/digital/io-hub/src/common/contact.avr.c
+++ b/digital/io-hub/src/common/contact.avr.c
@@ -73,7 +73,7 @@ contact_update (void)
enum team_color_e
contact_get_color (void)
{
- return !IO_GET (CONTACT_COLOR) ? TEAM_COLOR_LEFT : TEAM_COLOR_RIGHT;
+ return IO_GET (CONTACT_COLOR) ? TEAM_COLOR_LEFT : TEAM_COLOR_RIGHT;
}
uint8_t
diff --git a/digital/io-hub/src/common/contact.host.c b/digital/io-hub/src/common/contact.host.c
index 5e2309c4..cc302f46 100644
--- a/digital/io-hub/src/common/contact.host.c
+++ b/digital/io-hub/src/common/contact.host.c
@@ -49,7 +49,7 @@ contact_handle (void *user, mex_msg_t *msg)
uint32_t contacts;
mex_msg_pop (msg, "L", &contacts);
ctx.all = contacts;
- ctx.color_state = !(contacts & 1) ? TEAM_COLOR_LEFT : TEAM_COLOR_RIGHT;
+ ctx.color_state = (contacts & 1) ? TEAM_COLOR_LEFT : TEAM_COLOR_RIGHT;
ctx.jack_state = (contacts & 2) ? 1 : 0;
contacts >>= 2;
#define CONTACT(io) do { \
diff --git a/digital/io-hub/src/robospierre/Makefile b/digital/io-hub/src/robospierre/Makefile
index 21411631..88e6c79e 100644
--- a/digital/io-hub/src/robospierre/Makefile
+++ b/digital/io-hub/src/robospierre/Makefile
@@ -2,18 +2,24 @@
BASE = ../../../avr
# Name of the program to build.
PROGS = io_hub
+HOST_PROGS = test_element
# Sources to compile.
-io_hub_SOURCES = main.c \
- clamp.c \
- fsm.host.c fsm_AI_gen.avr.c \
+io_hub_SOURCES = main.c top.c \
+ clamp.c logistic.c element.c pawn_sensor.c \
+ codebar.avr.c codebar.host.c \
+ radar_defs.c radar.c path.c move.c \
+ init.c fsm.host.c fsm_AI_gen.avr.c fsm_queue.c \
pwm.avr.c pwm.host.c \
contact.avr.c contact.host.c \
twi_master.c asserv.c mimot.c \
chrono.c timer.avr.c simu.host.c
+test_element_SOURCES = test_element.c logistic.c element.c
# Modules needed for IO.
MODULES = proto uart twi utils \
- math/fixed math/geometry
-AI_MODULES = twi_master common utils fsm
+ adc devices/usdist \
+ math/fixed math/geometry path/astar
+AI_MODULES = twi_master common utils fsm move
+test_element_MODULES = host math/fixed math/geometry
# Configuration file.
CONFIGFILE = avrconfig.h
AVR_MCU = at90usb1287
diff --git a/digital/io-hub/src/robospierre/avrconfig.h b/digital/io-hub/src/robospierre/avrconfig.h
index 0fc2f11d..581fa136 100644
--- a/digital/io-hub/src/robospierre/avrconfig.h
+++ b/digital/io-hub/src/robospierre/avrconfig.h
@@ -100,6 +100,32 @@
/** Use internal pull up. */
#define AC_TWI_PULL_UP 0
+/* usdist - Analog US distance sensor. */
+/** Number of sensors. */
+#define AC_USDIST_NB 4
+/** Measuring period, in number of update call. */
+#define AC_USDIST_PERIOD 1
+/** List of space separated sensor definition, see usdist.h. */
+#define AC_USDIST_SENSORS \
+ USDIST_SENSOR (0, A, 0) \
+ USDIST_SENSOR (1, A, 1) \
+ USDIST_SENSOR (2, A, 2) \
+ USDIST_SENSOR (3, A, 3)
+
+/* path - Path finding module. */
+/** Report path found for debug. */
+#define AC_PATH_REPORT defined (HOST)
+/** Report function name. */
+#define AC_PATH_REPORT_CALLBACK simu_send_path
+/** Number of possible obstacles. */
+#define AC_PATH_OBSTACLES_NB 2
+
+/* astar - A* path finding module. */
+/** Neighbor callback. */
+#define AC_ASTAR_NEIGHBOR_CALLBACK path_astar_neighbor_callback
+/** Heuristic callback. */
+#define AC_ASTAR_HEURISTIC_CALLBACK path_astar_heuristic_callback
+
/* io-hub - io/ai board. */
/** TWI address of the io board. */
#define AC_IO_TWI_ADDRESS 10
diff --git a/digital/io-hub/src/robospierre/bot.h b/digital/io-hub/src/robospierre/bot.h
index 9043a62c..499046e2 100644
--- a/digital/io-hub/src/robospierre/bot.h
+++ b/digital/io-hub/src/robospierre/bot.h
@@ -31,9 +31,46 @@
#ifdef HOST
# define BOT_SCALE 0.0395840674352314
#else
-# define BOT_SCALE 0.0415178942124
+# define BOT_SCALE 0.0317975134344
#endif
+/** Distance from the robot axis to the front. */
+#define BOT_SIZE_FRONT 150
+/** Distance from the robot axis to the back. */
+#define BOT_SIZE_BACK 150
+/** Distance from the robot axis to the side. */
+#define BOT_SIZE_SIDE 190
+
+/** Radius of an element. */
+#define BOT_ELEMENT_RADIUS 100
+
+/** Distance between the front contact point and the robot center. */
+#define BOT_FRONT_CONTACT_DIST_MM 150
+/** Angle error at the front contact point. */
+#define BOT_FRONT_CONTACT_ANGLE_ERROR_DEG 0
+
+/** Distance from robot center to front pawn detection threshold. */
+#define BOT_PAWN_FRONT_DETECTION_THRESHOLD_MM 190
+/** Distance from robot center to back pawn detection threshold. */
+#define BOT_PAWN_BACK_DETECTION_THRESHOLD_MM -190
+/** Distance from robot center to an element near enough to be taken. */
+#define BOT_PAWN_TAKING_DISTANCE_MM 150
+
+/** Distance from border to position in front of a green element. */
+#define BOT_GREEN_ELEMENT_PLACE_DISTANCE_MM 600
+/** Distance from border to go to capture a green element. */
+#define BOT_GREEN_ELEMENT_DISTANCE_MM \
+ (BOT_ELEMENT_RADIUS + BOT_SIZE_FRONT + 10)
+
+/** Speed used for initialisation. */
+#ifdef HOST
+# define BOT_SPEED_INIT 0x20, 0x20, 0x20, 0x20
+#else
+# define BOT_SPEED_INIT 0x10, 0x10, 0x10, 0x10
+#endif
+/** Normal cruise speed. */
+#define BOT_SPEED_NORMAL 0x50, 0x60, 0x20, 0x20
+
#ifdef HOST
# define BOT_CLAMP_SLOT_FRONT_BOTTOM_ELEVATION_STEP 0
@@ -43,34 +80,106 @@
# define BOT_CLAMP_SLOT_BACK_MIDDLE_ELEVATION_STEP (0x3b0b / 2)
# define BOT_CLAMP_SLOT_BACK_TOP_ELEVATION_STEP 0x3b0b
# define BOT_CLAMP_SLOT_SIDE_ELEVATION_STEP 0x3b0b
-# define BOT_CLAMP_BAY_FRONT_LEAVE_ELEVATION_STEP (0x3b0b / 2)
-# define BOT_CLAMP_BAY_BACK_LEAVE_ELEVATION_STEP (0x3b0b / 2)
+# define BOT_CLAMP_BAY_FRONT_LEAVE_ELEVATION_STEP (0x3b0b / 2 + 1000)
+# define BOT_CLAMP_BAY_BACK_LEAVE_ELEVATION_STEP (0x3b0b / 2 + 1000)
# define BOT_CLAMP_BAY_SIDE_ENTER_LEAVE_ELEVATION_STEP (0x3b0b / 2)
+#define BOT_CLAMP_INIT_ELEVATION_SWITCH_STEP \
+ BOT_CLAMP_SLOT_FRONT_TOP_ELEVATION_STEP
+
+# define BOT_CLAMP_SLOT_FRONT_BOTTOM_ROTATION_STEP 0
+# define BOT_CLAMP_SLOT_FRONT_MIDDLE_ROTATION_STEP 0
+# define BOT_CLAMP_SLOT_FRONT_TOP_ROTATION_STEP 0
+# define BOT_CLAMP_SLOT_BACK_BOTTOM_ROTATION_STEP 0x233e
+# define BOT_CLAMP_SLOT_BACK_MIDDLE_ROTATION_STEP 0x233e
+# define BOT_CLAMP_SLOT_BACK_TOP_ROTATION_STEP 0x233e
-# define BOT_CLAMP_BAY_FRONT_ROTATION_STEP 0
-# define BOT_CLAMP_BAY_BACK_ROTATION_STEP 0x11c6
-# define BOT_CLAMP_BAY_SIDE_ROTATION_STEP (0x11c6 / 2)
+# define BOT_CLAMP_BAY_FRONT_ROTATION_STEP \
+ BOT_CLAMP_SLOT_FRONT_MIDDLE_ROTATION_STEP
+# define BOT_CLAMP_BAY_BACK_ROTATION_STEP \
+ BOT_CLAMP_SLOT_BACK_MIDDLE_ROTATION_STEP
+# define BOT_CLAMP_BAY_SIDE_ROTATION_STEP \
+ (BOT_CLAMP_BAY_BACK_ROTATION_STEP / 2)
+# define BOT_CLAMP_BAY_SIDE_MARGIN_ROTATION_STEP 1000
+
+#define BOT_CLAMP_CLOSED_FRONT_ROTATION_OFFSET 0
+#define BOT_CLAMP_CLOSED_BACK_ROTATION_OFFSET 0
+#define BOT_CLAMP_CLOSED_SIDE_ROTATION_OFFSET 0
#else /* !HOST */
# define BOT_CLAMP_SLOT_FRONT_BOTTOM_ELEVATION_STEP 0
-# define BOT_CLAMP_SLOT_FRONT_MIDDLE_ELEVATION_STEP 0x1d83
-# define BOT_CLAMP_SLOT_FRONT_TOP_ELEVATION_STEP 0x3288
-# define BOT_CLAMP_SLOT_BACK_BOTTOM_ELEVATION_STEP 0
-# define BOT_CLAMP_SLOT_BACK_MIDDLE_ELEVATION_STEP 0x1d83
-# define BOT_CLAMP_SLOT_BACK_TOP_ELEVATION_STEP 0x3288
-# define BOT_CLAMP_SLOT_SIDE_ELEVATION_STEP 0x3288
-# define BOT_CLAMP_BAY_FRONT_LEAVE_ELEVATION_STEP 0x1d83
-# define BOT_CLAMP_BAY_BACK_LEAVE_ELEVATION_STEP 0x1d83
-# define BOT_CLAMP_BAY_SIDE_ENTER_LEAVE_ELEVATION_STEP 0x1d83
+# define BOT_CLAMP_SLOT_FRONT_MIDDLE_ELEVATION_STEP (0x1da7 - 250)
+# define BOT_CLAMP_SLOT_FRONT_TOP_ELEVATION_STEP 0x35e2
+# define BOT_CLAMP_SLOT_BACK_BOTTOM_ELEVATION_STEP 0x0169
+# define BOT_CLAMP_SLOT_BACK_MIDDLE_ELEVATION_STEP (0x1f03 - 250)
+# define BOT_CLAMP_SLOT_BACK_TOP_ELEVATION_STEP 0x3610
+# define BOT_CLAMP_SLOT_SIDE_ELEVATION_STEP (0x3596 + 3 * 0x72)
+# define BOT_CLAMP_BAY_FRONT_LEAVE_ELEVATION_STEP 0x1da7
+# define BOT_CLAMP_BAY_BACK_LEAVE_ELEVATION_STEP 0x1f03
+# define BOT_CLAMP_BAY_SIDE_ENTER_LEAVE_ELEVATION_STEP ((0x1da7 + 0x1f03) / 2)
+#define BOT_CLAMP_INIT_ELEVATION_SWITCH_STEP 0x363f
+
+# define BOT_CLAMP_SLOT_FRONT_BOTTOM_ROTATION_STEP 92
+# define BOT_CLAMP_SLOT_FRONT_MIDDLE_ROTATION_STEP 92
+# define BOT_CLAMP_SLOT_FRONT_TOP_ROTATION_STEP 92
+# define BOT_CLAMP_SLOT_BACK_BOTTOM_ROTATION_STEP 0x2433
+# define BOT_CLAMP_SLOT_BACK_MIDDLE_ROTATION_STEP 0x2433
+# define BOT_CLAMP_SLOT_BACK_TOP_ROTATION_STEP 0x2433
-# define BOT_CLAMP_BAY_FRONT_ROTATION_STEP 0
-# define BOT_CLAMP_BAY_BACK_ROTATION_STEP 0x10e2
-# define BOT_CLAMP_BAY_SIDE_ROTATION_STEP 0x820
+# define BOT_CLAMP_BAY_FRONT_ROTATION_STEP \
+ BOT_CLAMP_SLOT_FRONT_MIDDLE_ROTATION_STEP
+# define BOT_CLAMP_BAY_BACK_ROTATION_STEP \
+ BOT_CLAMP_SLOT_BACK_MIDDLE_ROTATION_STEP
+# define BOT_CLAMP_BAY_SIDE_ROTATION_STEP (0x1183 + 120)
+# define BOT_CLAMP_BAY_SIDE_MARGIN_ROTATION_STEP 1000
+
+#define BOT_CLAMP_CLOSED_FRONT_ROTATION_OFFSET -129
+#define BOT_CLAMP_CLOSED_BACK_ROTATION_OFFSET -60
+#define BOT_CLAMP_CLOSED_SIDE_ROTATION_OFFSET -120
#endif /* !HOST */
+#define BOT_CLAMP_INIT_ELEVATION_STEP \
+ (BOT_CLAMP_SLOT_FRONT_MIDDLE_ELEVATION_STEP + 10 * 0x72)
+
+#define BOT_CLAMP_CLOSED_ROTATION_OFFSET(pos) \
+ (CLAMP_IS_SLOT_IN_FRONT_BAY (pos) \
+ ? BOT_CLAMP_CLOSED_FRONT_ROTATION_OFFSET \
+ : (CLAMP_IS_SLOT_IN_BACK_BAY (pos) \
+ ? BOT_CLAMP_CLOSED_BACK_ROTATION_OFFSET \
+ : BOT_CLAMP_CLOSED_SIDE_ROTATION_OFFSET))
+
+#define BOT_CLAMP_INIT_ELEVATION_SPEED 0x10
+#define BOT_CLAMP_INIT_ROTATION_SPEED -0x04
#define BOT_CLAMP_ELEVATION_SPEED 0x60
-#define BOT_CLAMP_ROTATION_SPEED 0x30
+#define BOT_CLAMP_ROTATION_SPEED 0x60
+#define BOT_CLAMP_ROTATION_OFFSET_SPEED 1
+
+#define BOT_PWM_CLAMP 2
+#define BOT_PWM_DOOR_FRONT_BOTTOM 0
+#define BOT_PWM_DOOR_FRONT_TOP 1
+#define BOT_PWM_DOOR_BACK_BOTTOM 3
+#define BOT_PWM_DOOR_BACK_TOP 4
+
+#define BOT_PWM_CLAMP_OPEN_TIME 150
+#define BOT_PWM_CLAMP_OPEN 0x1ff, 150, 0
+#define BOT_PWM_CLAMP_CLOSE_TIME 150
+#define BOT_PWM_CLAMP_CLOSE -0x1ff, 150, 0
+
+#define BOT_PWM_DOOR_OPEN_TIME 12
+#define BOT_PWM_DOOR_OPEN(slot) \
+ 0x1ff, (((slot) == CLAMP_SLOT_FRONT_BOTTOM \
+ || (slot) == CLAMP_SLOT_BACK_BOTTOM) ? 80 : 62), 0x55
+#define BOT_PWM_DOOR_CLOSE_TIME 100
+#define BOT_PWM_DOOR_CLOSE(slot) \
+ -0x1ff, (((slot) == CLAMP_SLOT_FRONT_BOTTOM \
+ || (slot) == CLAMP_SLOT_BACK_BOTTOM) ? 80 : 62), \
+ (((slot) == CLAMP_SLOT_FRONT_BOTTOM \
+ || (slot) == CLAMP_SLOT_BACK_BOTTOM) ? -0x100 : -0x200)
+
+#define BOT_PWM_CLAMP_INIT 0x1ff, 150, 0
+#define BOT_PWM_DOOR_INIT 0x100, 160, 0
+#define BOT_PWM_DOOR_INIT_START 0x55
+#define BOT_PWM_CLAMP_DOOR_INIT 250
#endif /* bot_h */
diff --git a/digital/io-hub/src/robospierre/clamp.c b/digital/io-hub/src/robospierre/clamp.c
index 2f1b2471..84b2771c 100644
--- a/digital/io-hub/src/robospierre/clamp.c
+++ b/digital/io-hub/src/robospierre/clamp.c
@@ -25,39 +25,145 @@
#include "common.h"
#include "clamp.h"
+#include "mimot.h"
+#include "pwm.h"
+#include "contact.h"
+#include "bot.h"
+#include "element.h"
+#include "playground.h"
+
#define FSM_NAME AI
#include "fsm.h"
+#include "fsm_queue.h"
-#include "mimot.h"
-#include "bot.h"
+#include "logistic.h"
+#include "pawn_sensor.h"
-FSM_INIT
+/*
+ * There is two FSM in this file.
+ *
+ * The clamp FSM handles high level clamp behaviour, new elements, drop, and
+ * gives orders to the clamp move FSM.
+ *
+ * The clamp move FSM only handle moving the clamp without load or moving an
+ * element from a slot to another one.
+ */
FSM_STATES (
- /* Wait order. */
+ /* Initial state. */
+ CLAMP_START,
+ /* Initialisation sequence: opening everything. */
+ CLAMP_INIT_OPENING,
+ /* Initialisation sequence: going to the middle level. */
+ CLAMP_INIT_GOING_MIDDLE,
+ /* Initialisation sequence: finding front right edge. */
+ CLAMP_INIT_FINDING_ROTATION_EDGE,
+ /* Initialisation sequence: finding top switch. */
+ CLAMP_INIT_FINDING_TOP,
+ /* Initialisation sequence: going to rest position. */
+ CLAMP_INIT_GOING_REST,
+ /* Clamp ready, waiting in rest position. */
+ CLAMP_INIT_READY,
+
+ /* Returning to idle position. */
+ CLAMP_GOING_IDLE,
+ /* Waiting external events, clamp at middle level. */
CLAMP_IDLE,
+ /* Taking an element at bottom slots. */
+ CLAMP_TAKING_DOOR_CLOSING,
+ /* Moving elements around. */
+ CLAMP_MOVING_ELEMENT,
+ /* Droping a tower. */
+ CLAMP_DROPING_DOOR_OPENING,
+ /* Droping a tower, waiting for robot to advance. */
+ CLAMP_DROPING_WAITING_ROBOT,
+ /* Clamp locked in a bay. */
+ CLAMP_LOCKED,
+ /* Clamp blocked. */
+ CLAMP_BLOCKED,
+
+ /* Waiting movement order. */
+ CLAMP_MOVE_IDLE,
/* Moving to a final or intermediary position. */
- CLAMP_ROUTING)
+ CLAMP_MOVE_ROUTING,
+ /* Moving to source slot. */
+ CLAMP_MOVE_SRC_ROUTING,
+ /* Closing the clamp once arrived at source. */
+ CLAMP_MOVE_SRC_CLAMP_CLOSING,
+ /* Opening door once clamp closed. */
+ CLAMP_MOVE_SRC_DOOR_OPENDING,
+ /* Moving to destination slot. */
+ CLAMP_MOVE_DST_ROUTING,
+ /* Closing door once arrived at destination. */
+ CLAMP_MOVE_DST_DOOR_CLOSING,
+ /* Opening the clamp once door closed. */
+ CLAMP_MOVE_DST_CLAMP_OPENING)
FSM_EVENTS (
+ /* New element inside bottom slot. */
+ clamp_new_element,
+ /* Order to prepare tower. */
+ clamp_prepare,
+ /* Sent when an element has just been taken (door closed). */
+ clamp_taken,
+ /* Sent when clamp is working. */
+ clamp_working,
+ /* Sent when clamp return to idle state. */
+ clamp_done,
+ /* Sent when clamp is blocked. */
+ clamp_blocked,
+ /* Order to drop elements. */
+ clamp_drop,
+ /* Sent once drop is done, but robot should advance to completely
+ * free the dropped tower. */
+ clamp_drop_waiting,
+ /* Received when top FSM made the robot advance after a drop. */
+ clamp_drop_clear,
/* Order to move the clamp. */
clamp_move,
+ /* Clamp movement success. */
+ clamp_move_success,
+ /* Clamp movement failure. */
+ clamp_move_failure,
/* Elevation and elevation motor success. */
clamp_elevation_rotation_success,
+ /* Elevation or elevation motor failure. */
+ clamp_elevation_or_rotation_failure,
+ /* Elevation motor success. */
+ clamp_elevation_success,
/* Elevation motor failure. */
clamp_elevation_failure,
+ /* Rotation motor success. */
+ clamp_rotation_success,
/* Rotation motor failure. */
clamp_rotation_failure)
-FSM_START_WITH (CLAMP_IDLE)
+FSM_START_WITH (CLAMP_START)
+FSM_START_WITH (CLAMP_MOVE_IDLE)
/** Clamp context. */
struct clamp_t
{
- /* Current position. */
+ /** True if clamp is working. */
+ uint8_t working;
+ /** Current position. */
uint8_t pos_current;
- /* Requested position. */
+ /** Requested position. */
uint8_t pos_request;
+ /** Element moving destination. */
+ uint8_t moving_to;
+ /** Position of a new element. */
+ uint8_t pos_new;
+ /** New element type. */
+ uint8_t new_element_type;
+ /** Drop direction, drop on the other side. */
+ uint8_t drop_direction;
+ /** True if clamp is open. */
+ uint8_t open;
+ /** True if clamp position is controled. */
+ uint8_t controled;
+ /** Contact state at start of move, for head check. */
+ uint8_t contact_head_before_move;
};
/** Global context. */
@@ -67,35 +173,185 @@ struct clamp_t clamp_global;
/** Clamp positions. */
static const uint16_t clamp_pos[][2] = {
{ BOT_CLAMP_SLOT_FRONT_BOTTOM_ELEVATION_STEP,
- BOT_CLAMP_BAY_FRONT_ROTATION_STEP },
+ BOT_CLAMP_SLOT_FRONT_BOTTOM_ROTATION_STEP },
{ BOT_CLAMP_SLOT_FRONT_MIDDLE_ELEVATION_STEP,
- BOT_CLAMP_BAY_FRONT_ROTATION_STEP },
+ BOT_CLAMP_SLOT_FRONT_MIDDLE_ROTATION_STEP },
{ BOT_CLAMP_SLOT_FRONT_TOP_ELEVATION_STEP,
- BOT_CLAMP_BAY_FRONT_ROTATION_STEP },
+ BOT_CLAMP_SLOT_FRONT_TOP_ROTATION_STEP },
{ BOT_CLAMP_SLOT_BACK_BOTTOM_ELEVATION_STEP,
- BOT_CLAMP_BAY_BACK_ROTATION_STEP },
+ BOT_CLAMP_SLOT_BACK_BOTTOM_ROTATION_STEP },
{ BOT_CLAMP_SLOT_BACK_MIDDLE_ELEVATION_STEP,
- BOT_CLAMP_BAY_BACK_ROTATION_STEP },
+ BOT_CLAMP_SLOT_BACK_MIDDLE_ROTATION_STEP },
{ BOT_CLAMP_SLOT_BACK_TOP_ELEVATION_STEP,
- BOT_CLAMP_BAY_BACK_ROTATION_STEP },
+ BOT_CLAMP_SLOT_BACK_TOP_ROTATION_STEP },
{ BOT_CLAMP_SLOT_SIDE_ELEVATION_STEP,
BOT_CLAMP_BAY_SIDE_ROTATION_STEP },
{ BOT_CLAMP_BAY_FRONT_LEAVE_ELEVATION_STEP,
BOT_CLAMP_BAY_FRONT_ROTATION_STEP },
+ { BOT_CLAMP_BAY_FRONT_LEAVE_ELEVATION_STEP,
+ BOT_CLAMP_BAY_SIDE_ROTATION_STEP },
{ BOT_CLAMP_BAY_BACK_LEAVE_ELEVATION_STEP,
BOT_CLAMP_BAY_BACK_ROTATION_STEP },
+ { BOT_CLAMP_BAY_BACK_LEAVE_ELEVATION_STEP,
+ BOT_CLAMP_BAY_SIDE_ROTATION_STEP },
{ BOT_CLAMP_BAY_SIDE_ENTER_LEAVE_ELEVATION_STEP,
BOT_CLAMP_BAY_SIDE_ROTATION_STEP },
};
+/** Slot doors. */
+static const uint8_t clamp_slot_door[] = {
+ BOT_PWM_DOOR_FRONT_BOTTOM,
+ 0xff,
+ BOT_PWM_DOOR_FRONT_TOP,
+ BOT_PWM_DOOR_BACK_BOTTOM,
+ 0xff,
+ BOT_PWM_DOOR_BACK_TOP,
+ 0xff
+};
+
+static void
+clamp_openclose (uint8_t open);
+
+static void
+clamp_route (void);
+
+static void
+clamp_head_check_prepare (uint8_t from);
+
+void
+clamp_init (void)
+{
+ ctx.open = 1;
+}
+
+uint8_t
+clamp_working (void)
+{
+ return ctx.working;
+}
+
void
clamp_move (uint8_t pos)
{
if (pos != ctx.pos_current)
{
ctx.pos_request = pos;
+ ctx.moving_to = CLAMP_POS_NB;
FSM_HANDLE (AI, clamp_move);
}
+ else
+ fsm_queue_post_event (FSM_EVENT (AI, clamp_move_success));
+}
+
+void
+clamp_move_element (uint8_t from, uint8_t to)
+{
+ assert (from != to);
+ ctx.pos_request = from;
+ ctx.moving_to = to;
+ clamp_head_check_prepare (from);
+ FSM_HANDLE (AI, clamp_move);
+}
+
+void
+clamp_new_element (uint8_t pos, uint8_t element_type)
+{
+ assert (pos == CLAMP_SLOT_FRONT_BOTTOM || pos == CLAMP_SLOT_BACK_BOTTOM);
+ ctx.pos_new = pos;
+ ctx.new_element_type = element_type;
+ FSM_HANDLE (AI, clamp_new_element);
+}
+
+void
+clamp_prepare (uint8_t prepare)
+{
+ logistic_global.prepare = prepare;
+ FSM_HANDLE (AI, clamp_prepare);
+}
+
+uint8_t
+clamp_drop (uint8_t drop_direction)
+{
+ if (FSM_CAN_HANDLE (AI, clamp_drop))
+ {
+ ctx.drop_direction = drop_direction;
+ FSM_HANDLE (AI, clamp_drop);
+ return 1;
+ }
+ else
+ return 0;
+}
+
+void
+clamp_drop_clear (void)
+{
+ FSM_HANDLE (AI, clamp_drop_clear);
+}
+
+void
+clamp_door (uint8_t pos, uint8_t open)
+{
+ if (pos == 0xff)
+ clamp_openclose (open);
+ else if (clamp_slot_door[pos] != 0xff)
+ {
+ if (open)
+ pwm_set_timed (clamp_slot_door[pos], BOT_PWM_DOOR_OPEN (pos));
+ else
+ pwm_set_timed (clamp_slot_door[pos], BOT_PWM_DOOR_CLOSE (pos));
+ }
+}
+
+uint8_t
+clamp_handle_event (void)
+{
+ if (FSM_CAN_HANDLE (AI, clamp_new_element))
+ {
+ uint8_t element_type;
+ element_type = pawn_sensor_get (DIRECTION_FORWARD);
+ if (element_type)
+ {
+ clamp_new_element (CLAMP_SLOT_FRONT_BOTTOM, element_type);
+ return 1;
+ }
+ element_type = pawn_sensor_get (DIRECTION_BACKWARD);
+ if (element_type)
+ {
+ clamp_new_element (CLAMP_SLOT_BACK_BOTTOM, element_type);
+ return 1;
+ }
+ }
+ /* Handle special hardware offset. */
+ uint16_t rotation_position = mimot_get_motor1_position ();
+ if ((ctx.pos_current == CLAMP_BAY_FRONT_LEAVING
+ && rotation_position > (BOT_CLAMP_BAY_SIDE_ROTATION_STEP +
+ BOT_CLAMP_BAY_FRONT_ROTATION_STEP) / 2)
+ || (ctx.pos_current == CLAMP_BAY_BACK_LEAVING
+ && rotation_position < (BOT_CLAMP_BAY_BACK_ROTATION_STEP +
+ BOT_CLAMP_BAY_SIDE_ROTATION_STEP) / 2))
+ {
+ /* Go directly to next point. */
+ clamp_route ();
+ }
+ return 0;
+}
+
+/** Open or close clamp and adjust rotation. */
+static void
+clamp_openclose (uint8_t open)
+{
+ if (open)
+ pwm_set_timed (BOT_PWM_CLAMP, BOT_PWM_CLAMP_OPEN);
+ else
+ pwm_set_timed (BOT_PWM_CLAMP, BOT_PWM_CLAMP_CLOSE);
+ if (ctx.controled)
+ {
+ int16_t offset = open ? 0
+ : BOT_CLAMP_CLOSED_ROTATION_OFFSET (ctx.pos_current);
+ mimot_move_motor1_absolute (clamp_pos[ctx.pos_current][1] + offset,
+ BOT_CLAMP_ROTATION_OFFSET_SPEED);
+ }
+ ctx.open = open;
}
/** Find next position and start motors. */
@@ -126,14 +382,30 @@ clamp_route (void)
}
else if (pos_current == CLAMP_BAY_FRONT_LEAVE)
{
- if (pos_request == CLAMP_SLOT_SIDE)
+ if (CLAMP_IS_SLOT_IN_FRONT_BAY (pos_request))
+ pos_new = pos_request;
+ else
+ pos_new = CLAMP_BAY_FRONT_LEAVING;
+ }
+ else if (pos_current == CLAMP_BAY_BACK_LEAVE)
+ {
+ if (CLAMP_IS_SLOT_IN_BACK_BAY (pos_request))
+ pos_new = pos_request;
+ else
+ pos_new = CLAMP_BAY_BACK_LEAVING;
+ }
+ else if (pos_current == CLAMP_BAY_FRONT_LEAVING)
+ {
+ if (pos_request == CLAMP_SLOT_SIDE
+ || pos_request == CLAMP_BAY_SIDE_ENTER_LEAVE)
pos_new = CLAMP_BAY_SIDE_ENTER_LEAVE;
else
pos_new = CLAMP_SLOT_BACK_MIDDLE;
}
- else if (pos_current == CLAMP_BAY_BACK_LEAVE)
+ else if (pos_current == CLAMP_BAY_BACK_LEAVING)
{
- if (pos_request == CLAMP_SLOT_SIDE)
+ if (pos_request == CLAMP_SLOT_SIDE
+ || pos_request == CLAMP_BAY_SIDE_ENTER_LEAVE)
pos_new = CLAMP_BAY_SIDE_ENTER_LEAVE;
else
pos_new = CLAMP_SLOT_FRONT_MIDDLE;
@@ -151,32 +423,584 @@ clamp_route (void)
/* Run motors. */
mimot_move_motor0_absolute (clamp_pos[pos_new][0],
BOT_CLAMP_ELEVATION_SPEED);
- mimot_move_motor1_absolute (clamp_pos[pos_new][1],
+ int16_t offset = ctx.open ? 0
+ : BOT_CLAMP_CLOSED_ROTATION_OFFSET (pos_new);
+ mimot_move_motor1_absolute (clamp_pos[pos_new][1] + offset,
BOT_CLAMP_ROTATION_SPEED);
+ ctx.controled = 1;
/* Remember new position. */
ctx.pos_current = pos_new;
}
-FSM_TRANS (CLAMP_IDLE, clamp_move, CLAMP_ROUTING)
+static void
+clamp_taken_pawn (uint8_t element_type)
{
- clamp_route ();
- return FSM_NEXT (CLAMP_IDLE, clamp_move);
+ position_t robot_pos;
+ asserv_get_position (&robot_pos);
+ element_taken (element_nearest_element_id (robot_pos), element_type);
+}
+
+/* When lifting an element, we can discover it is actually a head. In this
+ * case, change destination. */
+static void
+clamp_head_check (void)
+{
+ uint8_t from = logistic_global.moving_from;
+ if (!ctx.contact_head_before_move && logistic_global.slots[from] == ELEMENT_PAWN)
+ {
+ /* Look head contact. */
+ uint8_t contact_head = 0;
+ if (from == CLAMP_SLOT_FRONT_BOTTOM)
+ contact_head = !IO_GET (CONTACT_FRONT_TOP);
+ else if (from == CLAMP_SLOT_BACK_BOTTOM)
+ contact_head = !IO_GET (CONTACT_BACK_TOP);
+ /* Change? */
+ if (contact_head)
+ {
+ logistic_element_change (from, ELEMENT_KING);
+ clamp_taken_pawn (ELEMENT_HEAD);
+ if (logistic_global.moving_from != from)
+ /* Cancel move. */
+ ctx.pos_request = ctx.moving_to = from;
+ else
+ /* Change move. */
+ ctx.pos_request = ctx.moving_to = logistic_global.moving_to;
+ }
+ }
+}
+
+/** Prepare head check, if contact is set yet, this is not a new head. */
+static void
+clamp_head_check_prepare (uint8_t from)
+{
+ ctx.contact_head_before_move = 0;
+ if (CLAMP_IS_SLOT_IN_FRONT_BAY (from))
+ ctx.contact_head_before_move = !IO_GET (CONTACT_FRONT_TOP);
+ else if (CLAMP_IS_SLOT_IN_BACK_BAY (from))
+ ctx.contact_head_before_move = !IO_GET (CONTACT_BACK_TOP);
+}
+
+/* When clamp moved to bottom slot, we can discover it is actually a tower.
+ * In this case, stop movement. */
+static uint8_t
+clamp_tower_check (void)
+{
+ uint8_t from = logistic_global.moving_from;
+ if ((from == CLAMP_SLOT_FRONT_BOTTOM || from == CLAMP_SLOT_BACK_BOTTOM)
+ && ctx.pos_current == from
+ && logistic_global.slots[from] == ELEMENT_PAWN)
+ {
+ /* Check for green zone. */
+ position_t robot_pos;
+ asserv_get_position (&robot_pos);
+ if (robot_pos.v.x < 450 || robot_pos.v.x > PG_WIDTH - 450)
+ return 0;
+ /* Look tower contact. */
+ uint8_t contact_tower;
+ if (from == CLAMP_SLOT_FRONT_BOTTOM)
+ contact_tower = !IO_GET (CONTACT_FRONT_MIDDLE);
+ else
+ contact_tower = !IO_GET (CONTACT_BACK_MIDDLE);
+ /* Change? */
+ if (contact_tower)
+ {
+ logistic_element_change (from, ELEMENT_TOWER);
+ clamp_taken_pawn (ELEMENT_TOWER);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static void
+clamp_blocked (void)
+{
+ /* Free everything. */
+ clamp_openclose (1);
+ uint16_t rotation_position = mimot_get_motor1_position ();
+ uint16_t elevation_position = mimot_get_motor0_position ();
+ if (rotation_position < BOT_CLAMP_BAY_SIDE_ROTATION_STEP
+ - BOT_CLAMP_BAY_SIDE_MARGIN_ROTATION_STEP)
+ {
+ clamp_door (CLAMP_SLOT_FRONT_BOTTOM, 1);
+ if (elevation_position
+ > (BOT_CLAMP_SLOT_FRONT_MIDDLE_ELEVATION_STEP
+ + BOT_CLAMP_SLOT_FRONT_TOP_ELEVATION_STEP) / 2)
+ {
+ clamp_door (CLAMP_SLOT_FRONT_TOP, 1);
+ logistic_dump (DIRECTION_FORWARD, 1);
+ }
+ else
+ logistic_dump (DIRECTION_FORWARD, 0);
+ }
+ else if (rotation_position > BOT_CLAMP_BAY_SIDE_ROTATION_STEP
+ + BOT_CLAMP_BAY_SIDE_MARGIN_ROTATION_STEP)
+ {
+ clamp_door (CLAMP_SLOT_BACK_BOTTOM, 1);
+ if (elevation_position
+ > (BOT_CLAMP_SLOT_BACK_MIDDLE_ELEVATION_STEP
+ + BOT_CLAMP_SLOT_BACK_TOP_ELEVATION_STEP) / 2)
+ {
+ clamp_door (CLAMP_SLOT_BACK_TOP, 1);
+ logistic_dump (DIRECTION_BACKWARD, 1);
+ }
+ else
+ logistic_dump (DIRECTION_BACKWARD, 0);
+ }
+ mimot_motor0_free ();
+ mimot_motor1_free ();
+ /* Signal problem. */
+ fsm_queue_post_event (FSM_EVENT (AI, clamp_move_failure));
+}
+
+#define CLAMP_DECISION_MOVE_ELEMENT 0
+#define CLAMP_DECISION_MOVE_TO_IDLE 1
+#define CLAMP_DECISION_CLAMP_LOCKED 2
+#define CLAMP_DECISION_DONE 3
+
+static uint8_t
+clamp_decision (uint8_t unblock)
+{
+ if (!unblock && logistic_global.moving_from != CLAMP_SLOT_NB)
+ {
+ clamp_move_element (logistic_global.moving_from,
+ logistic_global.moving_to);
+ return CLAMP_DECISION_MOVE_ELEMENT;
+ }
+ else if (logistic_global.prepare != 3
+ && (unblock
+ || logistic_global.clamp_pos_idle != ctx.pos_current))
+ {
+ if (logistic_path_clear (ctx.pos_current,
+ logistic_global.clamp_pos_idle))
+ {
+ clamp_move (logistic_global.clamp_pos_idle);
+ return CLAMP_DECISION_MOVE_TO_IDLE;
+ }
+ else
+ {
+ ctx.working = 0;
+ fsm_queue_post_event (FSM_EVENT (AI, clamp_done));
+ return CLAMP_DECISION_CLAMP_LOCKED;
+ }
+ }
+ else
+ {
+ ctx.working = 0;
+ fsm_queue_post_event (FSM_EVENT (AI, clamp_done));
+ return CLAMP_DECISION_DONE;
+ }
+}
+
+/* CLAMP FSM */
+
+FSM_TRANS (CLAMP_START, init_actuators, CLAMP_INIT_OPENING)
+{
+ pwm_set_timed (BOT_PWM_DOOR_FRONT_BOTTOM, BOT_PWM_DOOR_INIT);
+ pwm_set_timed (BOT_PWM_DOOR_FRONT_TOP, BOT_PWM_DOOR_INIT);
+ pwm_set_timed (BOT_PWM_DOOR_BACK_BOTTOM, BOT_PWM_DOOR_INIT);
+ pwm_set_timed (BOT_PWM_DOOR_BACK_TOP, BOT_PWM_DOOR_INIT);
+ pwm_set_timed (BOT_PWM_CLAMP, BOT_PWM_CLAMP_INIT);
+ return FSM_NEXT (CLAMP_START, init_actuators);
}
-FSM_TRANS (CLAMP_ROUTING, clamp_elevation_rotation_success,
- done, CLAMP_IDLE,
- next, CLAMP_ROUTING)
+FSM_TRANS_TIMEOUT (CLAMP_INIT_OPENING, BOT_PWM_CLAMP_DOOR_INIT,
+ CLAMP_INIT_GOING_MIDDLE)
+{
+ mimot_move_motor0_absolute (mimot_get_motor0_position () +
+ BOT_CLAMP_INIT_ELEVATION_STEP,
+ BOT_CLAMP_INIT_ELEVATION_SPEED);
+ return FSM_NEXT_TIMEOUT (CLAMP_INIT_OPENING);
+}
+
+FSM_TRANS (CLAMP_INIT_GOING_MIDDLE, clamp_elevation_success,
+ CLAMP_INIT_FINDING_ROTATION_EDGE)
+{
+ mimot_motor1_find_zero (BOT_CLAMP_INIT_ROTATION_SPEED, 0, 0);
+ return FSM_NEXT (CLAMP_INIT_GOING_MIDDLE, clamp_elevation_success);
+}
+
+FSM_TRANS (CLAMP_INIT_FINDING_ROTATION_EDGE, clamp_rotation_success,
+ CLAMP_INIT_FINDING_TOP)
+{
+ mimot_motor0_find_zero (BOT_CLAMP_INIT_ELEVATION_SPEED, 1,
+ BOT_CLAMP_INIT_ELEVATION_SWITCH_STEP);
+ return FSM_NEXT (CLAMP_INIT_FINDING_ROTATION_EDGE,
+ clamp_rotation_success);
+}
+
+FSM_TRANS (CLAMP_INIT_FINDING_TOP, clamp_elevation_success,
+ rest, CLAMP_INIT_GOING_REST,
+ demo, CLAMP_GOING_IDLE)
+{
+ if (IO_GET (CONTACT_STRAT))
+ {
+ clamp_move (CLAMP_BAY_SIDE_ENTER_LEAVE);
+ return FSM_NEXT (CLAMP_INIT_FINDING_TOP, clamp_elevation_success,
+ rest);
+ }
+ else
+ {
+ clamp_move (logistic_global.clamp_pos_idle);
+ return FSM_NEXT (CLAMP_INIT_FINDING_TOP, clamp_elevation_success,
+ demo);
+ }
+}
+
+FSM_TRANS (CLAMP_INIT_GOING_REST, clamp_move_success, CLAMP_INIT_READY)
+{
+ mimot_motor0_free ();
+ mimot_motor1_free ();
+ return FSM_NEXT (CLAMP_INIT_GOING_REST, clamp_move_success);
+}
+
+FSM_TRANS (CLAMP_INIT_READY, init_start_round, CLAMP_GOING_IDLE)
+{
+ pwm_set (BOT_PWM_DOOR_FRONT_BOTTOM, BOT_PWM_DOOR_INIT_START);
+ pwm_set (BOT_PWM_DOOR_FRONT_TOP, BOT_PWM_DOOR_INIT_START);
+ pwm_set (BOT_PWM_DOOR_BACK_BOTTOM, BOT_PWM_DOOR_INIT_START);
+ pwm_set (BOT_PWM_DOOR_BACK_TOP, BOT_PWM_DOOR_INIT_START);
+ clamp_move (logistic_global.clamp_pos_idle);
+ return FSM_NEXT (CLAMP_INIT_READY, init_start_round);
+}
+
+FSM_TRANS (CLAMP_GOING_IDLE, clamp_move_success, CLAMP_IDLE)
+{
+ ctx.working = 0;
+ fsm_queue_post_event (FSM_EVENT (AI, clamp_done));
+ return FSM_NEXT (CLAMP_GOING_IDLE, clamp_move_success);
+}
+
+FSM_TRANS (CLAMP_GOING_IDLE, clamp_move_failure, CLAMP_BLOCKED)
+{
+ fsm_queue_post_event (FSM_EVENT (AI, clamp_blocked));
+ return FSM_NEXT (CLAMP_GOING_IDLE, clamp_move_failure);
+}
+
+FSM_TRANS (CLAMP_IDLE, clamp_new_element, CLAMP_TAKING_DOOR_CLOSING)
+{
+ ctx.working = 1;
+ fsm_queue_post_event (FSM_EVENT (AI, clamp_working));
+ pwm_set_timed (clamp_slot_door[ctx.pos_new],
+ BOT_PWM_DOOR_CLOSE (ctx.pos_new));
+ return FSM_NEXT (CLAMP_IDLE, clamp_new_element);
+}
+
+FSM_TRANS (CLAMP_IDLE, clamp_prepare,
+ move_element, CLAMP_MOVING_ELEMENT,
+ move_to_idle, CLAMP_GOING_IDLE,
+ clamp_locked, CLAMP_LOCKED,
+ done, CLAMP_IDLE)
+{
+ logistic_decision ();
+ switch (clamp_decision (0))
+ {
+ default:
+ case CLAMP_DECISION_MOVE_ELEMENT:
+ return FSM_NEXT (CLAMP_IDLE, clamp_prepare, move_element);
+ case CLAMP_DECISION_MOVE_TO_IDLE:
+ return FSM_NEXT (CLAMP_IDLE, clamp_prepare, move_to_idle);
+ case CLAMP_DECISION_CLAMP_LOCKED:
+ return FSM_NEXT (CLAMP_IDLE, clamp_prepare, clamp_locked);
+ case CLAMP_DECISION_DONE:
+ return FSM_NEXT (CLAMP_IDLE, clamp_prepare, done);
+ }
+}
+
+FSM_TRANS (CLAMP_IDLE, clamp_drop, CLAMP_DROPING_DOOR_OPENING)
+{
+ /* If going forward, drop at back. */
+ uint8_t bay = ctx.drop_direction == DIRECTION_FORWARD
+ ? CLAMP_SLOT_BACK_BOTTOM : CLAMP_SLOT_FRONT_BOTTOM;
+ pwm_set_timed (clamp_slot_door[bay + 0], BOT_PWM_DOOR_OPEN (bay + 0));
+ pwm_set_timed (clamp_slot_door[bay + 2], BOT_PWM_DOOR_OPEN (bay + 2));
+ return FSM_NEXT (CLAMP_IDLE, clamp_drop);
+}
+
+FSM_TRANS_TIMEOUT (CLAMP_TAKING_DOOR_CLOSING, BOT_PWM_DOOR_CLOSE_TIME,
+ move_element, CLAMP_MOVING_ELEMENT,
+ move_to_idle, CLAMP_GOING_IDLE,
+ clamp_locked, CLAMP_LOCKED,
+ done, CLAMP_IDLE)
+{
+ logistic_element_new (ctx.pos_new, ctx.new_element_type);
+ clamp_taken_pawn (ctx.new_element_type);
+ switch (clamp_decision (0))
+ {
+ default:
+ case CLAMP_DECISION_MOVE_ELEMENT:
+ return FSM_NEXT_TIMEOUT (CLAMP_TAKING_DOOR_CLOSING, move_element);
+ case CLAMP_DECISION_MOVE_TO_IDLE:
+ return FSM_NEXT_TIMEOUT (CLAMP_TAKING_DOOR_CLOSING, move_to_idle);
+ case CLAMP_DECISION_CLAMP_LOCKED:
+ return FSM_NEXT_TIMEOUT (CLAMP_TAKING_DOOR_CLOSING, clamp_locked);
+ case CLAMP_DECISION_DONE:
+ return FSM_NEXT_TIMEOUT (CLAMP_TAKING_DOOR_CLOSING, done);
+ }
+}
+
+FSM_TRANS (CLAMP_MOVING_ELEMENT, clamp_move_success,
+ move_element, CLAMP_MOVING_ELEMENT,
+ move_to_idle, CLAMP_GOING_IDLE,
+ clamp_locked, CLAMP_LOCKED,
+ done, CLAMP_IDLE)
+{
+ logistic_element_move_done ();
+ switch (clamp_decision (0))
+ {
+ default:
+ case CLAMP_DECISION_MOVE_ELEMENT:
+ return FSM_NEXT (CLAMP_MOVING_ELEMENT, clamp_move_success,
+ move_element);
+ case CLAMP_DECISION_MOVE_TO_IDLE:
+ return FSM_NEXT (CLAMP_MOVING_ELEMENT, clamp_move_success,
+ move_to_idle);
+ case CLAMP_DECISION_CLAMP_LOCKED:
+ return FSM_NEXT (CLAMP_MOVING_ELEMENT, clamp_move_success,
+ clamp_locked);
+ case CLAMP_DECISION_DONE:
+ return FSM_NEXT (CLAMP_MOVING_ELEMENT, clamp_move_success,
+ done);
+ }
+}
+
+FSM_TRANS (CLAMP_MOVING_ELEMENT, clamp_move_failure, CLAMP_BLOCKED)
+{
+ fsm_queue_post_event (FSM_EVENT (AI, clamp_blocked));
+ return FSM_NEXT (CLAMP_MOVING_ELEMENT, clamp_move_failure);
+}
+
+FSM_TRANS_TIMEOUT (CLAMP_DROPING_DOOR_OPENING, BOT_PWM_CLAMP_OPEN_TIME,
+ CLAMP_DROPING_WAITING_ROBOT)
+{
+ fsm_queue_post_event (FSM_EVENT (AI, clamp_drop_waiting));
+ return FSM_NEXT_TIMEOUT (CLAMP_DROPING_DOOR_OPENING);
+}
+
+FSM_TRANS (CLAMP_DROPING_WAITING_ROBOT, clamp_drop_clear,
+ move_element, CLAMP_MOVING_ELEMENT,
+ move_to_idle, CLAMP_GOING_IDLE,
+ clamp_locked, CLAMP_LOCKED,
+ done, CLAMP_IDLE)
+{
+ logistic_drop (ctx.drop_direction);
+ switch (clamp_decision (0))
+ {
+ default:
+ case CLAMP_DECISION_MOVE_ELEMENT:
+ return FSM_NEXT (CLAMP_DROPING_WAITING_ROBOT, clamp_drop_clear,
+ move_element);
+ case CLAMP_DECISION_MOVE_TO_IDLE:
+ return FSM_NEXT (CLAMP_DROPING_WAITING_ROBOT, clamp_drop_clear,
+ move_to_idle);
+ case CLAMP_DECISION_CLAMP_LOCKED:
+ return FSM_NEXT (CLAMP_DROPING_WAITING_ROBOT, clamp_drop_clear,
+ clamp_locked);
+ case CLAMP_DECISION_DONE:
+ return FSM_NEXT (CLAMP_DROPING_WAITING_ROBOT, clamp_drop_clear,
+ done);
+ }
+}
+
+FSM_TRANS (CLAMP_LOCKED, clamp_new_element, CLAMP_LOCKED)
+{
+ pwm_set_timed (clamp_slot_door[ctx.pos_new],
+ BOT_PWM_DOOR_CLOSE (ctx.pos_new));
+ logistic_element_new (ctx.pos_new, ctx.new_element_type);
+ clamp_taken_pawn (ctx.new_element_type);
+ return FSM_NEXT (CLAMP_LOCKED, clamp_new_element);
+}
+
+FSM_TRANS (CLAMP_LOCKED, clamp_drop, CLAMP_DROPING_DOOR_OPENING)
+{
+ /* If going forward, drop at back. */
+ uint8_t bay = ctx.drop_direction == DIRECTION_FORWARD
+ ? CLAMP_SLOT_BACK_BOTTOM : CLAMP_SLOT_FRONT_BOTTOM;
+ pwm_set_timed (clamp_slot_door[bay + 0], BOT_PWM_DOOR_OPEN (bay + 0));
+ pwm_set_timed (clamp_slot_door[bay + 2], BOT_PWM_DOOR_OPEN (bay + 2));
+ return FSM_NEXT (CLAMP_LOCKED, clamp_drop);
+}
+
+FSM_TRANS (CLAMP_BLOCKED, clamp_prepare,
+ move_to_idle, CLAMP_GOING_IDLE,
+ clamp_locked, CLAMP_LOCKED,
+ done, CLAMP_IDLE)
+{
+ switch (clamp_decision (1))
+ {
+ default:
+ case CLAMP_DECISION_MOVE_TO_IDLE:
+ return FSM_NEXT (CLAMP_BLOCKED, clamp_prepare, move_to_idle);
+ case CLAMP_DECISION_CLAMP_LOCKED:
+ return FSM_NEXT (CLAMP_BLOCKED, clamp_prepare, clamp_locked);
+ case CLAMP_DECISION_DONE:
+ return FSM_NEXT (CLAMP_BLOCKED, clamp_prepare, done);
+ }
+}
+
+/* CLAMP_MOVE FSM */
+
+FSM_TRANS (CLAMP_MOVE_IDLE, clamp_move,
+ move, CLAMP_MOVE_ROUTING,
+ move_element, CLAMP_MOVE_SRC_ROUTING,
+ move_element_here, CLAMP_MOVE_SRC_CLAMP_CLOSING)
+{
+ if (ctx.moving_to == CLAMP_POS_NB)
+ {
+ clamp_route ();
+ return FSM_NEXT (CLAMP_MOVE_IDLE, clamp_move, move);
+ }
+ else
+ {
+ if (ctx.pos_current != ctx.pos_request)
+ {
+ clamp_route ();
+ return FSM_NEXT (CLAMP_MOVE_IDLE, clamp_move, move_element);
+ }
+ else
+ {
+ clamp_openclose (0);
+ return FSM_NEXT (CLAMP_MOVE_IDLE, clamp_move, move_element_here);
+ }
+ }
+}
+
+FSM_TRANS (CLAMP_MOVE_ROUTING, clamp_elevation_rotation_success,
+ done, CLAMP_MOVE_IDLE,
+ next, CLAMP_MOVE_ROUTING)
{
if (ctx.pos_current == ctx.pos_request)
{
- return FSM_NEXT (CLAMP_ROUTING, clamp_elevation_rotation_success,
+ fsm_queue_post_event (FSM_EVENT (AI, clamp_move_success));
+ return FSM_NEXT (CLAMP_MOVE_ROUTING, clamp_elevation_rotation_success,
done);
}
else
{
clamp_route ();
- return FSM_NEXT (CLAMP_ROUTING, clamp_elevation_rotation_success,
+ return FSM_NEXT (CLAMP_MOVE_ROUTING, clamp_elevation_rotation_success,
next);
}
}
+FSM_TRANS (CLAMP_MOVE_ROUTING, clamp_elevation_or_rotation_failure,
+ CLAMP_MOVE_IDLE)
+{
+ clamp_blocked ();
+ return FSM_NEXT (CLAMP_MOVE_ROUTING, clamp_elevation_or_rotation_failure);
+}
+
+FSM_TRANS (CLAMP_MOVE_SRC_ROUTING, clamp_elevation_rotation_success,
+ cancel, CLAMP_MOVE_IDLE,
+ done, CLAMP_MOVE_SRC_CLAMP_CLOSING,
+ next, CLAMP_MOVE_SRC_ROUTING)
+{
+ if (clamp_tower_check ())
+ {
+ fsm_queue_post_event (FSM_EVENT (AI, clamp_move_success));
+ return FSM_NEXT (CLAMP_MOVE_SRC_ROUTING, clamp_elevation_rotation_success,
+ cancel);
+ }
+ else if (ctx.pos_current == ctx.pos_request)
+ {
+ clamp_openclose (0);
+ return FSM_NEXT (CLAMP_MOVE_SRC_ROUTING,
+ clamp_elevation_rotation_success, done);
+ }
+ else
+ {
+ clamp_route ();
+ return FSM_NEXT (CLAMP_MOVE_SRC_ROUTING,
+ clamp_elevation_rotation_success, next);
+ }
+}
+
+FSM_TRANS (CLAMP_MOVE_SRC_ROUTING, clamp_elevation_or_rotation_failure,
+ CLAMP_MOVE_IDLE)
+{
+ clamp_blocked ();
+ return FSM_NEXT (CLAMP_MOVE_SRC_ROUTING,
+ clamp_elevation_or_rotation_failure);
+}
+
+FSM_TRANS_TIMEOUT (CLAMP_MOVE_SRC_CLAMP_CLOSING, BOT_PWM_CLAMP_CLOSE_TIME,
+ open_door, CLAMP_MOVE_SRC_DOOR_OPENDING,
+ move, CLAMP_MOVE_DST_ROUTING)
+{
+ fsm_queue_post_event (FSM_EVENT (AI, clamp_taken));
+ if (clamp_slot_door[ctx.pos_current] != 0xff)
+ {
+ pwm_set_timed (clamp_slot_door[ctx.pos_current],
+ BOT_PWM_DOOR_OPEN (ctx.pos_current));
+ return FSM_NEXT_TIMEOUT (CLAMP_MOVE_SRC_CLAMP_CLOSING, open_door);
+ }
+ else
+ {
+ ctx.pos_request = ctx.moving_to;
+ clamp_route ();
+ return FSM_NEXT_TIMEOUT (CLAMP_MOVE_SRC_CLAMP_CLOSING, move);
+ }
+}
+
+FSM_TRANS_TIMEOUT (CLAMP_MOVE_SRC_DOOR_OPENDING, BOT_PWM_DOOR_OPEN_TIME,
+ CLAMP_MOVE_DST_ROUTING)
+{
+ ctx.pos_request = ctx.moving_to;
+ clamp_route ();
+ return FSM_NEXT_TIMEOUT (CLAMP_MOVE_SRC_DOOR_OPENDING);
+}
+
+FSM_TRANS (CLAMP_MOVE_DST_ROUTING, clamp_elevation_rotation_success,
+ done_close_door, CLAMP_MOVE_DST_DOOR_CLOSING,
+ done_open_clamp, CLAMP_MOVE_DST_CLAMP_OPENING,
+ next, CLAMP_MOVE_DST_ROUTING)
+{
+ clamp_head_check ();
+ if (ctx.pos_current == ctx.pos_request)
+ {
+ if (clamp_slot_door[ctx.pos_current] != 0xff)
+ {
+ pwm_set_timed (clamp_slot_door[ctx.pos_current],
+ BOT_PWM_DOOR_CLOSE (ctx.pos_current));
+ return FSM_NEXT (CLAMP_MOVE_DST_ROUTING,
+ clamp_elevation_rotation_success,
+ done_close_door);
+ }
+ else
+ {
+ clamp_openclose (1);
+ return FSM_NEXT (CLAMP_MOVE_DST_ROUTING,
+ clamp_elevation_rotation_success,
+ done_open_clamp);
+ }
+ }
+ else
+ {
+ clamp_route ();
+ return FSM_NEXT (CLAMP_MOVE_DST_ROUTING,
+ clamp_elevation_rotation_success, next);
+ }
+}
+
+FSM_TRANS (CLAMP_MOVE_DST_ROUTING, clamp_elevation_or_rotation_failure,
+ CLAMP_MOVE_IDLE)
+{
+ clamp_blocked ();
+ return FSM_NEXT (CLAMP_MOVE_DST_ROUTING,
+ clamp_elevation_or_rotation_failure);
+}
+
+FSM_TRANS_TIMEOUT (CLAMP_MOVE_DST_DOOR_CLOSING, BOT_PWM_DOOR_CLOSE_TIME,
+ CLAMP_MOVE_DST_CLAMP_OPENING)
+{
+ clamp_openclose (1);
+ return FSM_NEXT_TIMEOUT (CLAMP_MOVE_DST_DOOR_CLOSING);
+}
+
+FSM_TRANS_TIMEOUT (CLAMP_MOVE_DST_CLAMP_OPENING, BOT_PWM_CLAMP_OPEN_TIME,
+ CLAMP_MOVE_IDLE)
+{
+ fsm_queue_post_event (FSM_EVENT (AI, clamp_move_success));
+ return FSM_NEXT_TIMEOUT (CLAMP_MOVE_DST_CLAMP_OPENING);
+}
+
diff --git a/digital/io-hub/src/robospierre/clamp.h b/digital/io-hub/src/robospierre/clamp.h
index 104e3cb8..76dcc34b 100644
--- a/digital/io-hub/src/robospierre/clamp.h
+++ b/digital/io-hub/src/robospierre/clamp.h
@@ -36,10 +36,20 @@ enum {
CLAMP_SLOT_SIDE,
/** Leave the front bay, ready to enter side tunnel. */
CLAMP_BAY_FRONT_LEAVE,
+ /** Leaving the front bay, entered the side tunnel. When at midway point,
+ * go directly to the next position. */
+ CLAMP_BAY_FRONT_LEAVING,
/** Leave the back bay, ready to enter side tunnel. */
CLAMP_BAY_BACK_LEAVE,
- /* Enter the side bay. Position on the side, above wheels. */
+ /** Leaving the back bay, entered the side tunnel. When at midway point,
+ * go directly to the next position. */
+ CLAMP_BAY_BACK_LEAVING,
+ /** Enter the side bay. Position on the side, above wheels. */
CLAMP_BAY_SIDE_ENTER_LEAVE,
+ /** Total number of position, including intermediary positions. */
+ CLAMP_POS_NB,
+ /** Number of slots. */
+ CLAMP_SLOT_NB = CLAMP_SLOT_SIDE + 1,
};
/** Is slot in front bay? */
@@ -50,8 +60,46 @@ enum {
#define CLAMP_IS_SLOT_IN_BACK_BAY(slot) \
((slot) >= CLAMP_SLOT_BACK_BOTTOM && (slot) <= CLAMP_SLOT_BACK_TOP)
+/** Initialise clamp module. */
+void
+clamp_init (void);
+
+/** Is clamp working? */
+uint8_t
+clamp_working (void);
+
/** Move clamp to given position. */
void
clamp_move (uint8_t pos);
+/** Move element using clamp. */
+void
+clamp_move_element (uint8_t from, uint8_t to);
+
+/** Simulate the presence of a new element. */
+void
+clamp_new_element (uint8_t pos, uint8_t element_type);
+
+/** Change logisitic preparation level and update clamp state. */
+void
+clamp_prepare (uint8_t prepare);
+
+/** Drop an element tower. Return 0 if not currently possible. If
+ * drop_direction is forward, drop at the back. */
+uint8_t
+clamp_drop (uint8_t drop_direction);
+
+/** Signal robot advanced, and drop is finished. */
+void
+clamp_drop_clear (void);
+
+/** Open/close door (pos = slot) or clamp (pos = 0xff). */
+void
+clamp_door (uint8_t pos, uint8_t open);
+
+/** Examine sensors to generate new events, return non zero if an event was
+ * generated. */
+uint8_t
+clamp_handle_event (void);
+
#endif /* clamp_h */
diff --git a/digital/io-hub/src/robospierre/codebar.avr.c b/digital/io-hub/src/robospierre/codebar.avr.c
new file mode 100644
index 00000000..fcddb079
--- /dev/null
+++ b/digital/io-hub/src/robospierre/codebar.avr.c
@@ -0,0 +1,64 @@
+/* codebar.avr.c */
+/* robospierre - Eurobot 2011 AI. {{{
+ *
+ * Copyright (C) 2011 Nicolas Schodet
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * 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 "common.h"
+#include "codebar.h"
+
+#include "defs.h"
+
+#include "modules/twi/twi.h"
+#include "modules/utils/utils.h"
+#include "modules/utils/crc.h"
+#include "modules/utils/byte.h"
+
+#define CODEBAR_ADDRESS 0x20
+#define CODEBAR_STATUS_LENGTH 7
+
+void
+codebar_init (void)
+{
+}
+
+uint8_t
+codebar_get (uint8_t direction)
+{
+ uint8_t buffer[CODEBAR_STATUS_LENGTH];
+ /* Read status. */
+ twi_master_recv (CODEBAR_ADDRESS, buffer, sizeof (buffer));
+ uint8_t ret = twi_master_wait ();
+ if (ret != CODEBAR_STATUS_LENGTH)
+ return 0;
+ uint8_t crc = crc_compute (buffer + 1, CODEBAR_STATUS_LENGTH - 1);
+ if (crc != buffer[0])
+ return 0;
+ /* Get data. */
+ uint8_t offset = direction == DIRECTION_FORWARD ? 1 : 4;
+ uint16_t age = v8_to_v16 (buffer[offset], buffer[offset + 1]);
+ uint16_t type = buffer[offset + 2];
+ if (age > 3 * 250)
+ return 0;
+ else
+ return type;
+}
+
diff --git a/digital/io-hub/src/robospierre/codebar.h b/digital/io-hub/src/robospierre/codebar.h
new file mode 100644
index 00000000..d334f131
--- /dev/null
+++ b/digital/io-hub/src/robospierre/codebar.h
@@ -0,0 +1,36 @@
+#ifndef codebar_h
+#define codebar_h
+/* codebar.h */
+/* robospierre - Eurobot 2011 AI. {{{
+ *
+ * Copyright (C) 2011 Nicolas Schodet
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * 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.
+ *
+ * }}} */
+
+/** Initialise module. */
+void
+codebar_init (void);
+
+/** Get element type on the specified direction. */
+uint8_t
+codebar_get (uint8_t direction);
+
+#endif /* codebar_h */
diff --git a/digital/io-hub/src/robospierre/codebar.host.c b/digital/io-hub/src/robospierre/codebar.host.c
new file mode 100644
index 00000000..68ced300
--- /dev/null
+++ b/digital/io-hub/src/robospierre/codebar.host.c
@@ -0,0 +1,56 @@
+/* codebar.host.c */
+/* robospierre - Eurobot 2011 AI. {{{
+ *
+ * Copyright (C) 2011 Nicolas Schodet
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * 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 "common.h"
+#include "codebar.h"
+#include "defs.h"
+
+#include "modules/host/host.h"
+#include "modules/host/mex.h"
+
+uint8_t codebar_front, codebar_back;
+
+static void
+codebar_handle (void *user, mex_msg_t *msg)
+{
+ mex_msg_pop (msg, "BB", &codebar_front, &codebar_back);
+}
+
+void
+codebar_init (void)
+{
+ const char *mex_instance = host_get_instance ("io-hub0", 0);
+ uint8_t mtype = mex_node_reservef ("%s:codebar", mex_instance);
+ mex_node_register (mtype, codebar_handle, 0);
+}
+
+uint8_t
+codebar_get (uint8_t direction)
+{
+ if (direction == DIRECTION_FORWARD)
+ return codebar_front;
+ else
+ return codebar_back;
+}
+
diff --git a/digital/io-hub/src/robospierre/contact_defs.h b/digital/io-hub/src/robospierre/contact_defs.h
index 55b34354..132ec050 100644
--- a/digital/io-hub/src/robospierre/contact_defs.h
+++ b/digital/io-hub/src/robospierre/contact_defs.h
@@ -25,13 +25,25 @@
*
* }}} */
-#define CONTACT_COLOR A, 7
-#define CONTACT_JACK F, 7
-#define CONTACT_EX1 E, 0
-#define CONTACT_EX2 E, 1
+#define CONTACT_COLOR E, 3
+#define CONTACT_JACK E, 5
+#define CONTACT_STRAT E, 1
+#define CONTACT_FRONT_BOTTOM A, 4
+#define CONTACT_FRONT_MIDDLE F, 4
+#define CONTACT_BACK_BOTTOM A, 5
+#define CONTACT_BACK_MIDDLE F, 5
+#define CONTACT_FRONT_TOP A, 6
+#define CONTACT_BACK_TOP F, 6
+#define CONTACT_SIDE E, 7
#define CONTACT_LIST \
- CONTACT (CONTACT_EX1) \
- CONTACT (CONTACT_EX2)
+ CONTACT (CONTACT_FRONT_BOTTOM) \
+ CONTACT (CONTACT_FRONT_MIDDLE) \
+ CONTACT (CONTACT_FRONT_TOP) \
+ CONTACT (CONTACT_BACK_BOTTOM) \
+ CONTACT (CONTACT_BACK_MIDDLE) \
+ CONTACT (CONTACT_BACK_TOP) \
+ CONTACT (CONTACT_SIDE) \
+ CONTACT (CONTACT_STRAT)
#endif /* contact_defs_h */
diff --git a/digital/io-hub/src/robospierre/element.c b/digital/io-hub/src/robospierre/element.c
new file mode 100644
index 00000000..881e1be6
--- /dev/null
+++ b/digital/io-hub/src/robospierre/element.c
@@ -0,0 +1,828 @@
+/* element.c */
+/* io - Input & Output with Artificial Intelligence (ai) support on AVR. {{{
+ *
+ * Copyright (C) 2011 Jérôme Jutteau
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * 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 "common.h"
+#include "element.h"
+
+#include "modules/utils/utils.h"
+#include "modules/math/geometry/distance.h"
+#include "modules/math/geometry/geometry.h"
+
+#include "chrono.h"
+#include "logistic.h"
+#include "bot.h"
+#include "playground.h"
+
+/** Offset to be used when everything fail. */
+static uint8_t failure_offset_s;
+
+/** Elements on table. */
+struct element_t element_table[] =
+{
+ /*
+ 20 elements on intersections.
+ To be symmetric, alternate % 2.
+ See ELEMENT_INTERSEC_START and ELEMENT_INTERSEC_END
+ ELEMENT_INTERSEC_END don't takes central pawn.
+ */
+ {ELEMENT_NONE | ELEMENT_PAWN, {1500 - 2 * 350, 5 * 350}, ELEMENT_INTERSEC | ELEMENT_LEFT, 30, 0, 0}, /* top left */
+ {ELEMENT_NONE | ELEMENT_PAWN, {1500 + 2 * 350, 5 * 350}, ELEMENT_INTERSEC | ELEMENT_RIGHT, 30, 0, 0}, /* top right */
+ {ELEMENT_NONE | ELEMENT_PAWN, {1500 - 1 * 350, 5 * 350}, ELEMENT_INTERSEC | ELEMENT_LEFT, 30, 0, 0}, /* middle left */
+ {ELEMENT_NONE | ELEMENT_PAWN, {1500 + 1 * 350, 5 * 350}, ELEMENT_INTERSEC | ELEMENT_RIGHT, 30, 0, 0}, /* middle right */
+ {ELEMENT_NONE | ELEMENT_PAWN, {1500 - 2 * 350, 4 * 350}, ELEMENT_INTERSEC | ELEMENT_LEFT, 30, 0, 0}, /* 2nd line left */
+ {ELEMENT_NONE | ELEMENT_PAWN, {1500 + 2 * 350, 4 * 350}, ELEMENT_INTERSEC | ELEMENT_RIGHT, 30, 0, 0},
+ {ELEMENT_NONE | ELEMENT_PAWN, {1500 - 1 * 350, 4 * 350}, ELEMENT_INTERSEC | ELEMENT_LEFT, 30, 0, 0},
+ {ELEMENT_NONE | ELEMENT_PAWN, {1500 + 1 * 350, 4 * 350}, ELEMENT_INTERSEC | ELEMENT_RIGHT, 30, 0, 0},
+ {ELEMENT_NONE | ELEMENT_PAWN, {1500 - 2 * 350, 3 * 350}, ELEMENT_INTERSEC | ELEMENT_LEFT, 30, 0, 0}, /* 3th line left */
+ {ELEMENT_NONE | ELEMENT_PAWN, {1500 + 2 * 350, 3 * 350}, ELEMENT_INTERSEC | ELEMENT_RIGHT, 30, 0, 0},
+ {ELEMENT_NONE | ELEMENT_PAWN, {1500 - 1 * 350, 3 * 350}, ELEMENT_INTERSEC | ELEMENT_LEFT, 30, 0, 0},
+ {ELEMENT_NONE | ELEMENT_PAWN, {1500 + 1 * 350, 3 * 350}, ELEMENT_INTERSEC | ELEMENT_RIGHT, 30, 0, 0},
+ {ELEMENT_NONE | ELEMENT_PAWN, {1500 - 2 * 350, 2 * 350}, ELEMENT_INTERSEC | ELEMENT_LEFT, 30, 0, 0}, /* 4th line left */
+ {ELEMENT_NONE | ELEMENT_PAWN, {1500 + 2 * 350, 2 * 350}, ELEMENT_INTERSEC | ELEMENT_RIGHT, 30, 0, 0},
+ {ELEMENT_NONE | ELEMENT_PAWN, {1500 - 1 * 350, 2 * 350}, ELEMENT_INTERSEC | ELEMENT_LEFT, 30, 0, 0},
+ {ELEMENT_NONE | ELEMENT_PAWN, {1500 + 1 * 350, 2 * 350}, ELEMENT_INTERSEC | ELEMENT_RIGHT, 30, 0, 0},
+ {ELEMENT_NONE | ELEMENT_PAWN, {1500 - 2 * 350, 1 * 350}, ELEMENT_INTERSEC | ELEMENT_LEFT, 0, 0, 0}, /* 5th line left */
+ {ELEMENT_NONE | ELEMENT_PAWN, {1500 + 2 * 350, 1 * 350}, ELEMENT_INTERSEC | ELEMENT_RIGHT, 0, 0, 0},
+ {ELEMENT_NONE | ELEMENT_PAWN, {1500 - 1 * 350, 1 * 350}, ELEMENT_INTERSEC | ELEMENT_LEFT, -30, 0, 0},
+ {ELEMENT_NONE | ELEMENT_PAWN, {1500 + 1 * 350, 1 * 350}, ELEMENT_INTERSEC | ELEMENT_RIGHT, -30, 0, 0},
+
+ /* Central pawn. (see ELEMENT_CENTRAL_PAWN) */
+ {ELEMENT_PAWN, {1500, 3 * 350}, ELEMENT_INTERSEC | ELEMENT_CENTER, 30, 0, 0},
+
+ /*
+ 10 elements on green zones.
+ To be symmetric, alternate % 2.
+ See ELEMENT_GREEN_START and ELEMENT_GREEN_END
+ */
+ {ELEMENT_ANY, {200, 10 + 280 * 5}, ELEMENT_GREEN |ELEMENT_LEFT, 110, 0, 0}, /* top left */
+ {ELEMENT_ANY, {3000 - 200, 10 + 280 * 5}, ELEMENT_GREEN | ELEMENT_RIGHT, 110, 0, 0}, /* top right */
+ {ELEMENT_ANY, {200, 10 + 280 * 4}, ELEMENT_GREEN |ELEMENT_LEFT, 100, 0, 0}, /* 2nd line left */
+ {ELEMENT_ANY, {3000 - 200, 10 + 280 * 4}, ELEMENT_GREEN | ELEMENT_RIGHT, 100, 0, 0}, /* 2nd line right */
+ {ELEMENT_ANY, {200, 10 + 280 * 3}, ELEMENT_GREEN |ELEMENT_LEFT, 110, 0, 0}, /* ... */
+ {ELEMENT_ANY, {3000 - 200, 10 + 280 * 3}, ELEMENT_GREEN | ELEMENT_RIGHT, 110, 0, 0},
+ {ELEMENT_ANY, {200, 10 + 280 * 2}, ELEMENT_GREEN |ELEMENT_LEFT, 100, 0, 0},
+ {ELEMENT_ANY, {3000 - 200, 10 + 280 * 2}, ELEMENT_GREEN | ELEMENT_RIGHT, 100, 0, 0},
+ {ELEMENT_ANY, {200, 10 + 280 * 1}, ELEMENT_GREEN |ELEMENT_LEFT, -100, 0, 0},
+ {ELEMENT_ANY, {3000 - 200, 10 + 280 * 1}, ELEMENT_GREEN | ELEMENT_RIGHT, -100, 0, 0},
+
+ /*
+ 36 elements in the middle of a square.
+ Altern colors in order to retrieve position % 2.
+ See ELEMENT_UNLOAD_START and ELEMENT_UNLOAD_END
+ */
+ {ELEMENT_NONE | ELEMENT_ANY, {1500 - 2 * 350 - 175, 5 * 350 + 175}, ELEMENT_CENTER | ELEMENT_RIGHT, 0, 0, 0}, /* Top left blue */
+ {ELEMENT_NONE | ELEMENT_ANY, {1500 - 1 * 350 - 175, 5 * 350 + 175}, ELEMENT_CENTER | ELEMENT_LEFT, 0, 10, 0},
+ {ELEMENT_NONE | ELEMENT_ANY, {1500 - 0 * 350 - 175, 5 * 350 + 175}, ELEMENT_CENTER | ELEMENT_RIGHT, 0, 0, 0},
+ {ELEMENT_NONE | ELEMENT_ANY, {1500 + 0 * 350 + 175, 5 * 350 + 175}, ELEMENT_CENTER | ELEMENT_LEFT, 0, 0, 0},
+ {ELEMENT_NONE | ELEMENT_ANY, {1500 + 1 * 350 + 175, 5 * 350 + 175}, ELEMENT_CENTER | ELEMENT_RIGHT, 0, 10, 0},
+ {ELEMENT_NONE | ELEMENT_ANY, {1500 + 2 * 350 + 175, 5 * 350 + 175}, ELEMENT_CENTER | ELEMENT_LEFT, 0, 0, 0},
+ {ELEMENT_NONE | ELEMENT_ANY, {1500 - 2 * 350 - 175, 4 * 350 + 175}, ELEMENT_CENTER | ELEMENT_LEFT, 0, 0, 0}, /* 2nd line left red */
+ {ELEMENT_NONE | ELEMENT_ANY, {1500 - 1 * 350 - 175, 4 * 350 + 175}, ELEMENT_CENTER | ELEMENT_RIGHT | ELEMENT_BONUS, 0, 10, 0}, /* bonus */
+ {ELEMENT_NONE | ELEMENT_ANY, {1500 - 0 * 350 - 175, 4 * 350 + 175}, ELEMENT_CENTER | ELEMENT_LEFT, 0, 0, 0},
+ {ELEMENT_NONE | ELEMENT_ANY, {1500 + 0 * 350 + 175, 4 * 350 + 175}, ELEMENT_CENTER | ELEMENT_RIGHT, 0, 0, 0},
+ {ELEMENT_NONE | ELEMENT_ANY, {1500 + 1 * 350 + 175, 4 * 350 + 175}, ELEMENT_CENTER | ELEMENT_LEFT | ELEMENT_BONUS, 0, 10, 0}, /* bonus */
+ {ELEMENT_NONE | ELEMENT_ANY, {1500 + 2 * 350 + 175, 4 * 350 + 175}, ELEMENT_CENTER | ELEMENT_RIGHT, 0, 0, 0},
+ {ELEMENT_NONE | ELEMENT_ANY, {1500 - 2 * 350 - 175, 3 * 350 + 175}, ELEMENT_CENTER | ELEMENT_RIGHT, 0, 0, 0}, /* 3th line left blue */
+ {ELEMENT_NONE | ELEMENT_ANY, {1500 - 1 * 350 - 175, 3 * 350 + 175}, ELEMENT_CENTER | ELEMENT_LEFT, 0, 0, 0},
+ {ELEMENT_NONE | ELEMENT_ANY, {1500 - 0 * 350 - 175, 3 * 350 + 175}, ELEMENT_CENTER | ELEMENT_RIGHT, 0, 0, 0},
+ {ELEMENT_NONE | ELEMENT_ANY, {1500 + 0 * 350 + 175, 3 * 350 + 175}, ELEMENT_CENTER | ELEMENT_LEFT, 0, 0, 0},
+ {ELEMENT_NONE | ELEMENT_ANY, {1500 + 1 * 350 + 175, 3 * 350 + 175}, ELEMENT_CENTER | ELEMENT_RIGHT, 0, 0, 0},
+ {ELEMENT_NONE | ELEMENT_ANY, {1500 + 2 * 350 + 175, 3 * 350 + 175}, ELEMENT_CENTER | ELEMENT_LEFT, 0, 0, 0},
+ {ELEMENT_NONE | ELEMENT_ANY, {1500 - 2 * 350 - 175, 2 * 350 + 175}, ELEMENT_CENTER | ELEMENT_LEFT, 0, 0, 0}, /* 4th line left red */
+ {ELEMENT_NONE | ELEMENT_ANY, {1500 - 1 * 350 - 175, 2 * 350 + 175}, ELEMENT_CENTER | ELEMENT_RIGHT | ELEMENT_BONUS, 0, 4, 0}, /* bonus */
+ {ELEMENT_NONE | ELEMENT_ANY, {1500 - 0 * 350 - 175, 2 * 350 + 175}, ELEMENT_CENTER | ELEMENT_LEFT, 0, 0, 0},
+ {ELEMENT_NONE | ELEMENT_ANY, {1500 + 0 * 350 + 175, 2 * 350 + 175}, ELEMENT_CENTER | ELEMENT_RIGHT, 0, 0, 0},
+ {ELEMENT_NONE | ELEMENT_ANY, {1500 + 1 * 350 + 175, 2 * 350 + 175}, ELEMENT_CENTER | ELEMENT_LEFT | ELEMENT_BONUS, 0, 4, 0}, /* bonus */
+ {ELEMENT_NONE | ELEMENT_ANY, {1500 + 2 * 350 + 175, 2 * 350 + 175}, ELEMENT_CENTER | ELEMENT_RIGHT, 0, 0, 0},
+ {ELEMENT_NONE | ELEMENT_ANY, {1500 - 2 * 350 - 175, 1 * 350 + 175}, ELEMENT_CENTER | ELEMENT_RIGHT, 0, 0, 0}, /* 5th line left blue */
+ {ELEMENT_NONE | ELEMENT_ANY, {1500 - 1 * 350 - 175, 1 * 350 + 175}, ELEMENT_CENTER | ELEMENT_LEFT, 0, 0, 0},
+ {ELEMENT_NONE | ELEMENT_ANY, {1500 - 0 * 350 - 175, 1 * 350 + 175}, ELEMENT_CENTER | ELEMENT_RIGHT, 0, 0, 0},
+ {ELEMENT_NONE | ELEMENT_ANY, {1500 + 0 * 350 + 175, 1 * 350 + 175}, ELEMENT_CENTER | ELEMENT_LEFT, 0, 0, 0},
+ {ELEMENT_NONE | ELEMENT_ANY, {1500 + 1 * 350 + 175, 1 * 350 + 175}, ELEMENT_CENTER | ELEMENT_RIGHT, 0, 0, 0},
+ {ELEMENT_NONE | ELEMENT_ANY, {1500 + 2 * 350 + 175, 1 * 350 + 175}, ELEMENT_CENTER | ELEMENT_LEFT, 0, 0, 0},
+ {ELEMENT_NONE, {1500 - 2 * 350 - 175, 175}, ELEMENT_CENTER | ELEMENT_SAFE | ELEMENT_LEFT, 0, -100, 0}, /* left red */
+ {ELEMENT_NONE, {1500 - 1 * 350 - 175, 175}, ELEMENT_CENTER | ELEMENT_SAFE | ELEMENT_RIGHT, 0, -100, 0}, /* left blue */
+ {ELEMENT_NONE | ELEMENT_ANY, {1500 - 175, 175}, ELEMENT_CENTER | ELEMENT_LEFT | ELEMENT_BONUS, 0, 9, 0}, /* middle bonus left, red. */
+ {ELEMENT_NONE | ELEMENT_ANY, {1500 + 175, 175}, ELEMENT_CENTER | ELEMENT_RIGHT | ELEMENT_BONUS, 0, 9, 0}, /* middle bonus right, blue. */
+ {ELEMENT_NONE, {1500 + 1 * 350 + 175, 175}, ELEMENT_CENTER | ELEMENT_SAFE | ELEMENT_LEFT, 0, -100, 0}, /* right red */
+ {ELEMENT_NONE, {1500 + 2 * 350 + 175, 175}, ELEMENT_CENTER | ELEMENT_SAFE | ELEMENT_RIGHT, 0, -100, 0} /* right blue */
+};
+
+inline void
+element_set (uint8_t element_id, element_t element)
+{
+ assert (element_id < UTILS_COUNT (element_table));
+ element_table[element_id] = element;
+}
+
+void
+element_init ()
+{
+ /* Set NONE in middle of our squares and keep ELEMENT_NONE | ELEMENT_ANY
+ in others square middle. */
+ uint8_t i;
+ element_t e;
+ for (i = ELEMENT_UNLOAD_START; i <= ELEMENT_UNLOAD_END; i++)
+ {
+ e = element_get (i);
+ if ((team_color == TEAM_COLOR_LEFT &&
+ (e.attr & ELEMENT_LEFT)) ||
+ (team_color == TEAM_COLOR_RIGHT &&
+ (e.attr & ELEMENT_RIGHT)))
+ {
+ e.type = ELEMENT_NONE;
+ element_set (i, e);
+ }
+ }
+
+ /* Negative bonus for the other green zone at start. */
+ /* Do not touch last green emplacement. */
+ for (i = ELEMENT_GREEN_START; i <= ELEMENT_GREEN_END - 2; i++)
+ {
+ element_t e = element_get (i);
+ if (!((team_color == TEAM_COLOR_LEFT && (e.attr & ELEMENT_LEFT)) ||
+ (team_color == TEAM_COLOR_RIGHT && (e.attr & ELEMENT_RIGHT))))
+ {
+ if (e.bonus_load > 0)
+ {
+ e.bonus_load *= -1;
+ element_set (i, e);
+ }
+ }
+ }
+}
+
+int32_t
+element_unload_score (position_t robot_pos, uint8_t element_id)
+{
+ int32_t score = 0;
+ assert (element_id < UTILS_COUNT (element_table));
+ element_t e = element_get (element_id);
+
+ /* If it is not an unload zone, quit. */
+ if (!((e.attr & ELEMENT_CENTER) || (e.attr & ELEMENT_INTERSEC)))
+ return -1;
+
+ /* Unload color. */
+ if (!(
+ (e.attr & ELEMENT_CENTER) &&
+ ((team_color == TEAM_COLOR_LEFT && (e.attr & ELEMENT_LEFT))
+ ||(team_color == TEAM_COLOR_RIGHT && (e.attr & ELEMENT_RIGHT)))
+ ))
+ return -1;
+
+ /* If there is already something here, do not score. */
+ if (e.type != ELEMENT_NONE)
+ return -1;
+
+ /* Failed element. */
+ if (e.failure_until_s
+ && e.failure_until_s + failure_offset_s < (int) (chrono_remaining_time () / 1000))
+ return -1;
+
+ /* Bonus adjust. */
+ score += e.bonus_unload * ELEMENT_BONUS_COEFF;
+
+ /* Unload distance. */
+ /* TODO: minimal distance may not be the best choice. */
+ vect_t v = e.pos;
+ int32_t dr = distance_point_point (&v, &robot_pos.v);
+ score += 4242 - dr;
+
+ /* Alignment with the robot. */
+ if (dr > 100)
+ {
+ vect_t vr = v;
+ vect_sub (&vr, &robot_pos.v);
+ vect_t u;
+ uint16_t a;
+ if (logistic_global.collect_direction == DIRECTION_FORWARD)
+ a = robot_pos.a;
+ else
+ a = robot_pos.a + G_ANGLE_UF016_DEG (180);
+ vect_from_polar_uf016 (&u, 100, a);
+ int32_t dp = vect_dot_product (&u, &vr);
+ int32_t align = dp / dr;
+ score += align;
+ }
+
+ return score;
+}
+
+uint8_t
+element_unload_best (position_t robot_pos)
+{
+ uint8_t i;
+ uint8_t best = 0xff;
+ int32_t score, best_score = 0;
+ uint8_t retry = 0;
+ do
+ {
+ if (retry && failure_offset_s != 255)
+ failure_offset_s++;
+ for (i = ELEMENT_UNLOAD_START;
+ i <= ELEMENT_UNLOAD_END;
+ i++)
+ {
+ score = element_unload_score (robot_pos , i);
+ if (best == 0xff || best_score < score)
+ {
+ best = i;
+ best_score = score;
+ }
+ }
+ } while (best_score == -1 && retry++ < 10);
+ return best;
+}
+
+int32_t
+element_score (position_t robot_pos, uint8_t element_id)
+{
+ int32_t score = 0;
+ assert (element_id < UTILS_COUNT (element_table));
+ element_t e = element_get (element_id);
+
+ if (e.attr & ELEMENT_SAFE)
+ return -1;
+
+ if ((e.attr & ELEMENT_CENTER) &&
+ ((team_color == TEAM_COLOR_LEFT && (e.attr & ELEMENT_LEFT)) ||
+ (team_color == TEAM_COLOR_RIGHT && (e.attr & ELEMENT_RIGHT))))
+ return -1;
+
+ if (e.type == ELEMENT_NONE &&
+ ((e.attr & ELEMENT_INTERSEC) ||(e.attr & ELEMENT_GREEN)))
+ return -1;
+
+ /* Failed element. */
+ if (e.failure_until_s
+ && e.failure_until_s + failure_offset_s < (int) (chrono_remaining_time () / 1000))
+ return -1;
+
+ if (e.type == ELEMENT_KING)
+ score += ELEMENT_KING_SCORE;
+ else if (e.type == ELEMENT_QUEEN)
+ score += ELEMENT_QUEEN_SCORE;
+ else if (e.type == ELEMENT_PAWN)
+ score += ELEMENT_PAWN;
+ else if (e.type == ELEMENT_ANY)
+ score += ELEMENT_ANY_SCORE;
+ if (e.type & ELEMENT_NONE)
+ score /= 2;
+
+ /* Add score modifier. */
+ score += e.bonus_load * ELEMENT_BONUS_COEFF;
+
+ /* We are sure of this element. */
+ if (!(e.type & ELEMENT_NONE) &&
+ (e.attr == ELEMENT_INTERSEC || e.attr == ELEMENT_CENTER) &&
+ element_id != ELEMENT_CENTRAL_PAWN)
+ score += score / 4;
+
+ /* Distance from the robot. */
+ vect_t v = e.pos;
+ int32_t dr = distance_point_point (&v, &robot_pos.v);
+ score += (4242 - dr);
+
+ /* Alignment with the robot. */
+ if (dr > 100)
+ {
+ vect_t vr = v;
+ vect_sub (&vr, &robot_pos.v);
+ vect_t u;
+ uint16_t a;
+ if (logistic_global.collect_direction == DIRECTION_FORWARD)
+ a = robot_pos.a;
+ else
+ a = robot_pos.a + G_ANGLE_UF016_DEG (180);
+ vect_from_polar_uf016 (&u, 100, a);
+ int32_t dp = vect_dot_product (&u, &vr);
+ int32_t align = dp / dr;
+ score += align;
+ }
+
+ return score;
+}
+
+uint32_t
+element_proba (uint8_t element_id)
+{
+ assert (element_id < UTILS_COUNT (element_table));
+ element_t e = element_get (element_id);
+ uint32_t p_t = chrono_remaining_time () * 500 / CHRONO_MATCH_DURATION_MS;
+ uint8_t p_pos;
+ int32_t out = 0;
+
+ /* Intersections. */
+ if (e.attr & ELEMENT_INTERSEC)
+ {
+ /* Element on our side ? */
+ if ((team_color == TEAM_COLOR_LEFT && (e.attr & ELEMENT_LEFT)) ||
+ (team_color == TEAM_COLOR_RIGHT && (e.attr & ELEMENT_RIGHT)))
+ {
+ p_pos = 20 - element_id / 2;
+ out = p_pos * p_t;
+ }
+ /* Element on the other side ? */
+ else
+ {
+ p_pos = element_id / 2 + 1;
+ out = p_pos * p_t;
+ }
+ }
+ /* Green zone. */
+ else if (e.attr & ELEMENT_GREEN)
+ {
+ /* In our side. */
+ if ((team_color == TEAM_COLOR_LEFT && (e.attr & ELEMENT_LEFT)) ||
+ (team_color == TEAM_COLOR_RIGHT && (e.attr & ELEMENT_RIGHT)))
+ {
+ p_pos = 5 - ((element_id - ELEMENT_GREEN_START) / 2);
+ out = p_t * p_pos;
+
+ }
+ /* Other side. */
+ else
+ {
+ p_pos = (element_id - ELEMENT_GREEN_START) / 2 + 1;
+ out = p_t * p_pos;
+ }
+
+ }
+ /* Central pawn */
+ else if (e.type == ELEMENT_CENTRAL_PAWN)
+ out = p_t;
+ /* Centre of squares. */
+ else if (e.attr & ELEMENT_CENTER)
+ {
+ /* In our side. */
+ if ((team_color == TEAM_COLOR_LEFT && (e.attr & ELEMENT_LEFT)) ||
+ (team_color == TEAM_COLOR_RIGHT && (e.attr & ELEMENT_RIGHT)))
+ out = 0;
+ /* Other side. */
+ else
+ {
+ p_pos = (element_id - ELEMENT_UNLOAD_START) / 2 + 1;
+ out = (1000 - p_t) * p_pos;
+ }
+
+ }
+ else
+ out = 0;
+ return out;
+}
+
+uint8_t
+element_best (position_t robot_pos)
+{
+ uint8_t i;
+ uint8_t best = 0xff;
+ int32_t score = 0, best_score = 0;
+ uint8_t retry = 0;
+ do
+ {
+ if (retry && failure_offset_s != 255)
+ failure_offset_s++;
+ for (i = 0; i < UTILS_COUNT (element_table); i++)
+ {
+ score = element_score (robot_pos ,i);
+ if (best == 0xff || best_score < score)
+ {
+ best = i;
+ best_score = score;
+ }
+ }
+ } while (best_score == -1 && retry++ < 10);
+ return best;
+}
+
+void
+element_not_here (uint8_t element_id)
+{
+ assert (element_id < UTILS_COUNT (element_table));
+ element_t e = element_get (element_id);
+ e.type = ELEMENT_NONE;
+ element_set (element_id, e);
+
+ /* Invalidate the same element to the other side. */
+ if (e.attr & ELEMENT_INTERSEC)
+ {
+ uint8_t other_side_id = element_opposed (element_id);
+ element_t other_side = element_get (other_side_id);
+ other_side.type = ELEMENT_NONE;
+ element_set (other_side_id, other_side);
+ }
+
+ /* If the element is on an intersection, try to guess last elements. */
+ element_intersec_symetric (element_id, ELEMENT_NONE);
+}
+
+inline void
+element_intersec_symetric (uint8_t element_id, uint8_t element_type)
+{
+ static uint8_t element_columns[2][5] =
+ {
+ {
+ ELEMENT_NONE | ELEMENT_PAWN,
+ ELEMENT_NONE | ELEMENT_PAWN,
+ ELEMENT_NONE | ELEMENT_PAWN,
+ ELEMENT_NONE | ELEMENT_PAWN,
+ ELEMENT_NONE | ELEMENT_PAWN
+ },
+ {
+ ELEMENT_NONE | ELEMENT_PAWN,
+ ELEMENT_NONE | ELEMENT_PAWN,
+ ELEMENT_NONE | ELEMENT_PAWN,
+ ELEMENT_NONE | ELEMENT_PAWN,
+ ELEMENT_NONE | ELEMENT_PAWN
+ }
+ };
+ element_t e = element_get (element_id);
+
+ /* if the element is on an intersection, try to guess last elements. */
+ if ((e.attr & ELEMENT_INTERSEC) && !(e.attr & ELEMENT_CENTER))
+ {
+ uint8_t cpt_none = 0;
+ uint8_t cpt_pawn = 0;
+ uint8_t col;
+ uint8_t i;
+ uint8_t type = 0;
+
+ if (element_id % 4 <= 1)
+ col = 0;
+ else
+ col = 1;
+
+ /* Nothing to see. */
+ if (element_columns[col][4] != (ELEMENT_NONE | ELEMENT_PAWN))
+ return;
+
+ /* Count. */
+ for (i = 0; i < 5; i++)
+ {
+ if (element_columns[col][i] == ELEMENT_PAWN || element_type == ELEMENT_PAWN)
+ cpt_pawn++;
+ if (element_columns[col][i] == ELEMENT_NONE || element_type == ELEMENT_NONE)
+ cpt_none++;
+ if (element_columns[col][i] == (ELEMENT_NONE | ELEMENT_PAWN))
+ {
+ element_columns[col][i] = element_type;
+ break;
+ }
+ }
+
+ /* With which element are we going to fill the rest ? */
+ if (cpt_pawn == 2)
+ type = ELEMENT_NONE;
+ else if (cpt_none == 3)
+ type = ELEMENT_PAWN;
+ else
+ return;
+
+ for (i = 0; i < 5; i++)
+ if (element_columns[col][i] == (ELEMENT_NONE | ELEMENT_PAWN))
+ element_columns[col][i] = type;
+
+ /* Complete if possible. */
+ for (i = ELEMENT_INTERSEC_START; i < ELEMENT_INTERSEC_END; i++)
+ {
+ uint8_t col_i;
+ if (i % 4 <= 1)
+ col_i = 0;
+ else
+ col_i = 1;
+ if (col_i == col)
+ {
+ element_t el = element_get (i);
+ element_t sym = element_get (element_opposed (i));
+ if (el.type == (ELEMENT_NONE | ELEMENT_PAWN))
+ {
+ el.type = type;
+ element_set (i, el);
+ /* Set opposed. */
+ if (sym.type == (ELEMENT_NONE | ELEMENT_PAWN))
+ {
+ sym.type = type;
+ element_set (element_opposed (i), sym);
+ }
+ }
+ }
+ }
+ }
+}
+
+void
+element_taken (uint8_t element_id, uint8_t element_type)
+{
+ assert (element_id < UTILS_COUNT (element_table));
+ static uint8_t pawn_c = 3, queen_c = 1, king_c = 1, any_nb = 5;
+ uint8_t other_side_id, other_side_id_element = 0;
+
+ if (element_type != ELEMENT_PAWN && element_type != ELEMENT_QUEEN && element_type != ELEMENT_KING)
+ return;
+
+ /* Set element. */
+ element_t e = element_get (element_id);
+ e.type = ELEMENT_NONE;
+ element_set (element_id, e);
+
+ /* Deduce symmetric position. */
+ if ((e.attr & ELEMENT_INTERSEC) || (e.attr & ELEMENT_GREEN))
+ {
+ other_side_id_element = element_opposed (element_id);
+ element_t other_side = element_get (other_side_id_element);
+ if (other_side.type != ELEMENT_NONE)
+ {
+ other_side.type = element_type;
+ element_set (other_side_id_element, other_side);
+ }
+ }
+
+ /* If the element is on an intersection, try to guess last elements. */
+ element_intersec_symetric (element_id, element_type);
+
+ /* If the element is in the green zone, try to guess last elements. */
+ if ((e.attr & ELEMENT_GREEN) && any_nb > 0)
+ {
+ uint8_t i;
+ if (element_type == ELEMENT_PAWN)
+ pawn_c--;
+ else if (element_type == ELEMENT_QUEEN)
+ queen_c--;
+ else if (element_type == ELEMENT_KING)
+ king_c--;
+ any_nb--;
+
+ /* If there is something to guess. */
+ if (any_nb <= 3)
+ {
+ /* All others are pawns. */
+ if (!queen_c && !king_c)
+ {
+ for (i = ELEMENT_GREEN_START; i <= ELEMENT_GREEN_END; i++)
+ {
+ element_t el = element_get (i);
+ if (el.type == ELEMENT_ANY)
+ {
+ el.type = ELEMENT_PAWN;
+ element_set (i, el);
+ any_nb--;
+ /* Set opposed side. */
+ other_side_id = element_opposed (element_id);
+ element_t other_side = element_get (other_side_id);
+ if (other_side.type != ELEMENT_NONE &&
+ other_side_id != other_side_id_element)
+ {
+ other_side.type = ELEMENT_PAWN;
+ element_set (other_side_id, other_side);
+ }
+ }
+ }
+ }
+ /* All others are unidentified heads */
+ else if (pawn_c == 0 && any_nb == 2)
+ {
+ for (i = ELEMENT_GREEN_START; i <= ELEMENT_GREEN_END; i++)
+ {
+ element_t el = element_get (i);
+ if (el.type == ELEMENT_ANY)
+ {
+ el.type = ELEMENT_HEAD;
+ element_set (i, el);
+ /* Set opposed side. */
+ other_side_id = element_opposed (element_id);
+ element_t other_side = element_get (other_side_id);
+ if (other_side.type != ELEMENT_NONE &&
+ other_side_id != other_side_id_element)
+ {
+ other_side.type = ELEMENT_HEAD;
+ element_set (other_side_id, other_side);
+ }
+ }
+ }
+ }
+ /* Last element. */
+ if (any_nb == 1)
+ {
+ uint8_t last_type;
+ if (pawn_c == 1) last_type = ELEMENT_PAWN;
+ else if (queen_c == 1) last_type = ELEMENT_QUEEN;
+ else last_type = ELEMENT_KING;
+ for (i = ELEMENT_GREEN_START; i <= ELEMENT_GREEN_END; i++)
+ {
+ element_t el = element_get (i);
+ if (el.type == ELEMENT_ANY || el.type == ELEMENT_HEAD)
+ {
+ el.type = last_type;
+ element_set (i, el);
+ any_nb--;
+ /* Set opposed side. */
+ other_side_id = element_opposed (i);
+ element_t other_side = element_get (other_side_id);
+ if (other_side.type != ELEMENT_NONE &&
+ other_side_id != other_side_id_element)
+ {
+ other_side.type = last_type;
+ element_set (other_side_id, other_side);
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+void
+element_down (uint8_t element_id, uint8_t element_type)
+{
+ uint8_t i;
+ element_t e = element_get (element_id);
+ e.type = element_type;
+ element_set (element_id, e);
+
+ /* Malus elements near this element. */
+ for (i = ELEMENT_INTERSEC_START; i <= ELEMENT_INTERSEC_END; i++)
+ {
+ element_t ie = element_get (i);
+ if (UTILS_ABS (e.pos.x - ie.pos.x)
+ < BOT_ELEMENT_RADIUS + BOT_SIZE_SIDE + 20
+ && UTILS_ABS (e.pos.y - ie.pos.y)
+ < BOT_ELEMENT_RADIUS + BOT_SIZE_SIDE + 20)
+ {
+ ie.bonus_load = -50;
+ element_set (i, ie);
+ }
+ }
+}
+
+void
+element_failure (uint8_t element_id)
+{
+ element_t e = element_get (element_id);
+ e.failure_until_s = chrono_remaining_time () / 1000 - 7;
+ element_set (element_id, e);
+}
+
+uint8_t
+element_nearest_element_id (position_t robot_pos)
+{
+ uint8_t i;
+ uint8_t id = 0;
+ int32_t distance = 4242;
+ element_t e;
+ for (i = 0; i < UTILS_COUNT (element_table); i++)
+ {
+ e = element_get (i);
+ vect_t v = e.pos;
+ int32_t dr = distance_point_point (&v, &robot_pos.v);
+ if (dr < distance)
+ {
+ id = i;
+ distance = dr;
+ }
+ }
+ return id;
+}
+
+uint8_t
+element_opposed (uint8_t element_id)
+{
+ uint8_t op = 0xff;
+ element_t e = element_get (element_id);
+ if ((e.attr & ELEMENT_GREEN) ||(e.attr & ELEMENT_INTERSEC))
+ {
+ if (e.attr & ELEMENT_LEFT)
+ op = element_id + 1;
+ else
+ op = element_id - 1;
+ }
+ return op;
+}
+
+vect_t
+element_get_pos (uint8_t element_id)
+{
+ element_t e = element_get (element_id);
+ vect_t pos;
+ pos = e.pos;
+ if (e.attr == (ELEMENT_GREEN |ELEMENT_RIGHT))
+ {
+ /* To the right. */
+ pos.x = PG_WIDTH - BOT_GREEN_ELEMENT_DISTANCE_MM;
+ }
+ if (e.attr == (ELEMENT_GREEN |ELEMENT_LEFT))
+ {
+ /* To the left. */
+ pos.x = BOT_GREEN_ELEMENT_DISTANCE_MM;
+ }
+ return pos;
+}
+
+uint8_t
+element_blocking (uint8_t element_id, uint8_t escape)
+{
+ element_t e = element_get (element_id);
+ return e.type == ELEMENT_TOWER || (!escape && e.type == ELEMENT_PAWN);
+}
+
+uint8_t
+element_blocking_path (vect_t a, vect_t b, int16_t ab, uint8_t escape)
+{
+ uint8_t i;
+ element_t e;
+ /* Only unload area are blocking. */
+ for (i = ELEMENT_UNLOAD_START; i <= ELEMENT_UNLOAD_END; i++)
+ {
+ e = element_get (i);
+ if (e.type == ELEMENT_TOWER || (!escape && e.type == ELEMENT_PAWN))
+ {
+ /* Compute square of distance to obstacle, see
+ * distance_segment_point in modules/math/geometry for the method
+ * explanation. */
+ int32_t absq = (int32_t) ab * ab;
+ vect_t vab = b; vect_sub (&vab, &a);
+ vect_t vao = e.pos; vect_sub (&vao, &a);
+ int32_t dp = vect_dot_product (&vab, &vao);
+ int32_t dsq;
+ if (dp < 0)
+ {
+ dsq = vect_dot_product (&vao, &vao);
+ }
+ else if (dp > absq)
+ {
+ vect_t vbo = e.pos; vect_sub (&vbo, &b);
+ dsq = vect_dot_product (&vbo, &vbo);
+ }
+ else
+ {
+ vect_t vabn = vab; vect_normal (&vabn);
+ dsq = vect_dot_product (&vabn, &vao) / ab;
+ dsq *= dsq;
+ }
+ /* Compare with square of authorised distance. */
+ if (dsq < (int32_t) (BOT_ELEMENT_RADIUS + BOT_SIZE_SIDE + 20) *
+ (BOT_ELEMENT_RADIUS + BOT_SIZE_SIDE + 20))
+ return 1;
+ }
+ }
+ return 0;
+}
+
+void
+element_i_like_green ()
+{
+ /* Negative bonus for the other green zone at start. */
+ /* Do not touch last green emplacement. */
+ int i;
+ for (i = ELEMENT_GREEN_START; i <= ELEMENT_GREEN_END - 2; i++)
+ {
+ element_t e = element_get (i);
+ if (!((team_color == TEAM_COLOR_LEFT && (e.attr & ELEMENT_LEFT)) ||
+ (team_color == TEAM_COLOR_RIGHT && (e.attr & ELEMENT_RIGHT)))
+ && e.bonus_load < 0
+ && (e.type == ELEMENT_KING || e.type == ELEMENT_QUEEN))
+ {
+ e.bonus_load = 40;
+ element_set (i, e);
+ }
+ }
+}
+
+void
+element_no_more_green (void)
+{
+ uint8_t i;
+ /* Remove our green zone score at first unload. */
+ for (i = ELEMENT_GREEN_START; i <= ELEMENT_GREEN_END - 2; i++)
+ {
+ element_t e = element_get (i);
+ if ((team_color == TEAM_COLOR_LEFT && (e.attr & ELEMENT_LEFT)) ||
+ (team_color == TEAM_COLOR_RIGHT && (e.attr & ELEMENT_RIGHT)))
+ {
+ e.bonus_load = 0;
+ element_set (i, e);
+ }
+ }
+}
diff --git a/digital/io-hub/src/robospierre/element.h b/digital/io-hub/src/robospierre/element.h
new file mode 100644
index 00000000..41985e95
--- /dev/null
+++ b/digital/io-hub/src/robospierre/element.h
@@ -0,0 +1,213 @@
+#ifndef element_h
+#define element_h
+/* element.h */
+/* robospierre - Eurobot 2011 AI. {{{
+ *
+ * Copyright (C) 2011 Nicolas Schodet, Jérôme Jutteau
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * 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 "defs.h"
+
+/** None. */
+#define ELEMENT_NONE 1
+/** A pawn, not a head. */
+#define ELEMENT_PAWN 2
+/** Queen pawn, used for statistic update of table data. */
+#define ELEMENT_QUEEN 4
+/** King pawn, used for statistic update of table data. */
+#define ELEMENT_KING 8
+/** Any head, queen or king. */
+#define ELEMENT_HEAD (ELEMENT_QUEEN |ELEMENT_KING)
+/** Any element, pawn, queen, or king. */
+#define ELEMENT_ANY (ELEMENT_HEAD |ELEMENT_PAWN)
+/** Tower types. */
+#define ELEMENT_TOWER_1_QUEEN 16
+#define ELEMENT_TOWER_2_QUEEN 32
+#define ELEMENT_TOWER_1_KING 64
+#define ELEMENT_TOWER_2_KING 128
+
+#define ELEMENT_TOWER (ELEMENT_TOWER_1_QUEEN | \
+ ELEMENT_TOWER_2_QUEEN | \
+ ELEMENT_TOWER_1_KING | \
+ ELEMENT_TOWER_2_KING)
+
+/** Return non zero if element is a head, not a pawn. */
+#define ELEMENT_IS_HEAD(e) ((e) && !((e) & ELEMENT_PAWN))
+
+/** Return non zero if element may be a head. */
+#define ELEMENT_CAN_BE_HEAD(e) ((e) & ELEMENT_HEAD)
+
+#define ELEMENT_PAWN_SCORE 10
+#define ELEMENT_ANY_SCORE 15
+#define ELEMENT_QUEEN_SCORE 20 * 30
+#define ELEMENT_KING_SCORE 30 * 30
+
+/** Emplacement attributes bits. */
+#define ELEMENT_BONUS 1
+/**
+ * Two meanings:
+ * - When it is on an intersection or in the green zone, this mean that it is positioned on the
+ * left size of the table.
+ * - When it is located on an color, this corresponds to the red color.
+ */
+#define ELEMENT_LEFT 2
+/**
+ * Two meanings:
+ * - When it is on an intersection or in the green zone, this mean that it is positioned on the
+ * left right of the table.
+ * - When it is located on an color, this corresponds to the blue color.
+ */
+#define ELEMENT_RIGHT 4
+#define ELEMENT_SAFE 8
+#define ELEMENT_GREEN 16
+#define ELEMENT_INTERSEC 64
+/** Center of a square or central element. */
+#define ELEMENT_CENTER 128
+
+struct element_t
+{
+ /** May have several types if unknown (pawn, king, queen). */
+ uint8_t type;
+ /** Element position. */
+ vect_t pos;
+ /** Emplacement attributes. */
+ uint8_t attr;
+ /** Bonus coefficient (or Mallus if negative) for load scores. */
+ int8_t bonus_load;
+ /** Bonus coefficient (or Mallus if negative) for unload scores. */
+ int8_t bonus_unload;
+ /** Failure expiration date, can not take this element until chrono is
+ * lower than this date in seconds. */
+ int8_t failure_until_s;
+
+};
+typedef struct element_t element_t;
+
+/* Elements range, see element table content. */
+#define ELEMENT_INTERSEC_START 0
+#define ELEMENT_INTERSEC_END 19
+#define ELEMENT_CENTRAL_PAWN 20
+#define ELEMENT_GREEN_START 21
+#define ELEMENT_GREEN_END 30
+#define ELEMENT_UNLOAD_START 31
+#define ELEMENT_UNLOAD_END 66
+
+#define ELEMENT_BONUS_COEFF 100
+
+/** Elements on table. */
+extern struct element_t element_table[];
+
+/** Initialize elements. */
+void
+element_init (void);
+
+/** Gives the score of an element considering it as an unload zone. */
+int32_t
+element_unload_score (position_t robot_pos, uint8_t element_id);
+
+/** Gives best unload. */
+uint8_t
+element_unload_best (position_t robot_pos);
+
+/** Gives score of an element. */
+int32_t
+element_score (position_t robot_pos, uint8_t element_id);
+
+/** Return a probability of an element to be here.
+ * This depends of the remaining time.
+ * Returns a probability from 0 (element may really not be here)
+ * to maximal value (element may be here).
+ */
+uint32_t
+element_proba (uint8_t element_id);
+
+/** Return the best element to pick. */
+uint8_t
+element_best (position_t robot_pos);
+
+/** Function to call when we see an element is not here. */
+void
+element_not_here (uint8_t element_id);
+
+/** Call this function when an element is taken. */
+void
+element_taken (uint8_t element_id, uint8_t element_type);
+
+/** Call this function when the robot put down an element. */
+void
+element_down (uint8_t element_id, uint8_t element_type);
+
+/** Call this function when taking an element failled. */
+void
+element_failure (uint8_t element_id);
+
+/** Gives the nearest element from a position. */
+uint8_t
+element_give_position (position_t pos);
+
+/** Give the opposed element. */
+uint8_t
+element_opposed (uint8_t element_id);
+
+/** Return 1 if the element is in our side, 0 otherwise. */
+int
+element_our_side (uint8_t element_id);
+
+inline void
+element_intersec_symetric (uint8_t element_id, uint8_t element_type);
+
+uint8_t
+element_nearest_element_id (position_t robot_pos);
+
+/**
+ Give the position where the robot need to be placed to get an element.
+ */
+vect_t
+element_get_pos (uint8_t element_id);
+
+extern inline element_t
+element_get (uint8_t element_id)
+{
+ return element_table[element_id];
+}
+
+/** Return whether an element is blocking robot. */
+uint8_t
+element_blocking (uint8_t element_id, uint8_t blocking);
+
+/** Return whether an element is blocking a line segment.
+ * - a: line segment first point.
+ * - b: line segment second point.
+ * - ab: line segment length.
+ * - escape: trying to escape, be a little bit more permissive.
+ * - returns: 1 if the path should not be used. */
+uint8_t
+element_blocking_path (vect_t a, vect_t b, int16_t ab, uint8_t escape);
+
+/** Ask to adjust score for the opposed green zone. */
+void
+element_i_like_green ();
+
+/** Do not go to our green zone any more. */
+void
+element_no_more_green (void);
+
+#endif /* element_h */
diff --git a/digital/io-hub/src/robospierre/init_defs.h b/digital/io-hub/src/robospierre/init_defs.h
new file mode 100644
index 00000000..6ce6eaae
--- /dev/null
+++ b/digital/io-hub/src/robospierre/init_defs.h
@@ -0,0 +1,50 @@
+#ifndef init_defs_h
+#define init_defs_h
+/* init_defs.h */
+/* robospierre - Eurobot 2011 AI. {{{
+ *
+ * Copyright (C) 2011 Nicolas Schodet
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * 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 "playground.h"
+#include "bot.h"
+
+/** Parameters to push the first wall. */
+#define INIT_FIRST_WALL_PUSH \
+ 0, PG_X (BOT_FRONT_CONTACT_DIST_MM), 200, \
+ PG_A_DEG (180 + BOT_FRONT_CONTACT_ANGLE_ERROR_DEG)
+/** Parameters to go away from the first wall. */
+#define INIT_FIRST_WALL_AWAY -500
+/** Parameter to face the second wall. */
+#define INIT_SECOND_WALL_ANGLE PG_A_DEG (90)
+/** Parameters to push the second wall. */
+#define INIT_SECOND_WALL_PUSH \
+ 0, -1, PG_Y (PG_LENGTH - BOT_FRONT_CONTACT_DIST_MM), -1
+/** Parameters to go away from the second wall. */
+#define INIT_SECOND_WALL_AWAY -(200 - BOT_FRONT_CONTACT_DIST_MM)
+/** Parameter to face the start position. */
+#define INIT_START_POSITION_ANGLE PG_A_DEG (0)
+/** Start position. */
+#define INIT_START_POSITION \
+ PG_X (200), PG_Y (PG_LENGTH - 200), PG_A_DEG (0), ASSERV_BACKWARD
+
+#endif /* init_defs_h */
diff --git a/digital/io-hub/src/robospierre/logistic.c b/digital/io-hub/src/robospierre/logistic.c
new file mode 100644
index 00000000..82f5a4fa
--- /dev/null
+++ b/digital/io-hub/src/robospierre/logistic.c
@@ -0,0 +1,622 @@
+/* logistic.c */
+/* robospierre - Eurobot 2011 AI. {{{
+ *
+ * Copyright (C) 2011 Nicolas Schodet
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * 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 "common.h"
+#include "logistic.h"
+
+#include "clamp.h"
+#include "defs.h"
+
+#include "contact.h"
+#include "io.h"
+
+#include "debug.host.h"
+
+/** Handle elements stored inside the robot. */
+
+/** Global context. */
+struct logistic_t logistic_global;
+#define ctx logistic_global
+
+inline void
+logistic_debug_dump (void)
+{
+#ifdef HOST
+ uint8_t i;
+ static const char *names[][CLAMP_SLOT_NB] = {
+ { "f1", "f2", "f3", "b1", "b2", "b3", "s1" },
+ { "F1", "F2", "F3", "B1", "B2", "B3", "S1" }
+ };
+ static const char *names_dir[] = { "--", "<-", "->" };
+ DPRINTF ("%s", names_dir[ctx.collect_direction]);
+ for (i = 0; i < CLAMP_SLOT_NB; i++)
+ {
+ DPRINTF (" %s", ctx.slots[i]
+ ? names[ELEMENT_IS_HEAD (ctx.slots[i]) ? 1 : 0][i]
+ : "__");
+ }
+ if (ctx.moving_from != CLAMP_SLOT_NB)
+ {
+ DPRINTF (" %s => %s", names[0][ctx.moving_from], names[0][ctx.moving_to]);
+ }
+ DPRINTF ("\n");
+ DPRINTF ("construct_possible: %u\n", ctx.construct_possible);
+ DPRINTF ("prepare: %u\n", ctx.prepare);
+ DPRINTF ("ready: %u\n", ctx.ready);
+ DPRINTF ("need_prepare: %u\n", ctx.need_prepare);
+#endif
+}
+
+/** Return 1 if location corresponds to element. */
+inline uint8_t
+logistic_case_test (uint8_t loc, uint8_t e)
+{
+ if (e == LOG_a && ctx.slots[loc])
+ return 1;
+ if (e == LOG__)
+ return 1;
+ if ((e == LOG_e || e == LOG_D) && !ctx.slots[loc])
+ return 1;
+ if ((e == LOG_P || e == LOG_p) && ctx.slots[loc] &&
+ !ELEMENT_IS_HEAD (ctx.slots[loc]))
+ return 1;
+ if ((e == LOG_H || e == LOG_h) && ELEMENT_IS_HEAD (ctx.slots[loc]))
+ return 1;
+ if (e == LOG_t && ctx.slots[loc] == ELEMENT_TOWER)
+ return 1;
+ return 0;
+}
+
+static uint8_t
+logistic_case (uint8_t e1, uint8_t e2, uint8_t e3, uint8_t e4, uint8_t e5,
+ uint8_t e6, uint8_t e7, uint8_t new_dir, uint8_t ready,
+ uint8_t check_symetric)
+{
+ /* Define direction bay and opposed bay. */
+ uint8_t dir_bay, opp_bay;
+ if (ctx.collect_direction == DIRECTION_FORWARD)
+ {
+ dir_bay = CLAMP_SLOT_FRONT_BOTTOM;
+ opp_bay = CLAMP_SLOT_BACK_BOTTOM;
+ }
+ else
+ {
+ dir_bay = CLAMP_SLOT_BACK_BOTTOM;
+ opp_bay = CLAMP_SLOT_FRONT_BOTTOM;
+ }
+ /*if (check_symetric)
+ {
+ uint8_t tmp = dir_bay;
+ dir_bay = opp_bay;
+ opp_bay = tmp;
+ }*/
+
+ /* Emplacement of elements. */
+ uint8_t
+ e1_loc = dir_bay + 2,
+ e3_loc = dir_bay + 1,
+ e6_loc = dir_bay,
+ e4_loc = CLAMP_SLOT_SIDE,
+ e2_loc = opp_bay + 2,
+ e5_loc = opp_bay + 1,
+ e7_loc = opp_bay;
+
+ /* Check elements are here. */
+ if (!(logistic_case_test (e1_loc, e1) &&
+ logistic_case_test (e2_loc, e2) &&
+ logistic_case_test (e3_loc, e3) &&
+ logistic_case_test (e4_loc, e4) &&
+ logistic_case_test (e5_loc, e5) &&
+ logistic_case_test (e6_loc, e6) &&
+ logistic_case_test (e7_loc, e7)))
+ {
+ /* Check mirror. */
+ /*if (!check_symetric)
+ logistic_case (e1, e2, e3, e4, e5, e6, e7, new_dir, ready, 1);*/
+ return 0;
+ }
+
+ /* Find source/destination if we have to make a move. */
+ /* Find source. */
+ uint8_t src = CLAMP_SLOT_NB, dst = CLAMP_SLOT_NB;
+ if (e1 == LOG_P ||e1 == LOG_H)
+ src = e1_loc;
+ else if (e3 == LOG_P ||e3 == LOG_H)
+ src = e3_loc;
+ else if (e6 == LOG_P ||e6 == LOG_H)
+ src = e6_loc;
+ else if (e4 == LOG_P ||e4 == LOG_H)
+ src = e4_loc;
+ else if (e2 == LOG_P ||e2 == LOG_H)
+ src = e2_loc;
+ else if (e5 == LOG_P ||e5 == LOG_H)
+ src = e5_loc;
+ else if (e7 == LOG_P ||e7 == LOG_H)
+ src = e7_loc;
+
+ /* Find destination. */
+ if (e1 == LOG_D)
+ dst = e1_loc;
+ else if (e3 == LOG_D)
+ dst = e3_loc;
+ else if (e6 == LOG_D)
+ dst = e6_loc;
+ else if (e4 == LOG_D)
+ dst = e4_loc;
+ else if (e2 == LOG_D)
+ dst = e2_loc;
+ else if (e5 == LOG_D)
+ dst = e5_loc;
+ else if (e7 == LOG_D)
+ dst = e7_loc;
+
+ /* We are making a move. */
+ if (src != CLAMP_SLOT_NB && dst != CLAMP_SLOT_NB)
+ {
+ if (ctx.slots[src] && !ctx.slots[dst])
+ {
+ ctx.moving_from = src;
+ ctx.moving_to = dst;
+ ctx.ready = 0;
+ }
+ }
+
+ /* Set collect direction. */
+ /* LEFT means we keep the same side, RIGHT means we put the opposed side. */
+ if (new_dir == LOG_DIR_RIGHT)
+ {
+ if (ctx.collect_direction == DIRECTION_FORWARD)
+ ctx.collect_direction = DIRECTION_BACKWARD;
+ else
+ ctx.collect_direction = DIRECTION_FORWARD;
+ }
+
+ /* Don't touch clamp's idle position if broken. */
+ if (ctx.prepare != 3)
+ {
+ /* Set clamp position idle. */
+ if (ctx.collect_direction == DIRECTION_FORWARD)
+ ctx.clamp_pos_idle = CLAMP_SLOT_FRONT_MIDDLE;
+ else
+ ctx.clamp_pos_idle = CLAMP_SLOT_BACK_MIDDLE;
+ }
+ /* Set ready */
+ ctx.ready = ready;
+ return 1;
+}
+
+static void
+logistic_update_construct_possible ()
+{
+ uint8_t pawn = 0, head = 0, i;
+ /* Check for tower. */
+ if (ctx.slots[CLAMP_SLOT_FRONT_BOTTOM] == ELEMENT_TOWER ||
+ ctx.slots[CLAMP_SLOT_BACK_BOTTOM] == ELEMENT_TOWER)
+ {
+ ctx.construct_possible = 1;
+ return;
+ }
+
+ for (i = CLAMP_SLOT_FRONT_BOTTOM; i < CLAMP_SLOT_NB; i++)
+ {
+ if (ELEMENT_IS_HEAD (ctx.slots[i]))
+ head++;
+ else if (ctx.slots[i])
+ pawn++;
+ if (head >= 1 && pawn >= 2)
+ {
+ ctx.construct_possible = 1;
+ return;
+ }
+ }
+ if (pawn || head)
+ ctx.construct_possible = 2;
+ else
+ ctx.construct_possible = 0;
+}
+
+static void
+logistic_update_need_prepare ()
+{
+ uint8_t i, head = 0, pawn = 0;
+ for (i = CLAMP_SLOT_FRONT_BOTTOM; i < CLAMP_SLOT_NB; i++)
+ {
+ if (ELEMENT_IS_HEAD (ctx.slots[i]))
+ head++;
+ else if (ctx.slots[i])
+ pawn++;
+ }
+ if ((head == 1 && pawn == 3) ||
+ head == 2 || pawn >= 4)
+ ctx.need_prepare = 1;
+ else
+ ctx.need_prepare = 0;
+
+ /* Define direction bay and opposed bay. */
+ uint8_t dir_bay, opp_bay;
+ if (ctx.collect_direction == DIRECTION_FORWARD)
+ {
+ dir_bay = CLAMP_SLOT_FRONT_BOTTOM;
+ opp_bay = CLAMP_SLOT_BACK_BOTTOM;
+ }
+ else
+ {
+ dir_bay = CLAMP_SLOT_BACK_BOTTOM;
+ opp_bay = CLAMP_SLOT_FRONT_BOTTOM;
+ }
+ /* If a head appear at the back (?) */
+ if (ELEMENT_IS_HEAD (ctx.slots[opp_bay]))
+ ctx.need_prepare = 1;
+
+ /* We founded a tower ! */
+ if (ctx.slots[CLAMP_SLOT_FRONT_BOTTOM] == ELEMENT_TOWER ||
+ ctx.slots[CLAMP_SLOT_FRONT_BOTTOM] == ELEMENT_TOWER)
+ ctx.need_prepare = 1;
+}
+
+static void
+logisitic_make_broken ()
+{
+ LOGISTIC_CASE (_, _,
+ _, _, _,
+ a, _, RIGHT, 1);
+
+ LOGISTIC_CASE (_, _,
+ _, _, _,
+ _, a, LEFT, 1);
+}
+
+static void
+logistic_make_tower ()
+{
+ LOGISTIC_CASE (_, _,
+ _, _, _,
+ _, t, LEFT, 1);
+
+ LOGISTIC_CASE (_, _,
+ _, _, _,
+ t, _, RIGHT, 1);
+
+ LOGISTIC_CASE (D, _,
+ e, _, _,
+ H, _, RIGHT, 0);
+
+ LOGISTIC_CASE (_, h,
+ _, _, p,
+ _, p, LEFT, 1);
+
+ LOGISTIC_CASE (P, h,
+ e, _, e,
+ _, D, LEFT, 0);
+
+ LOGISTIC_CASE (_, h,
+ e, _, e,
+ P, D, LEFT, 0);
+
+ LOGISTIC_CASE (_, h,
+ _, P, e,
+ _, D, LEFT, 0);
+
+ LOGISTIC_CASE (P, h,
+ e, _, D,
+ _, p, LEFT, 0);
+
+ LOGISTIC_CASE (_, h,
+ e, _, D,
+ P, p, LEFT, 0);
+
+ LOGISTIC_CASE (_, h,
+ _, P, D,
+ _, p, LEFT, 0);
+}
+
+static void
+logistic_make_unload ()
+{
+ /* Making a small tower. Move head when having pawn. */
+ LOGISTIC_CASE (D, _,
+ e, p, _,
+ H, _, RIGHT, 0);
+
+ LOGISTIC_CASE (D, p,
+ e, e, e,
+ H, _, RIGHT, 0);
+
+ LOGISTIC_CASE (D, _,
+ e, e, e,
+ H, p, RIGHT, 0);
+
+ /* Making a small tower. Move pawn under head. */
+ LOGISTIC_CASE (_, h,
+ _, P, e,
+ _, D, LEFT, 0);
+
+ LOGISTIC_CASE (P, h,
+ e, e, e,
+ _, D, LEFT, 0);
+
+ LOGISTIC_CASE (_, h,
+ e, e, e,
+ P, D, LEFT, 0);
+
+ /* Making a small tower. Finally move head on pawn. */
+ LOGISTIC_CASE (_, H,
+ _, _, D,
+ _, p, LEFT, 0);
+
+ LOGISTIC_CASE (_, _,
+ _, _, h,
+ _, p, LEFT, 1);
+
+ /* Having any element. */
+ LOGISTIC_CASE (_, _,
+ _, _, _,
+ _, a, LEFT, 1);
+
+ LOGISTIC_CASE (_, _,
+ _, _, _,
+ a, _, RIGHT, 1);
+
+ LOGISTIC_CASE (_, a,
+ _, _, e,
+ _, D, LEFT, 0);
+
+ LOGISTIC_CASE (a, _,
+ e, _, _,
+ D, _, RIGHT, 0);
+
+ LOGISTIC_CASE (_, _,
+ _, P, e,
+ _, D, LEFT, 0);
+
+ LOGISTIC_CASE (_, _,
+ e, P, _,
+ D, _, RIGHT, 0);
+}
+
+static void
+logisitic_make_switches ()
+{
+ LOGISTIC_CASE (_, P,
+ _, D, e,
+ _, _, LEFT, 0);
+
+ LOGISTIC_CASE (P, _,
+ e, D, _,
+ _, _, LEFT, 0);
+
+ LOGISTIC_CASE (_, _,
+ e, D, _,
+ P, _, LEFT, 0);
+
+ LOGISTIC_CASE (_, _,
+ _, D, e,
+ _, P, LEFT, 0);
+
+ LOGISTIC_CASE (_, D,
+ e, p, e,
+ P, _, LEFT, 0);
+
+ LOGISTIC_CASE (_, a,
+ e, p, e,
+ P, D, LEFT, 0);
+
+ LOGISTIC_CASE (D, _,
+ e, _, _,
+ H, _, RIGHT, 0);
+
+ LOGISTIC_CASE (h, P,
+ e, _, e,
+ D, _, RIGHT, 0);
+
+ LOGISTIC_CASE (h, e,
+ e, _, e,
+ D, P, RIGHT, 0);
+
+ LOGISTIC_CASE (P, h,
+ e, _, e,
+ _, D, LEFT, 0);
+
+ LOGISTIC_CASE (e, h,
+ e, _, e,
+ P, D, LEFT, 0);
+}
+
+void
+logistic_decision (void)
+{
+ /* Reset. */
+ ctx.moving_from = CLAMP_SLOT_NB;
+ ctx.moving_to = CLAMP_SLOT_NB;
+ ctx.construct_possible = 0;
+ ctx.ready = 0;
+ ctx.need_prepare = 0;
+
+ /* Update context. */
+ logistic_update_construct_possible ();
+ /* Update if a something is possible. */
+ logistic_update_need_prepare ();
+
+ /* Broken clamp. */
+ if (ctx.construct_possible && ctx.prepare == 3)
+ {
+ DPRINTF ("\nlogisitic_make_broken\n");
+ logisitic_make_broken ();
+ }
+ /* Prepare tower. */
+ else if (ctx.construct_possible == 1 && ctx.prepare != 0)
+ {
+
+ DPRINTF ("\nlogisitic_make_tower\n");
+ logistic_make_tower ();
+ }
+ /* Need to unload. */
+ else if (ctx.construct_possible == 2 && ctx.prepare == 2)
+ {
+ DPRINTF ("\nlogisitic_make_unload\n");
+ logistic_make_unload ();
+ }
+ /* Internal switches. */
+ else
+ {
+ DPRINTF ("\nlogisitic_make_switches\n");
+ logisitic_make_switches ();
+ }
+
+ logistic_debug_dump ();
+ return;
+}
+
+void
+logistic_init (void)
+{
+ uint8_t i;
+ for (i = 0; i < CLAMP_SLOT_NB; i++)
+ ctx.slots[i] = 0;
+ ctx.moving_from = ctx.moving_to = CLAMP_SLOT_NB;
+ ctx.collect_direction = DIRECTION_FORWARD;
+ ctx.clamp_pos_idle = ctx.collect_direction == DIRECTION_FORWARD
+ ? CLAMP_SLOT_FRONT_MIDDLE : CLAMP_SLOT_BACK_MIDDLE;
+ ctx.construct_possible = 0;
+ ctx.prepare = 1;
+ ctx.ready = 0;
+ ctx.need_prepare = 0;
+}
+
+void
+logistic_update (void)
+{
+ uint8_t side_now = !IO_GET (CONTACT_SIDE);
+ /* Filter side contact. */
+ if (side_now)
+ {
+ ctx.side_filter = 0;
+ ctx.side_state = 1;
+ }
+ else if (ctx.side_filter++ == 2 * 250)
+ {
+ ctx.side_state = 0;
+ ctx.side_filter = 0;
+ }
+ /* Side slot element can be lost. */
+ if (ctx.moving_from != CLAMP_SLOT_SIDE && !ctx.side_state)
+ ctx.slots[CLAMP_SLOT_SIDE] = 0;
+}
+
+void
+logistic_element_new (uint8_t pos, uint8_t element_type)
+{
+ assert (pos < CLAMP_SLOT_NB);
+ assert (!ctx.slots[pos]);
+ ctx.slots[pos] = element_type;
+ logistic_decision ();
+}
+
+void
+logistic_element_change (uint8_t pos, uint8_t element_type)
+{
+ assert (pos < CLAMP_SLOT_NB);
+ ctx.slots[pos] = element_type;
+ logistic_decision ();
+}
+
+void
+logistic_element_move_done (void)
+{
+ assert (!ctx.slots[ctx.moving_to] || ctx.moving_to == ctx.moving_from);
+ ctx.slots[ctx.moving_to] = ctx.slots[ctx.moving_from];
+ ctx.slots[ctx.moving_from] = 0;
+ ctx.moving_from = ctx.moving_to = CLAMP_SLOT_NB;
+ logistic_decision ();
+}
+
+void
+logistic_drop (uint8_t direction)
+{
+ uint8_t bay = direction == DIRECTION_FORWARD
+ ? CLAMP_SLOT_BACK_BOTTOM : CLAMP_SLOT_FRONT_BOTTOM;
+ uint8_t i;
+ for (i = bay; i < bay + 3; i++)
+ ctx.slots[i] = 0;
+ logistic_decision ();
+}
+
+uint8_t
+logistic_drop_element_type (uint8_t direction)
+{
+ uint8_t bay = direction == DIRECTION_FORWARD
+ ? CLAMP_SLOT_BACK_BOTTOM : CLAMP_SLOT_FRONT_BOTTOM;
+ uint8_t nb = 0;
+ uint8_t element_type = ELEMENT_NONE;
+ uint8_t i;
+ for (i = bay; i < bay + 3; i++)
+ {
+ if (ctx.slots[i])
+ {
+ nb++;
+ element_type = ctx.slots[i];
+ }
+ }
+ return nb > 1 ? ELEMENT_TOWER : element_type;
+}
+
+void
+logistic_dump (uint8_t direction, uint8_t drop_top)
+{
+ /* Drop. */
+ uint8_t i;
+ uint8_t bay = direction == DIRECTION_FORWARD
+ ? CLAMP_SLOT_FRONT_BOTTOM : CLAMP_SLOT_BACK_BOTTOM;
+ for (i = bay; i < bay + 2 + drop_top; i++)
+ ctx.slots[i] = 0;
+}
+
+static uint8_t
+logistic_slot_clear (uint8_t slot)
+{
+ if (CLAMP_IS_SLOT_IN_FRONT_BAY (slot))
+ {
+ if (ctx.slots[CLAMP_SLOT_FRONT_MIDDLE])
+ return 0;
+ uint8_t middle_type = ctx.slots[CLAMP_SLOT_FRONT_BOTTOM];
+ if (ELEMENT_IS_HEAD (middle_type) || middle_type == ELEMENT_TOWER)
+ return 0;
+ }
+ else if (CLAMP_IS_SLOT_IN_BACK_BAY (slot))
+ {
+ if (ctx.slots[CLAMP_SLOT_BACK_MIDDLE])
+ return 0;
+ uint8_t middle_type = ctx.slots[CLAMP_SLOT_BACK_BOTTOM];
+ if (ELEMENT_IS_HEAD (middle_type) || middle_type == ELEMENT_TOWER)
+ return 0;
+ }
+ return 1;
+}
+
+uint8_t
+logistic_path_clear (uint8_t slot1, uint8_t slot2)
+{
+ return logistic_slot_clear (slot1) && logistic_slot_clear (slot2);
+}
+
diff --git a/digital/io-hub/src/robospierre/logistic.h b/digital/io-hub/src/robospierre/logistic.h
new file mode 100644
index 00000000..c6bc0210
--- /dev/null
+++ b/digital/io-hub/src/robospierre/logistic.h
@@ -0,0 +1,143 @@
+#ifndef logistic_h
+#define logistic_h
+/* logistic.h */
+/* robospierre - Eurobot 2011 AI. {{{
+ *
+ * Copyright (C) 2011 Nicolas Schodet
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * 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 "element.h"
+#include "clamp.h"
+
+/** Defines for logistic macro, see LOGISTIC_CASE. */
+/** Any element must be present (not empty). */
+#define LOG_a 0
+/** Do not care if there is an element or not. */
+#define LOG__ 1
+/** There must not be element here. */
+#define LOG_e 2
+/** Pawn to pick up. */
+#define LOG_P 4
+/** A head to pick up. */
+#define LOG_H 5
+/** Pawn who has to be present. */
+#define LOG_p 6
+/** Head who has to be present. */
+#define LOG_h 7
+/** Destination (who has to be empty). */
+#define LOG_D 8
+/** We have a tower (always at bottom). */
+#define LOG_t 9
+/* LEFT means we keep the same side, RIGHT means we put the opposed side. */
+#define LOG_DIR_LEFT 0
+#define LOG_DIR_RIGHT 1
+/** Logistic macro to test if a case correspond and to perform movement.
+ * We have to consider that the moving direction is on the left.
+ * New direction is indicated (same or opposed).
+ * Set ready or not. */
+#define LOGISTIC_CASE(e1, e2, \
+ e3, e4, e5, \
+ e6, e7, new_dir, ready) \
+{ \
+ if (logistic_case (LOG_##e1, LOG_##e2, LOG_##e3, LOG_##e4, LOG_##e5, \
+ LOG_##e6, LOG_##e7, LOG_DIR_##new_dir, ready, 0)) \
+ return; \
+}
+
+/** Logistic context. */
+struct logistic_t
+{
+ /** Current robot content.
+ *
+ * Elements are fully specified (pawn, queen or king). An exception can
+ * occurs when a codebar is read but does not correspond to a valid word.
+ *
+ * When a movement is outgoing, the element is kept in the source slot. */
+ uint8_t slots[CLAMP_SLOT_NB];
+ /** Current element movement source and destination, CLAMP_SLOT_NB if no
+ * current movement. */
+ uint8_t moving_from, moving_to;
+ /** Best collect direction. */
+ uint8_t collect_direction;
+ /** Idle clamp position, depend on collect direction. */
+ uint8_t clamp_pos_idle;
+ /** Inform TOP if no construct is possible (0), if a tower is possible (1), if an
+ * other element can be put even if the clamp is broken (2). */
+ uint8_t construct_possible;
+ /** TOP set 0 if we do not want to build something, 1 if we can build a tower, 2 to prepare
+ anything possible, 3 the clamp is broken, prepare anything with *_BOTTOM. */
+ uint8_t prepare;
+ /** Inform TOP if a construct is ready (1) or not (0). */
+ uint8_t ready;
+ /* Inform TOP that we can't take any more elements and needs to put
+ * construction somewhere. */
+ uint8_t need_prepare;
+ /** Filtered side slot sensor. */
+ uint8_t side_state;
+ /** Filtered side slot sensor counter. */
+ uint16_t side_filter;
+};
+
+/** Global context. */
+extern struct logistic_t logistic_global;
+
+/** Initialise module. */
+void
+logistic_init (void);
+
+/** Examine current state and take a decision. */
+void
+logistic_decision (void);
+
+/** To be called at regular interval to check for bad robot state. */
+void
+logistic_update (void);
+
+/** To be called when a new element is entering the robot. */
+void
+logistic_element_new (uint8_t pos, uint8_t element_type);
+
+/** Oh la la, the pawn was not a pawn, it's a head. */
+void
+logistic_element_change (uint8_t pos, uint8_t element_type);
+
+/** To be called when a element movement is done. */
+void
+logistic_element_move_done (void);
+
+/** To be called when elements have been dropped on the opposite side of
+ * direction. */
+void
+logistic_drop (uint8_t direction);
+
+/** Get element type to be dropped. */
+uint8_t
+logistic_drop_element_type (uint8_t direction);
+
+/** Dump every element on one direction. */
+void
+logistic_dump (uint8_t direction, uint8_t drop_top);
+
+/** Is path clear between two positions? */
+uint8_t
+logistic_path_clear (uint8_t slot1, uint8_t slot2);
+
+#endif /* logistic_h */
diff --git a/digital/io-hub/src/robospierre/main.c b/digital/io-hub/src/robospierre/main.c
index 3a32a1ae..9ae644e6 100644
--- a/digital/io-hub/src/robospierre/main.c
+++ b/digital/io-hub/src/robospierre/main.c
@@ -28,6 +28,8 @@
#include "modules/uart/uart.h"
#include "modules/proto/proto.h"
+#include "modules/devices/usdist/usdist.h"
+
#include "timer.h"
#include "chrono.h"
#include "simu.host.h"
@@ -38,30 +40,60 @@
#include "pwm.h"
#include "contact.h"
+#include "codebar.h"
+#include "pawn_sensor.h"
+#include "radar.h"
#define FSM_NAME AI
#include "fsm.h"
#ifdef HOST
# include <string.h>
#endif
+#include "fsm_queue.h"
#include "clamp.h"
+#include "logistic.h"
+#include "path.h"
+#include "move.h"
+
+#include "bot.h"
#include "io.h"
+#ifndef HOST
+# include <avr/wdt.h>
+#endif
+
/** Our color. */
enum team_color_e team_color;
+/** Obstacles positions, updated using radar module. */
+vect_t main_obstacles_pos[2];
+
+/** Number of obstacles in main_obstacles_pos. */
+uint8_t main_obstacles_nb;
+
/** Asserv stats counters. */
static uint8_t main_stats_asserv_, main_stats_asserv_cpt_;
/** Contact stats counters. */
static uint8_t main_stats_contact_, main_stats_contact_cpt_;
+/** Codebar stats counters. */
+static uint8_t main_stats_codebar_, main_stats_codebar_cpt_;
+
+/** US sensors stats counters. */
+static uint8_t main_stats_usdist_, main_stats_usdist_cpt_;
+
/** Main initialisation. */
static void
main_init (void)
{
+#ifndef HOST
+ /* Disable watchdog (enabled in bootloader). */
+ MCUSR &= ~(1 << WDRF);
+ wdt_disable ();
+#endif
/* Serial port */
uart0_init ();
/* Enable interrupts */
@@ -76,6 +108,12 @@ main_init (void)
/* IO modules. */
pwm_init ();
contact_init ();
+ codebar_init ();
+ usdist_init ();
+ /* AI modules. */
+ clamp_init ();
+ logistic_init ();
+ path_init ();
/* Initialization done. */
proto_send0 ('z');
}
@@ -93,18 +131,52 @@ main_event_to_fsm (void)
#define FSM_HANDLE_TIMEOUT_E(fsm) \
do { if (FSM_HANDLE_TIMEOUT (fsm)) return; } while (0)
/* Update FSM timeouts. */
- //FSM_HANDLE_TIMEOUT_E (AI);
+ FSM_HANDLE_TIMEOUT_E (AI);
/* Motor status. */
- asserv_status_e mimot_motor0_status, mimot_motor1_status;
+ asserv_status_e robot_move_status, mimot_motor0_status,
+ mimot_motor1_status;
+ robot_move_status = asserv_move_cmd_status ();
mimot_motor0_status = mimot_motor0_cmd_status ();
mimot_motor1_status = mimot_motor1_cmd_status ();
+ if (robot_move_status == success)
+ FSM_HANDLE_E (AI, robot_move_success);
+ else if (robot_move_status == failure)
+ FSM_HANDLE_E (AI, robot_move_failure);
if (mimot_motor0_status == success
&& mimot_motor1_status == success)
FSM_HANDLE_E (AI, clamp_elevation_rotation_success);
+ if (mimot_motor0_status == failure
+ || mimot_motor1_status == failure)
+ FSM_HANDLE_E (AI, clamp_elevation_or_rotation_failure);
+ if (mimot_motor0_status == success)
+ FSM_HANDLE_E (AI, clamp_elevation_success);
else if (mimot_motor0_status == failure)
FSM_HANDLE_E (AI, clamp_elevation_failure);
+ if (mimot_motor1_status == success)
+ FSM_HANDLE_E (AI, clamp_rotation_success);
else if (mimot_motor1_status == failure)
FSM_HANDLE_E (AI, clamp_rotation_failure);
+ /* Clamp specific events. */
+ if (clamp_handle_event ())
+ return;
+ /* Jack. */
+ if (!contact_get_jack ())
+ FSM_HANDLE_E (AI, jack_inserted);
+ else
+ FSM_HANDLE_E (AI, jack_removed);
+ /* Events from the event queue. */
+ if (fsm_queue_poll ())
+ {
+ /* We must post the event at the end of this block because if it is
+ * handled, the function will return and every instruction after will
+ * never be executed. */
+ uint8_t save_event = fsm_queue_pop_event ();
+ /* Post the event */
+ FSM_HANDLE_VAR_E (AI, save_event);
+ }
+ /* Check obstables. */
+ if (move_check_obstacles ())
+ return;
}
/** Main (and infinite) loop. */
@@ -120,6 +192,12 @@ main_loop (void)
/* Is match over? */
if (chrono_is_match_over ())
{
+ /* Power off doors. */
+ pwm_set (BOT_PWM_DOOR_FRONT_BOTTOM, 0);
+ pwm_set (BOT_PWM_DOOR_FRONT_TOP, 0);
+ pwm_set (BOT_PWM_DOOR_BACK_BOTTOM, 0);
+ pwm_set (BOT_PWM_DOOR_BACK_TOP, 0);
+ pwm_set (BOT_PWM_CLAMP, 0);
/* End it and block here indefinitely. */
chrono_end_match (42);
return;
@@ -130,6 +208,18 @@ main_loop (void)
/* Update IO modules. */
pwm_update ();
contact_update ();
+ pawn_sensor_update ();
+ if (usdist_update ())
+ {
+ position_t robot_pos;
+ asserv_get_position (&robot_pos);
+ main_obstacles_nb = radar_update (&robot_pos, main_obstacles_pos);
+ move_obstacles_update ();
+ simu_send_pos_report (main_obstacles_pos, main_obstacles_nb, 0);
+ }
+ /* Update AI modules. */
+ logistic_update ();
+ path_decay ();
/* Only manage events if slaves are synchronised. */
if (twi_master_sync ())
main_event_to_fsm ();
@@ -146,9 +236,21 @@ main_loop (void)
}
if (main_stats_contact_ && !--main_stats_contact_cpt_)
{
- proto_send1d ('P', contact_all ());
+ proto_send1d ('P', contact_all () | (uint32_t) mimot_get_input () << 24);
main_stats_contact_cpt_ = main_stats_contact_;
}
+ if (main_stats_codebar_ && !--main_stats_codebar_cpt_)
+ {
+ proto_send2b ('B', codebar_get (DIRECTION_FORWARD),
+ codebar_get (DIRECTION_BACKWARD));
+ main_stats_codebar_cpt_ = main_stats_codebar_;
+ }
+ if (main_stats_usdist_ && !--main_stats_usdist_cpt_)
+ {
+ proto_send4w ('U', usdist_mm[0], usdist_mm[1], usdist_mm[2],
+ usdist_mm[3]);
+ main_stats_usdist_cpt_ = main_stats_usdist_;
+ }
}
}
@@ -163,6 +265,10 @@ proto_callback (uint8_t cmd, uint8_t size, uint8_t *args)
/* Reset */
utils_reset ();
break;
+ case c ('j', 0):
+ /* Simulate jack insertion. */
+ fsm_queue_post_event (FSM_EVENT (AI, jack_inserted));
+ break;
case c ('w', 3):
/* Set PWM.
* - 1b: index.
@@ -179,11 +285,64 @@ proto_callback (uint8_t cmd, uint8_t size, uint8_t *args)
v8_to_v16 (args[3], args[4]),
v8_to_v16 (args[5], args[6]));
break;
+ case c ('m', 5):
+ /* Go to position.
+ * - 2w: x, y.
+ * - 1b: backward. */
+ {
+ vect_t position = { v8_to_v16 (args[0], args[1]),
+ v8_to_v16 (args[2], args[3]) };
+ move_start_noangle (position, args[4], 0);
+ }
+ break;
case c ('c', 1):
/* Move clamp.
* - 1b: position. */
clamp_move (args[0]);
break;
+ case c ('c', 2):
+ /* Move element using clamp.
+ * - 1b: source.
+ * - 1b: destination. */
+ clamp_move_element (args[0], args[1]);
+ break;
+ case c ('n', 2):
+ /* Simulate the presence of a new element.
+ * - 1b: position.
+ * - 1b: type. */
+ clamp_new_element (args[0], args[1]);
+ break;
+ case c ('d', 0):
+ /* Open all doors. */
+ pwm_set_timed (BOT_PWM_DOOR_FRONT_BOTTOM,
+ BOT_PWM_DOOR_OPEN (CLAMP_SLOT_FRONT_BOTTOM));
+ pwm_set_timed (BOT_PWM_DOOR_FRONT_TOP,
+ BOT_PWM_DOOR_OPEN (CLAMP_SLOT_FRONT_TOP));
+ pwm_set_timed (BOT_PWM_DOOR_BACK_BOTTOM,
+ BOT_PWM_DOOR_OPEN (CLAMP_SLOT_BACK_BOTTOM));
+ pwm_set_timed (BOT_PWM_DOOR_BACK_TOP,
+ BOT_PWM_DOOR_OPEN (CLAMP_SLOT_BACK_TOP));
+ break;
+ case c ('d', 1):
+ /* Drop elements.
+ * - 1b: 00: drop clear, 01: drop forward, 02: drop backward. */
+ if (args[0] == 0x00)
+ clamp_drop_clear ();
+ else
+ clamp_drop (args[0]);
+ break;
+ case c ('d', 2):
+ /* Open or close door or clamp.
+ * - 1b: pos, or 0xff for clamp.
+ * - 1b: non zero to open. */
+ clamp_door (args[0], args[1]);
+ break;
+ case c ('w', 0):
+ /* Disable all motor control. */
+ mimot_motor0_free ();
+ mimot_motor1_free ();
+ asserv_free_motor ();
+ break;
/* Stats commands.
* - b: interval between stats. */
case c ('A', 1):
@@ -194,6 +353,14 @@ proto_callback (uint8_t cmd, uint8_t size, uint8_t *args)
/* Contact stats. */
main_stats_contact_ = main_stats_contact_cpt_ = args[0];
break;
+ case c ('B', 1):
+ /* Codebar stats. */
+ main_stats_codebar_ = main_stats_codebar_cpt_ = args[0];
+ break;
+ case c ('U', 1):
+ /* US sensors stats. */
+ main_stats_usdist_ = main_stats_usdist_cpt_ = args[0];
+ break;
default:
/* Unknown commands */
proto_send0 ('?');
diff --git a/digital/io-hub/src/robospierre/main.h b/digital/io-hub/src/robospierre/main.h
new file mode 100644
index 00000000..529aa0b2
--- /dev/null
+++ b/digital/io-hub/src/robospierre/main.h
@@ -0,0 +1,31 @@
+#ifndef main_h
+#define main_h
+/* main.h */
+/* robospierre - Eurobot 2011 AI. {{{
+ *
+ * Copyright (C) 2011 Nicolas Schodet
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * 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.
+ *
+ * }}} */
+
+extern vect_t main_obstacles_pos[2];
+extern uint8_t main_obstacles_nb;
+
+#endif /* main_h */
diff --git a/digital/io-hub/src/robospierre/move.c b/digital/io-hub/src/robospierre/move.c
new file mode 100644
index 00000000..a44b5715
--- /dev/null
+++ b/digital/io-hub/src/robospierre/move.c
@@ -0,0 +1,541 @@
+/* move.c */
+/* robospierre - Eurobot 2011 AI. {{{
+ *
+ * Copyright (C) 2011 Nicolas Schodet
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * 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 "common.h"
+#include "move.h"
+#include "playground_2011.h"
+
+#include "main.h"
+#include "asserv.h"
+
+#define FSM_NAME AI
+#include "fsm.h"
+#include "fsm_queue.h"
+
+#include "radar.h"
+#include "path.h"
+
+#include "modules/utils/utils.h"
+
+#include <math.h>
+
+/** Move context. */
+struct move_t
+{
+ /** Final position. */
+ position_t final;
+ /** Use angle consign for final point. */
+ uint8_t with_angle;
+ /** Next step. */
+ vect_t step;
+ /** Next step angle. */
+ uint16_t step_angle;
+ /** Next step with_angle. */
+ uint8_t step_with_angle;
+ /** Next step backward. */
+ uint8_t step_backward;
+ /** Non zero means this is a tricky move, slow down, and minimize
+ * turns. */
+ uint8_t slow;
+ /** Backward direction allowed flag. */
+ uint8_t backward_movement_allowed;
+ /** Try again counter. */
+ uint8_t try_again_counter;
+ /** Dirty fix to know this is the final move. */
+ uint8_t final_move;
+ /** Distance to remove from path. */
+ int16_t shorten;
+};
+
+/* Global context. */
+struct move_t move_data;
+
+void
+move_start (position_t position, uint8_t backward)
+{
+ /* Set parameters. */
+ move_data.final = position;
+ move_data.with_angle = 1;
+ move_data.backward_movement_allowed = backward;
+ move_data.final_move = 0;
+ move_data.shorten = 0;
+ /* Reset try counter. */
+ move_data.try_again_counter = 3;
+ /* Start the FSM. */
+ fsm_queue_post_event (FSM_EVENT (AI, move_start));
+}
+
+void
+move_start_noangle (vect_t position, uint8_t backward, int16_t shorten)
+{
+ /* Set parameters. */
+ move_data.final.v = position;
+ move_data.with_angle = 0;
+ move_data.backward_movement_allowed = backward;
+ move_data.final_move = 0;
+ move_data.shorten = shorten;
+ /* Reset try counter. */
+ move_data.try_again_counter = 3;
+ /* Start the FSM. */
+ fsm_queue_post_event (FSM_EVENT (AI, move_start));
+}
+
+void
+move_stop (void)
+{
+ /* Stop the FSM. */
+ fsm_queue_post_event (FSM_EVENT (AI, move_stop));
+}
+
+void
+move_obstacles_update (void)
+{
+ uint8_t i;
+ for (i = 0; i < main_obstacles_nb; i++)
+ path_obstacle (i, main_obstacles_pos[i], MOVE_OBSTACLE_RADIUS, 0,
+ MOVE_OBSTACLE_VALIDITY);
+}
+
+uint8_t
+move_check_obstacles (void)
+{
+ if (FSM_CAN_HANDLE (AI, obstacle_in_front))
+ {
+ position_t robot_pos;
+ asserv_get_position (&robot_pos);
+ if (radar_blocking (&robot_pos.v, &move_data.step, main_obstacles_pos,
+ main_obstacles_nb))
+ if (FSM_HANDLE (AI, obstacle_in_front))
+ return 1;
+ }
+ return 0;
+}
+
+FSM_STATES (
+ /* Waiting for the start order. */
+ MOVE_IDLE,
+ /* Rotating towards next point. */
+ MOVE_ROTATING,
+ /* Moving to a position (intermediate or final). */
+ MOVE_MOVING,
+ /* Moving backward to go away from what is blocking the bot. */
+ MOVE_MOVING_BACKWARD_TO_TURN_FREELY,
+ /* Waiting for obstacle to disappear. */
+ MOVE_WAIT_FOR_CLEAR_PATH)
+
+FSM_EVENTS (
+ /* Report from asserv after a successful move command. */
+ robot_move_success,
+ /* Report from asserv after a failed move command. */
+ robot_move_failure,
+ /* Initialize the FSM and start the movement directly. */
+ move_start,
+ /* Stop movement. */
+ move_stop,
+ /* Movement success. */
+ move_success,
+ /* Movement failure. */
+ move_failure,
+ /* The bot has seen something (front is the same when going backward). */
+ obstacle_in_front)
+
+FSM_START_WITH (MOVE_IDLE)
+
+/** Go to current step, low level function. */
+static void
+move_go (void)
+{
+ vect_t dst = move_data.step;
+ /* Modify final point if requested. */
+ if (move_data.final_move && move_data.shorten)
+ {
+ /* Compute a vector from destination to robot with lenght
+ * 'shorten'. */
+ position_t robot_position;
+ asserv_get_position (&robot_position);
+ vect_t v = robot_position.v;
+ vect_sub (&v, &move_data.step);
+ int16_t d = vect_norm (&v);
+ if (d > move_data.shorten)
+ {
+ vect_scale_f824 (&v, 0x1000000 / d * move_data.shorten);
+ vect_translate (&dst, &v);
+ }
+ }
+ if (move_data.step_with_angle)
+ asserv_goto_xya (dst.x, dst.y, move_data.step_angle,
+ move_data.step_backward);
+ else
+ asserv_goto (dst.x, dst.y, move_data.step_backward);
+}
+
+/** Go or rotate toward position, returns 1 for linear move, 2 for angular
+ * move. */
+static uint8_t
+move_go_or_rotate (vect_t dst, uint16_t angle, uint8_t with_angle,
+ uint8_t backward)
+{
+ position_t robot_position;
+ asserv_get_position (&robot_position);
+ uint16_t robot_angle = robot_position.a;
+ if (backward & ASSERV_BACKWARD)
+ robot_angle += 0x8000;
+ /* Check for green zone. */
+ if (robot_position.v.x < PG_GREEN_WIDTH_MM
+ || robot_position.v.x > PG_WIDTH - PG_GREEN_WIDTH_MM)
+ backward |= ASSERV_REVERT_OK;
+ /* Remember step. */
+ move_data.step = dst;
+ move_data.step_angle = angle;
+ move_data.step_with_angle = with_angle;
+ move_data.step_backward = backward;
+ /* Compute angle to destination. */
+ vect_t v = dst; vect_sub (&v, &robot_position.v);
+ uint16_t dst_angle = atan2 (v.y, v.x) * ((1l << 16) / (2 * M_PI));
+ if (backward & ASSERV_BACKWARD)
+ dst_angle += 0x8000;
+ int16_t diff_angle = dst_angle - robot_angle;
+ if ((backward & ASSERV_REVERT_OK)
+ && (diff_angle > 0x4000 || diff_angle < -0x4000))
+ dst_angle += 0x8000;
+ int16_t diff = dst_angle - robot_angle;
+ /* Move or rotate. */
+ if (UTILS_ABS (diff) < 0x1000)
+ {
+ move_go ();
+ return 1;
+ }
+ else
+ {
+ asserv_goto_angle (dst_angle);
+ return 2;
+ }
+}
+
+/** Go to next position computed by path module, to be called by
+ * move_path_init and move_path_next. Returns 1 for linear move, 2 for angular
+ * move. */
+static uint8_t
+move_go_to_next (vect_t dst)
+{
+ uint8_t r;
+ /* If it is not the last position. */
+ if (dst.x != move_data.final.v.x || dst.y != move_data.final.v.y)
+ {
+ /* Not final position. */
+ move_data.final_move = 0;
+ /* Goto without angle. */
+ r = move_go_or_rotate (dst, 0, 0, move_data.backward_movement_allowed
+ | (move_data.slow ? ASSERV_REVERT_OK : 0));
+ }
+ else
+ {
+ /* Final position. */
+ move_data.final_move = 1;
+ /* Goto with angle if requested. */
+ r = move_go_or_rotate (dst, move_data.final.a, move_data.with_angle,
+ move_data.backward_movement_allowed);
+ }
+ /* Next time, do not use slow. */
+ move_data.slow = 0;
+ return r;
+}
+
+/** Update and go to first position, return non zero if a path is found, 1 for
+ * linear move, 2 for angular move. */
+static uint8_t
+move_path_init (void)
+{
+ uint8_t found;
+ vect_t dst;
+ /* Get the current position */
+ position_t current_pos;
+ asserv_get_position (&current_pos);
+ /* Give the current position of the bot to the path module */
+ path_endpoints (current_pos.v, move_data.final.v);
+ /* Update the path module */
+ move_data.slow = 0;
+ path_update ();
+ found = path_get_next (&dst);
+ /* If not found, try to escape. */
+ if (!found)
+ {
+ move_data.slow = 1;
+ path_escape (8);
+ path_update ();
+ found = path_get_next (&dst);
+ }
+ /* If found, go. */
+ if (found)
+ {
+ return move_go_to_next (dst);
+ }
+ else
+ {
+ /* Error, not final move. */
+ move_data.final_move = 0;
+ return 0;
+ }
+}
+
+/** Go to next position in path. Returns 1 for linear move, 2 for angular
+ * move. */
+static uint8_t
+move_path_next (void)
+{
+ vect_t dst;
+ path_get_next (&dst);
+ return move_go_to_next (dst);
+}
+
+FSM_TRANS (MOVE_IDLE, move_start,
+ path_found_rotate, MOVE_ROTATING,
+ path_found, MOVE_MOVING,
+ no_path_found, MOVE_IDLE)
+{
+ uint8_t next = move_path_init ();
+ if (next)
+ {
+ if (next == 2)
+ return FSM_NEXT (MOVE_IDLE, move_start, path_found_rotate);
+ else
+ return FSM_NEXT (MOVE_IDLE, move_start, path_found);
+ }
+ else
+ {
+ fsm_queue_post_event (FSM_EVENT (AI, move_failure));
+ return FSM_NEXT (MOVE_IDLE, move_start, no_path_found);
+ }
+}
+
+FSM_TRANS (MOVE_ROTATING,
+ robot_move_success,
+ MOVE_MOVING)
+{
+ move_go ();
+ return FSM_NEXT (MOVE_ROTATING, robot_move_success);
+}
+
+FSM_TRANS (MOVE_ROTATING,
+ robot_move_failure,
+ MOVE_MOVING)
+{
+ move_go ();
+ return FSM_NEXT (MOVE_ROTATING, robot_move_failure);
+}
+
+FSM_TRANS_TIMEOUT (MOVE_ROTATING, 1250,
+ MOVE_MOVING)
+{
+ move_go ();
+ return FSM_NEXT_TIMEOUT (MOVE_ROTATING);
+}
+
+FSM_TRANS (MOVE_ROTATING, move_stop, MOVE_IDLE)
+{
+ asserv_stop_motor ();
+ return FSM_NEXT (MOVE_ROTATING, move_stop);
+}
+
+FSM_TRANS (MOVE_MOVING, robot_move_success,
+ done, MOVE_IDLE,
+ path_found_rotate, MOVE_ROTATING,
+ path_found, MOVE_MOVING,
+ no_path_found, MOVE_IDLE)
+{
+ if (move_data.final_move)
+ {
+ fsm_queue_post_event (FSM_EVENT (AI, move_success));
+ return FSM_NEXT (MOVE_MOVING, robot_move_success, done);
+ }
+ else
+ {
+ uint8_t next = move_path_next ();
+ if (next == 2)
+ return FSM_NEXT (MOVE_MOVING, robot_move_success, path_found_rotate);
+ else
+ return FSM_NEXT (MOVE_MOVING, robot_move_success, path_found);
+ }
+ //return FSM_NEXT (MOVE_MOVING, robot_move_success, no_path_found);
+}
+
+static void
+move_moving_backward_to_turn_freely (void)
+{
+ move_data.final_move = 0;
+ /* Assume there is an obstacle in front of the robot. */
+ position_t robot_pos;
+ asserv_get_position (&robot_pos);
+ vect_t obstacle_pos;
+ int16_t dist = asserv_get_last_moving_direction () == DIRECTION_FORWARD
+ ? BOT_SIZE_FRONT + MOVE_REAL_OBSTACLE_RADIUS
+ : -(BOT_SIZE_BACK + MOVE_REAL_OBSTACLE_RADIUS);
+ vect_from_polar_uf016 (&obstacle_pos, dist, robot_pos.a);
+ vect_translate (&obstacle_pos, &robot_pos.v);
+ path_obstacle (0, obstacle_pos, MOVE_OBSTACLE_RADIUS, 0,
+ MOVE_OBSTACLE_VALIDITY);
+ /* Move backward to turn freely. */
+ asserv_move_linearly (asserv_get_last_moving_direction ()
+ == DIRECTION_FORWARD ? -300 : 300);
+}
+
+FSM_TRANS (MOVE_MOVING,
+ robot_move_failure,
+ MOVE_MOVING_BACKWARD_TO_TURN_FREELY)
+{
+ move_moving_backward_to_turn_freely ();
+ return FSM_NEXT (MOVE_MOVING, robot_move_failure);
+}
+
+FSM_TRANS_TIMEOUT (MOVE_MOVING, 2500,
+ MOVE_MOVING_BACKWARD_TO_TURN_FREELY)
+{
+ move_moving_backward_to_turn_freely ();
+ return FSM_NEXT_TIMEOUT (MOVE_MOVING);
+}
+
+FSM_TRANS (MOVE_MOVING, obstacle_in_front,
+ tryagain, MOVE_WAIT_FOR_CLEAR_PATH,
+ tryout, MOVE_IDLE)
+{
+ move_data.final_move = 0;
+ asserv_stop_motor ();
+ if (--move_data.try_again_counter == 0)
+ {
+ fsm_queue_post_event (FSM_EVENT (AI, move_failure));
+ return FSM_NEXT (MOVE_MOVING, obstacle_in_front, tryout);
+ }
+ else
+ return FSM_NEXT (MOVE_MOVING, obstacle_in_front, tryagain);
+}
+
+FSM_TRANS (MOVE_MOVING, move_stop, MOVE_IDLE)
+{
+ asserv_stop_motor ();
+ return FSM_NEXT (MOVE_MOVING, move_stop);
+}
+
+FSM_TRANS (MOVE_MOVING_BACKWARD_TO_TURN_FREELY, robot_move_success,
+ tryout, MOVE_IDLE,
+ path_found_rotate, MOVE_ROTATING,
+ path_found, MOVE_MOVING,
+ no_path_found, MOVE_IDLE)
+{
+ if (--move_data.try_again_counter == 0)
+ {
+ fsm_queue_post_event (FSM_EVENT (AI, move_failure));
+ return FSM_NEXT (MOVE_MOVING_BACKWARD_TO_TURN_FREELY, robot_move_success, tryout);
+ }
+ else
+ {
+ uint8_t next = move_path_init ();
+ if (next)
+ {
+ if (next == 2)
+ return FSM_NEXT (MOVE_MOVING_BACKWARD_TO_TURN_FREELY, robot_move_success, path_found_rotate);
+ else
+ return FSM_NEXT (MOVE_MOVING_BACKWARD_TO_TURN_FREELY, robot_move_success, path_found);
+ }
+ else
+ {
+ fsm_queue_post_event (FSM_EVENT (AI, move_failure));
+ return FSM_NEXT (MOVE_MOVING_BACKWARD_TO_TURN_FREELY, robot_move_success, no_path_found);
+ }
+ }
+}
+
+FSM_TRANS (MOVE_MOVING_BACKWARD_TO_TURN_FREELY, robot_move_failure,
+ tryout, MOVE_IDLE,
+ path_found_rotate, MOVE_ROTATING,
+ path_found, MOVE_MOVING,
+ no_path_found_tryagain, MOVE_WAIT_FOR_CLEAR_PATH,
+ no_path_found_tryout, MOVE_IDLE)
+{
+ if (--move_data.try_again_counter == 0)
+ {
+ fsm_queue_post_event (FSM_EVENT (AI, move_failure));
+ return FSM_NEXT (MOVE_MOVING_BACKWARD_TO_TURN_FREELY, robot_move_failure, tryout);
+ }
+ else
+ {
+ uint8_t next = move_path_init ();
+ if (next)
+ {
+ if (next == 2)
+ return FSM_NEXT (MOVE_MOVING_BACKWARD_TO_TURN_FREELY, robot_move_failure, path_found_rotate);
+ else
+ return FSM_NEXT (MOVE_MOVING_BACKWARD_TO_TURN_FREELY, robot_move_failure, path_found);
+ }
+ else
+ {
+ if (--move_data.try_again_counter == 0)
+ {
+ fsm_queue_post_event (FSM_EVENT (AI, move_failure));
+ return FSM_NEXT (MOVE_MOVING_BACKWARD_TO_TURN_FREELY, robot_move_failure, no_path_found_tryout);
+ }
+ else
+ return FSM_NEXT (MOVE_MOVING_BACKWARD_TO_TURN_FREELY, robot_move_failure, no_path_found_tryagain);
+ }
+ }
+}
+
+FSM_TRANS (MOVE_MOVING_BACKWARD_TO_TURN_FREELY, move_stop, MOVE_IDLE)
+{
+ asserv_stop_motor ();
+ return FSM_NEXT (MOVE_MOVING_BACKWARD_TO_TURN_FREELY, move_stop);
+}
+
+FSM_TRANS_TIMEOUT (MOVE_WAIT_FOR_CLEAR_PATH, 250,
+ path_found_rotate, MOVE_ROTATING,
+ path_found, MOVE_MOVING,
+ no_path_found_tryagain, MOVE_WAIT_FOR_CLEAR_PATH,
+ no_path_found_tryout, MOVE_IDLE)
+{
+ /* Try to move. */
+ uint8_t next = move_path_init ();
+ if (next)
+ {
+ if (next == 2)
+ return FSM_NEXT_TIMEOUT (MOVE_WAIT_FOR_CLEAR_PATH, path_found_rotate);
+ else
+ return FSM_NEXT_TIMEOUT (MOVE_WAIT_FOR_CLEAR_PATH, path_found);
+ }
+ else
+ {
+ /* Error, no new position, should we try again? */
+ if (--move_data.try_again_counter == 0)
+ {
+ fsm_queue_post_event (FSM_EVENT (AI, move_failure));
+ return FSM_NEXT_TIMEOUT (MOVE_WAIT_FOR_CLEAR_PATH, no_path_found_tryout);
+ }
+ else
+ return FSM_NEXT_TIMEOUT (MOVE_WAIT_FOR_CLEAR_PATH, no_path_found_tryagain);
+ }
+}
+
+FSM_TRANS (MOVE_WAIT_FOR_CLEAR_PATH, move_stop, MOVE_IDLE)
+{
+ return FSM_NEXT (MOVE_WAIT_FOR_CLEAR_PATH, move_stop);
+}
+
diff --git a/digital/io-hub/src/robospierre/move.h b/digital/io-hub/src/robospierre/move.h
new file mode 100644
index 00000000..72af5b84
--- /dev/null
+++ b/digital/io-hub/src/robospierre/move.h
@@ -0,0 +1,63 @@
+#ifndef move_h
+#define move_h
+/* move.h */
+/* robospierre - Eurobot 2011 AI. {{{
+ *
+ * Copyright (C) 2011 Nicolas Schodet
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * 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 "defs.h"
+#include "bot.h"
+
+/** Real radius of an obstacle. */
+#define MOVE_REAL_OBSTACLE_RADIUS 150
+
+/** Obstacle radius for the path module.
+ * It corresponds to the real radius of the obstacle plus the distance you
+ * want to add to avoid it. */
+#define MOVE_OBSTACLE_RADIUS (MOVE_REAL_OBSTACLE_RADIUS \
+ + RADAR_CLEARANCE_MM \
+ + BOT_SIZE_SIDE)
+
+/** Obstacle validity time (in term of number of cycles). */
+#define MOVE_OBSTACLE_VALIDITY (3 * 225)
+
+/** Go to a position, see asserv.h for backward argument. */
+void
+move_start (position_t position, uint8_t backward);
+
+/** Go to a position, with no angle consign. */
+void
+move_start_noangle (vect_t position, uint8_t backward, int16_t shorten);
+
+/** Stop movement. */
+void
+move_stop (void);
+
+/** To be called when obstacles positions are computed. */
+void
+move_obstacles_update (void);
+
+/** Check for blocking obstacles, return non zero if an event is handled. */
+uint8_t
+move_check_obstacles (void);
+
+#endif /* move_h */
diff --git a/digital/io-hub/src/robospierre/path.c b/digital/io-hub/src/robospierre/path.c
new file mode 100644
index 00000000..ecdddbf7
--- /dev/null
+++ b/digital/io-hub/src/robospierre/path.c
@@ -0,0 +1,621 @@
+/* path.c */
+/* robospierre - Eurobot 2011 AI. {{{
+ *
+ * Copyright (C) 2011 Nicolas Schodet
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * 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 "common.h"
+#include "defs.h"
+#include "path.h"
+#include "bot.h"
+#include "playground_2011.h"
+#include "element.h"
+
+#include "modules/path/astar/astar.h"
+#include "modules/utils/utils.h"
+#include "modules/math/geometry/distance.h"
+
+#define PATH_DEBUG 0
+
+#if PATH_DEBUG
+#include "debug.host.h"
+#endif
+
+/**
+ * This year, due to the large number of obstacles, a grid like structure is
+ * used for path finding on the playground. The A* algorithm is used to find
+ * path along nodes.
+ *
+ * The grid is composed of 11 columns of 4 node each. They are numbered by
+ * column. Even columns are aligned with center of squares, while odd columns
+ * are at squares intersections. Therefore, odd columns have a offset of
+ * 352/2 mm, and that is the reason why code should handle odd and even
+ * columns differently.
+ *
+ * There is also extra grid nodes in front of the green zone.
+ *
+ * All those tricks are used to reduce the number of nodes.
+ */
+
+/** Number of possible obstacles. */
+#define PATH_OBSTACLES_NB AC_PATH_OBSTACLES_NB
+
+/** Number of nodes in a column. */
+#define PATH_COLUMN_NODES_NB 4
+
+/** Number of columns. */
+#define PATH_COLUMNS_NB 11
+
+/** Number of nodes in the grid. */
+#define PATH_GRID_NODES_NB (PATH_COLUMNS_NB * PATH_COLUMN_NODES_NB)
+
+/** Number of nodes in front of each green zone. */
+#define PATH_GREEN_NODES_NB 4
+
+/** Number of fixed nodes. */
+#define PATH_FIXED_NODES_NB (PATH_GRID_NODES_NB + 2 * PATH_GREEN_NODES_NB)
+
+/** Number of nodes in search graph, last two nodes are destination and source
+ * nodes. */
+#define PATH_NODES_NB (PATH_FIXED_NODES_NB + 2)
+
+/** Index of destination node. */
+#define PATH_DST_NODE_INDEX PATH_FIXED_NODES_NB
+
+/** Index of source node. */
+#define PATH_SRC_NODE_INDEX (PATH_DST_NODE_INDEX + 1)
+
+/** Information on a node. */
+struct path_node_t
+{
+ /** Whether this node can be used. */
+ uint8_t usable;
+};
+
+/** Context. */
+struct path_t
+{
+ /** List of obstacles. */
+ struct path_obstacle_t obstacles[PATH_OBSTACLES_NB];
+ /** Escape factor, 0 if none. */
+ uint8_t escape_factor;
+ /** List of nodes used for A*. */
+ struct astar_node_t astar_nodes[PATH_NODES_NB];
+ /** Cache of whether a node is blocked. */
+ uint8_t valid[PATH_FIXED_NODES_NB];
+ /** Position of end points. */
+ vect_t endpoints[2];
+ /** Whether the last update was a success. */
+ uint8_t found;
+ /** Which node to look at for next step. */
+ uint8_t get;
+};
+static struct path_t path;
+
+/** Static information on nodes. */
+static const struct path_node_t path_nodes[PATH_FIXED_NODES_NB] = {
+ /* {{{ */
+ { 1 }, /* 0 column 0. */
+ { 1 }, /* 1 */
+ { 1 }, /* 2 */
+ { 1 }, /* 3 */
+ { 1 }, /* 4 column 1. */
+ { 1 }, /* 5 */
+ { 1 }, /* 6 */
+ { 1 }, /* 7 */
+ { 1 }, /* 8 column 2. */
+ { 1 }, /* 9 */
+ { 1 }, /* 10 */
+ { 1 }, /* 11 */
+ { 1 }, /* 12 column 3. */
+ { 1 }, /* 13 */
+ { 1 }, /* 14 */
+ { 1 }, /* 15 */
+ { 1 }, /* 16 column 4. */
+ { 1 }, /* 17 */
+ { 1 }, /* 18 */
+ { 1 }, /* 19 */
+ { 1 }, /* 20 column 5. */
+ { 1 }, /* 21 */
+ { 1 }, /* 22 */
+ { 1 }, /* 23 */
+ { 1 }, /* 24 column 6. */
+ { 1 }, /* 25 */
+ { 1 }, /* 26 */
+ { 1 }, /* 27 */
+ { 1 }, /* 28 column 7. */
+ { 1 }, /* 29 */
+ { 1 }, /* 30 */
+ { 1 }, /* 31 */
+ { 1 }, /* 32 column 8. */
+ { 1 }, /* 33 */
+ { 1 }, /* 34 */
+ { 1 }, /* 35 */
+ { 1 }, /* 36 column 9. */
+ { 1 }, /* 37 */
+ { 1 }, /* 38 */
+ { 1 }, /* 39 */
+ { 1 }, /* 40 column 10. */
+ { 1 }, /* 41 */
+ { 1 }, /* 42 */
+ { 1 }, /* 43 */
+ { 1 }, /* 44 left green. */
+ { 1 }, /* 45 */
+ { 1 }, /* 46 */
+ { 1 }, /* 47 */
+ { 1 }, /* 48 right green. */
+ { 1 }, /* 49 */
+ { 1 }, /* 50 */
+ { 1 }, /* 51 */
+ /* }}} */
+};
+
+/** Compute position of a node. */
+static void
+path_pos (uint8_t node, vect_t *pos)
+{
+ assert (node < PATH_NODES_NB);
+ if (node < PATH_GRID_NODES_NB)
+ {
+ uint8_t col = node / PATH_COLUMN_NODES_NB;
+ uint8_t line = node - col * PATH_COLUMN_NODES_NB;
+ pos->x = 400 + 50 + 350 / 2 + col * 350 / 2;
+ pos->y = 2100 - 350 - 350 / 2
+ + (col % 2 ? 350 / 2 : 0)
+ - line * 350;
+ }
+ else if (node < PATH_GRID_NODES_NB + 2 * PATH_GREEN_NODES_NB)
+ {
+ node -= PATH_GRID_NODES_NB;
+ uint8_t col = node / PATH_GREEN_NODES_NB;
+ uint8_t line = node - col * PATH_GREEN_NODES_NB;
+ pos->x = col == 0 ? BOT_GREEN_ELEMENT_PLACE_DISTANCE_MM
+ : PG_WIDTH - BOT_GREEN_ELEMENT_PLACE_DISTANCE_MM;
+ pos->y = (5 - line) * 280 + 10;
+ }
+ else
+ {
+ *pos = path.endpoints[node - PATH_FIXED_NODES_NB];
+ }
+}
+
+static uint8_t
+path_element_blocking (uint8_t node, uint8_t escape)
+{
+ vect_t pos;
+ path_pos (node, &pos);
+ int16_t square_x = (pos.x - 450 - 1) / 350;
+ int16_t square_y = (2100 - pos.y - 1) / 350;
+ uint8_t element_id = ELEMENT_UNLOAD_START + square_x + 6 * square_y;
+ if (element_blocking (element_id, escape))
+ return 1;
+ uint8_t intersection = ((pos.x - 450) / 350) != square_x;
+ if (intersection)
+ {
+ if (element_blocking (element_id + 1, escape))
+ return 1;
+ if (element_blocking (element_id + 6, escape))
+ return 1;
+ if (element_blocking (element_id + 6 + 1, escape))
+ return 1;
+ }
+ return 0;
+}
+
+/** Return 1 if the direct path between a and b nodes is blocked, also compute
+ * distance. */
+static uint8_t
+path_blocking (uint8_t a, uint8_t b, int16_t *dp)
+{
+ uint8_t i;
+ vect_t va;
+ vect_t vb;
+ uint8_t escape_factor = 0;
+ uint8_t factor = 1;
+ uint8_t blocking = 0;
+ if (a == PATH_SRC_NODE_INDEX || b == PATH_SRC_NODE_INDEX)
+ escape_factor = path.escape_factor;
+ path_pos (a, &va);
+ path_pos (b, &vb);
+ /* Test for green zone. */
+ uint8_t a_green, b_green;
+ a_green = va.x < PG_GREEN_WIDTH_MM || va.x > PG_WIDTH - PG_GREEN_WIDTH_MM;
+ b_green = vb.x < PG_GREEN_WIDTH_MM || vb.x > PG_WIDTH - PG_GREEN_WIDTH_MM;
+ if ((va.x < BOT_GREEN_ELEMENT_PLACE_DISTANCE_MM
+ && vb.x > BOT_GREEN_ELEMENT_PLACE_DISTANCE_MM)
+ || (va.x > BOT_GREEN_ELEMENT_PLACE_DISTANCE_MM
+ && vb.x < BOT_GREEN_ELEMENT_PLACE_DISTANCE_MM)
+ || (va.x > PG_WIDTH - BOT_GREEN_ELEMENT_PLACE_DISTANCE_MM
+ && vb.x < PG_WIDTH - BOT_GREEN_ELEMENT_PLACE_DISTANCE_MM)
+ || (va.x < PG_WIDTH - BOT_GREEN_ELEMENT_PLACE_DISTANCE_MM
+ && vb.x > PG_WIDTH - BOT_GREEN_ELEMENT_PLACE_DISTANCE_MM))
+ return 1;
+ if (a_green && b_green)
+ return 1;
+ if (a_green || b_green)
+ factor = 4;
+ /* Test for protected zone. */
+ if (va.y <= 350 && va.x > PG_WIDTH / 2 - 350 && va.y < PG_WIDTH / 2 + 350
+ && (vb.x < PG_WIDTH / 2 - 350 || vb.x > PG_WIDTH / 2 + 350))
+ return 1;
+ if (vb.y <= 350 && vb.x > PG_WIDTH / 2 - 350 && vb.y < PG_WIDTH / 2 + 350
+ && (va.x < PG_WIDTH / 2 - 350 || va.x > PG_WIDTH / 2 + 350))
+ return 1;
+ /* Test for a blocking obstacle. */
+ for (i = 0; i < PATH_OBSTACLES_NB && !blocking; i++)
+ {
+ if (path.obstacles[i].valid)
+ {
+ uint16_t d = distance_segment_point (&va, &vb,
+ &path.obstacles[i].c);
+ if (d < path.obstacles[i].r)
+ blocking = 1;
+ }
+ }
+ /* Compute distance. */
+ int16_t d = distance_point_point (&va, &vb);
+ if (d == 0)
+ {
+ *dp = 0;
+ return 0;
+ }
+ /* Test for a blocking element. */
+ if (element_blocking_path (va, vb, d, path.escape_factor))
+ blocking = 1;
+ /* Handle escaping. */
+ if (blocking)
+ {
+ if (escape_factor)
+ {
+ *dp = d * escape_factor;
+ return 0;
+ }
+ else
+ return 1;
+ }
+ /* No blocking. */
+ *dp = d * factor;
+ return 0;
+}
+
+/** Update the cache of blocked nodes. */
+static void
+path_blocked_update (void)
+{
+ uint8_t i, j;
+ for (i = 0; i < PATH_FIXED_NODES_NB; i++)
+ {
+ uint8_t valid = 1;
+ /* First, gather information from tables. */
+ if (!path_nodes[i].usable
+ || path_element_blocking (i, path.escape_factor))
+ valid = 0;
+ else
+ {
+ vect_t pos;
+ path_pos (i, &pos);
+ /* Then, test for obstacles. */
+ for (j = 0; j < PATH_OBSTACLES_NB; j++)
+ {
+ if (path.obstacles[j].valid)
+ {
+ vect_t v = pos; vect_sub (&v, &path.obstacles[j].c);
+ uint32_t dsq = vect_dot_product (&v, &v);
+ uint32_t r = path.obstacles[j].r;
+ if (dsq <= r * r)
+ {
+ valid = 0;
+ break;
+ }
+ }
+ }
+ }
+ /* Update cache. */
+ path.valid[i] = valid;
+ }
+}
+
+void
+path_init (void)
+{
+}
+
+void
+path_endpoints (vect_t s, vect_t d)
+{
+ path.endpoints[0] = d;
+ path.endpoints[1] = s;
+}
+
+void
+path_escape (uint8_t factor)
+{
+ path.escape_factor = factor;
+}
+
+void
+path_obstacle (uint8_t i, vect_t c, uint16_t r, uint8_t factor,
+ uint16_t valid)
+{
+ assert (i < AC_PATH_OBSTACLES_NB);
+ assert (factor == 0);
+ path.obstacles[i].c = c;
+ path.obstacles[i].r = r;
+ path.obstacles[i].valid = valid;
+}
+
+void
+path_decay (void)
+{
+ uint8_t i;
+ for (i = 0; i < PATH_OBSTACLES_NB; i++)
+ {
+ if (path.obstacles[i].valid
+ && path.obstacles[i].valid != PATH_OBSTACLE_VALID_ALWAYS)
+ path.obstacles[i].valid--;
+ }
+}
+
+void
+path_update (void)
+{
+ path_blocked_update ();
+ path.found = astar (path.astar_nodes, PATH_NODES_NB, PATH_DST_NODE_INDEX,
+ PATH_SRC_NODE_INDEX);
+ path.get = PATH_SRC_NODE_INDEX;
+#if AC_PATH_REPORT
+ if (path.found)
+ {
+ uint8_t n, len = 0;
+ vect_t points[PATH_NODES_NB];
+ for (n = path.get; n != PATH_DST_NODE_INDEX; n = path.astar_nodes[n].prev)
+ path_pos (n, &points[len++]);
+ path_pos (n, &points[len++]);
+ AC_PATH_REPORT_CALLBACK (points, len, path.obstacles,
+ PATH_OBSTACLES_NB);
+ }
+#endif
+}
+
+uint8_t
+path_get_next (vect_t *p)
+{
+ if (path.found)
+ {
+ assert (path.get != PATH_DST_NODE_INDEX);
+ uint8_t prev = path.get;
+ vect_t pp;
+ path_pos (prev, &pp);
+ uint8_t next = path.astar_nodes[path.get].prev;
+ path.get = next;
+ path_pos (next, p);
+ while (next != 0xff)
+ {
+ /* Try to remove useless points. */
+ uint8_t next = path.astar_nodes[path.get].prev;
+ if (next == 0xff || next == PATH_DST_NODE_INDEX)
+ break;
+ vect_t np;
+ path_pos (next, &np);
+ vect_t vnp = np; vect_sub (&vnp, &pp);
+ vect_t vp = *p; vect_sub (&vp, &pp);
+ if (vect_normal_dot_product (&vp, &vnp) == 0)
+ {
+ path.get = next;
+ *p = np;
+ }
+ else
+ break;
+ }
+ return 1;
+ }
+ else
+ return 0;
+}
+
+/** Neighbors callback for nodes in grid. */
+static uint8_t
+path_astar_neighbor_callback_grid (uint8_t node,
+ struct astar_neighbor_t *neighbors)
+{
+ uint8_t neighbors_nb = 0;
+ uint8_t i;
+ /* Add neighbors in all 8 directions. */
+ static const struct {
+ /** Column offset of this neighbor. */
+ int8_t column_offset;
+ /** Line offset of this neighbor, for even columns. */
+ int8_t even_line_offset;
+ /** Line offset for odd columns. */
+ int8_t odd_line_offset;
+ /** Distance to this neighbor. */
+ uint16_t weight;
+ } star_n[] = {
+ { 0, -1, -1, 350 }, /* N */
+ { -1, 0, -1, 248 }, /* NW */
+ { -2, 0, 0, 350 }, /* W */
+ { -1, 1, 0, 248 }, /* SW */
+ { 0, 1, 1, 350 }, /* S */
+ { 1, 1, 0, 248 }, /* SE */
+ { 2, 0, 0, 350 }, /* E */
+ { 1, 0, -1, 248 }, /* NE */
+ };
+ uint8_t col = node / PATH_COLUMN_NODES_NB;
+ uint8_t line = node - col * PATH_COLUMN_NODES_NB;
+ uint8_t odd = col % 2;
+ for (i = 0; i < UTILS_COUNT (star_n); i++)
+ {
+ int8_t new_col = col + star_n[i].column_offset;
+ int8_t new_line = line + (odd ? star_n[i].odd_line_offset
+ : star_n[i].even_line_offset);
+ int8_t new_node = new_col * PATH_COLUMN_NODES_NB + new_line;
+ if (new_col >= 0 && new_col < PATH_COLUMNS_NB
+ && new_line >= 0 && new_line < PATH_COLUMN_NODES_NB)
+ {
+ uint8_t valid = path.valid[new_node];
+ if (valid)
+ {
+ neighbors[neighbors_nb].node = new_node;
+ neighbors[neighbors_nb].weight = star_n[i].weight + 1;
+ neighbors_nb++;
+ }
+ }
+ }
+ /* Check path to green nodes. */
+ int16_t d;
+ if (col <= 1 || col >= PATH_COLUMNS_NB - 1)
+ {
+ uint8_t green = PATH_GRID_NODES_NB
+ + (col <= 1 ? 0 : PATH_GREEN_NODES_NB);
+ for (i = green; i < green + PATH_GREEN_NODES_NB; i++)
+ {
+ if (!path_blocking (node, i, &d))
+ {
+ neighbors[neighbors_nb].node = i;
+ neighbors[neighbors_nb].weight = d + 1;
+ neighbors_nb++;
+ }
+ }
+ }
+ /* Check if direct path OK. */
+ if (!path_blocking (node, PATH_SRC_NODE_INDEX, &d))
+ {
+ /* Add this neighbor. */
+ neighbors[neighbors_nb].node = PATH_SRC_NODE_INDEX;
+ neighbors[neighbors_nb].weight = d + 1;
+ neighbors_nb++;
+ }
+#if PATH_DEBUG
+ for (i = 0; i < neighbors_nb; i++)
+ DPRINTF (" n %d %d\n", neighbors[i].node, neighbors[i].weight);
+#endif
+ return neighbors_nb;
+}
+
+/** Neighbors callback for green nodes. */
+static uint8_t
+path_astar_neighbor_callback_green (uint8_t node,
+ struct astar_neighbor_t *neighbors)
+{
+ uint8_t neighbors_nb = 0;
+ uint8_t i;
+ uint8_t col = (node - PATH_GRID_NODES_NB) / PATH_GREEN_NODES_NB;
+ int16_t d;
+ /* Check path to grid nodes. */
+ uint8_t grid = col ? PATH_GRID_NODES_NB - 2 * PATH_COLUMN_NODES_NB : 0;
+ for (i = grid; i < grid + 2 * PATH_COLUMN_NODES_NB; i++)
+ {
+ if (!path_blocking (node, i, &d))
+ {
+ neighbors[neighbors_nb].node = i;
+ neighbors[neighbors_nb].weight = d + 1;
+ neighbors_nb++;
+ }
+ }
+ /* Check path to other green nodes. */
+ uint8_t green = PATH_GRID_NODES_NB + (col ? PATH_GREEN_NODES_NB : 0);
+ for (i = green; i < green + PATH_GREEN_NODES_NB; i++)
+ {
+ if (i != node && !path_blocking (node, i, &d))
+ {
+ neighbors[neighbors_nb].node = i;
+ neighbors[neighbors_nb].weight = d + 1;
+ neighbors_nb++;
+ }
+ }
+ /* Check if direct path OK. */
+ if (!path_blocking (node, PATH_SRC_NODE_INDEX, &d))
+ {
+ /* Add this neighbor. */
+ neighbors[neighbors_nb].node = PATH_SRC_NODE_INDEX;
+ neighbors[neighbors_nb].weight = d + 1;
+ neighbors_nb++;
+ }
+#if PATH_DEBUG
+ for (i = 0; i < neighbors_nb; i++)
+ DPRINTF (" n %d %d\n", neighbors[i].node, neighbors[i].weight);
+#endif
+ return neighbors_nb;
+}
+
+/** Neighbors callback for endpoints. */
+static uint8_t
+path_astar_neighbor_callback_endpoints (uint8_t node,
+ struct astar_neighbor_t *neighbors)
+{
+ uint8_t neighbors_nb = 0;
+ uint8_t i;
+ assert (node == PATH_DST_NODE_INDEX);
+ /* Select neighbors in the fixed nodes. */
+ for (i = 0; i < PATH_FIXED_NODES_NB; i++)
+ {
+ /* Discard blocking nodes. */
+ if (!path.valid[i])
+ continue;
+ /* Check if there is an obstacle along the path. */
+ int16_t d;
+ if (path_blocking (PATH_DST_NODE_INDEX, i, &d))
+ continue;
+ /* Add this neighbor. */
+ neighbors[neighbors_nb].node = i;
+ neighbors[neighbors_nb].weight = d + 1;
+ neighbors_nb++;
+ }
+ /* Check if direct path OK. */
+ int16_t d;
+ if (!path_blocking (PATH_DST_NODE_INDEX, PATH_SRC_NODE_INDEX, &d))
+ {
+ /* Add this neighbor. */
+ neighbors[neighbors_nb].node = PATH_SRC_NODE_INDEX;
+ neighbors[neighbors_nb].weight = d + 1;
+ neighbors_nb++;
+ }
+#if PATH_DEBUG
+ for (i = 0; i < neighbors_nb; i++)
+ DPRINTF (" n %d %d\n", neighbors[i].node, neighbors[i].weight);
+#endif
+ return neighbors_nb;
+}
+
+uint8_t
+path_astar_neighbor_callback (uint8_t node,
+ struct astar_neighbor_t *neighbors)
+{
+#if PATH_DEBUG
+ DPRINTF ("neighbor %d\n", node);
+#endif
+ if (node < PATH_GRID_NODES_NB)
+ return path_astar_neighbor_callback_grid (node, neighbors);
+ else if (node < PATH_GRID_NODES_NB + 2 * PATH_GREEN_NODES_NB)
+ return path_astar_neighbor_callback_green (node, neighbors);
+ else
+ return path_astar_neighbor_callback_endpoints (node, neighbors);
+}
+
+uint16_t
+path_astar_heuristic_callback (uint8_t node)
+{
+ /* TODO: a better and faster heuristic can be found, considering that
+ * movement is only allowed on the grid. */
+ vect_t pos;
+ path_pos (node, &pos);
+ return distance_point_point (&pos, &path.endpoints[0]);
+}
diff --git a/digital/io-hub/src/robospierre/path.h b/digital/io-hub/src/robospierre/path.h
new file mode 100644
index 00000000..22a8ead8
--- /dev/null
+++ b/digital/io-hub/src/robospierre/path.h
@@ -0,0 +1,78 @@
+#ifndef path_h
+#define path_h
+/* path.h */
+/* robospierre - Eurobot 2011 AI. {{{
+ *
+ * Copyright (C) 2011 Nicolas Schodet
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * 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 "defs.h"
+
+/** This implement a interface similar to the path module, but adapted for the
+ * special grid of Eurobot 2011. See real path modules for interface comments. */
+
+/** Infinite validity for an obstacle. */
+#define PATH_OBSTACLE_VALID_ALWAYS 0xffff
+
+/** Obstacle. */
+struct path_obstacle_t
+{
+ /** Center. */
+ vect_t c;
+ /** Radius. */
+ uint16_t r;
+ /** Validity counter, when this is zero, the obstacle is ignored. */
+ uint16_t valid;
+};
+
+void
+path_init (void);
+
+void
+path_endpoints (vect_t s, vect_t d);
+
+void
+path_escape (uint8_t factor);
+
+void
+path_obstacle (uint8_t i, vect_t c, uint16_t r, uint8_t factor,
+ uint16_t valid);
+
+void
+path_decay (void);
+
+void
+path_update (void);
+
+uint8_t
+path_get_next (vect_t *p);
+
+#if AC_PATH_REPORT
+
+/** Report computed path. */
+void
+AC_PATH_REPORT_CALLBACK (vect_t *points, uint8_t len,
+ struct path_obstacle_t *obstacles,
+ uint8_t obstacles_nb);
+
+#endif
+
+#endif /* path_h */
diff --git a/digital/io-hub/src/robospierre/pawn_sensor.c b/digital/io-hub/src/robospierre/pawn_sensor.c
new file mode 100644
index 00000000..cc9e6900
--- /dev/null
+++ b/digital/io-hub/src/robospierre/pawn_sensor.c
@@ -0,0 +1,222 @@
+/* pawn_sensor.c */
+/* robospierre - Eurobot 2011 AI. {{{
+ *
+ * Copyright (C) 2011 Nicolas Schodet
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * 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 "common.h"
+#include "defs.h"
+#include "pawn_sensor.h"
+
+#include "asserv.h"
+#include "contact.h"
+#include "logistic.h"
+#include "element.h"
+#include "clamp.h"
+#include "bot.h"
+#include "playground.h"
+#include "codebar.h"
+#include "mimot.h"
+#include "main.h"
+
+#define FSM_NAME AI
+#include "fsm.h"
+#include "fsm_queue.h"
+
+#include "modules/utils/utils.h"
+#include "modules/math/geometry/distance.h"
+
+/* Handle pawn sensors. When a pawn is detected, it can not be taken
+ * directly, but only once it is inside the robot. */
+
+/** Pawn sensor context. */
+struct pawn_sensor_t
+{
+ /** Is there something in front of the sensor? */
+ uint8_t active;
+ /** If active, supposed position of element. */
+ vect_t active_position;
+};
+
+/** Pawn sensor general context. */
+struct pawn_sensor_general_t
+{
+ /** Activate bumpers. */
+ uint8_t bumper_enabled;
+ /** Last bumped element position. */
+ vect_t last_bumped;
+ /** Bumper triggered, wait until the next one. */
+ uint16_t bump_wait;
+};
+
+/** Global contexts. */
+struct pawn_sensor_t pawn_sensor_front, pawn_sensor_back;
+struct pawn_sensor_general_t pawn_sensor_global;
+
+static uint8_t
+pawn_sensor_get_type (uint8_t direction)
+{
+ uint8_t element_type = codebar_get (direction);
+ if (!element_type)
+ element_type = ELEMENT_PAWN;
+ return element_type;
+}
+
+uint8_t
+pawn_sensor_get (uint8_t direction)
+{
+ struct pawn_sensor_t *ctx;
+ uint8_t contact_value, slot;
+ int16_t dist;
+ /* Check direction. */
+ if (direction == DIRECTION_FORWARD)
+ {
+ ctx = &pawn_sensor_front;
+ contact_value = !IO_GET (CONTACT_FRONT_BOTTOM);
+ slot = CLAMP_SLOT_FRONT_BOTTOM;
+ dist = BOT_PAWN_FRONT_DETECTION_THRESHOLD_MM;
+ }
+ else
+ {
+ ctx = &pawn_sensor_back;
+ contact_value = !IO_GET (CONTACT_BACK_BOTTOM);
+ slot = CLAMP_SLOT_BACK_BOTTOM;
+ dist = BOT_PAWN_BACK_DETECTION_THRESHOLD_MM;
+ }
+ /* Handle contact. */
+ if (contact_value)
+ {
+ if (!logistic_global.slots[slot]
+ && logistic_global.moving_to != slot)
+ {
+ position_t robot_position;
+ asserv_get_position (&robot_position);
+ if (ctx->active)
+ {
+ /* In green zone, take it when near enougth from the wall. */
+ if (robot_position.v.x < BOT_GREEN_ELEMENT_DISTANCE_MM + 10
+ || (robot_position.v.x > PG_WIDTH
+ - BOT_GREEN_ELEMENT_DISTANCE_MM - 10))
+ {
+ ctx->active = 0;
+ return pawn_sensor_get_type (direction);
+ }
+ /* Else, take it if near enough from the supposed element
+ * position. */
+ int32_t d = distance_point_point (&ctx->active_position,
+ &robot_position.v);
+ if (d < BOT_PAWN_TAKING_DISTANCE_MM)
+ {
+ ctx->active = 0;
+ return pawn_sensor_get_type (direction);
+ }
+ else if (d > UTILS_ABS (dist))
+ {
+ vect_from_polar_uf016 (&ctx->active_position, dist,
+ robot_position.a);
+ vect_translate (&ctx->active_position, &robot_position.v);
+ }
+ }
+ else
+ {
+ ctx->active = 1;
+ vect_from_polar_uf016 (&ctx->active_position, dist,
+ robot_position.a);
+ vect_translate (&ctx->active_position, &robot_position.v);
+ }
+ }
+ }
+ else
+ {
+ ctx->active = 0;
+ }
+ return 0;
+}
+
+void
+pawn_sensor_bumper (uint8_t bumped, uint16_t dx, uint16_t dy)
+{
+ uint8_t i;
+ if (bumped)
+ {
+ /* Compute pawn position. */
+ position_t robot_pos;
+ asserv_get_position (&robot_pos);
+ vect_t bumped_pawn;
+ bumped_pawn.x = dx;
+ bumped_pawn.y = dy;
+ vect_rotate_uf016 (&bumped_pawn, robot_pos.a);
+ vect_translate (&bumped_pawn, &robot_pos.v);
+ /* Do not count if out of the table. */
+ if (bumped_pawn.x < 400 + BOT_ELEMENT_RADIUS
+ && bumped_pawn.x >= PG_WIDTH - 400 - BOT_ELEMENT_RADIUS
+ && bumped_pawn.y < BOT_ELEMENT_RADIUS
+ && bumped_pawn.y >= PG_WIDTH - BOT_ELEMENT_RADIUS)
+ return;
+ /* Do not count the opponent as a pawn. */
+ for (i = 0; i < main_obstacles_nb; i++)
+ {
+ uint16_t dist = distance_point_point (&bumped_pawn,
+ &main_obstacles_pos[i]);
+ if (dist < 300 + BOT_ELEMENT_RADIUS)
+ return;
+ }
+ /* OK, take it. */
+ pawn_sensor_global.last_bumped = bumped_pawn;
+ fsm_queue_post_event (FSM_EVENT (AI, top_bumper));
+ pawn_sensor_global.bump_wait = 3 * 250;
+ }
+}
+
+void
+pawn_sensor_update (void)
+{
+#define BUMPER_FRONT_LEFT _BV (6)
+#define BUMPER_FRONT_RIGHT _BV (7)
+#define BUMPER_BACK_RIGHT _BV (5)
+#define BUMPER_BACK_LEFT _BV (4)
+ if (pawn_sensor_global.bumper_enabled)
+ {
+ if (pawn_sensor_global.bump_wait)
+ pawn_sensor_global.bump_wait--;
+ else
+ {
+ uint8_t bumpers = mimot_get_input ();
+ pawn_sensor_bumper (!(bumpers & BUMPER_FRONT_LEFT), 120, 265);
+ pawn_sensor_bumper (!(bumpers & BUMPER_FRONT_RIGHT), 120, -265);
+ pawn_sensor_bumper (!(bumpers & BUMPER_BACK_RIGHT), -120, -265);
+ pawn_sensor_bumper (!(bumpers & BUMPER_BACK_LEFT), -120, 265);
+ }
+ }
+}
+
+void
+pawn_sensor_bumper_enable (uint8_t enabled)
+{
+ pawn_sensor_global.bumper_enabled = enabled;
+}
+
+vect_t
+pawn_sensor_get_last_bumped (void)
+{
+ return pawn_sensor_global.last_bumped;
+}
+
diff --git a/digital/io-hub/src/robospierre/pawn_sensor.h b/digital/io-hub/src/robospierre/pawn_sensor.h
new file mode 100644
index 00000000..8d6d2651
--- /dev/null
+++ b/digital/io-hub/src/robospierre/pawn_sensor.h
@@ -0,0 +1,45 @@
+#ifndef pawn_sensor_h
+#define pawn_sensor_h
+/* pawn_sensor.h */
+/* robospierre - Eurobot 2011 AI. {{{
+ *
+ * Copyright (C) 2011 Nicolas Schodet
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * 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.
+ *
+ * }}} */
+
+/** Update sensor state and return the element type if an element is ready to
+ * be taken. */
+uint8_t
+pawn_sensor_get (uint8_t direction);
+
+/** Update pawn sensors. */
+void
+pawn_sensor_update (void);
+
+/** Enable bumpers. */
+void
+pawn_sensor_bumper_enable (uint8_t enabled);
+
+/** Return last bumped pawn. */
+vect_t
+pawn_sensor_get_last_bumped (void);
+
+#endif /* pawn_sensor_h */
diff --git a/digital/io-hub/src/robospierre/playground_2011.h b/digital/io-hub/src/robospierre/playground_2011.h
new file mode 100644
index 00000000..a9963e34
--- /dev/null
+++ b/digital/io-hub/src/robospierre/playground_2011.h
@@ -0,0 +1,33 @@
+#ifndef playground_2011_h
+#define playground_2011_h
+/* playground_2011.h */
+/* robospierre - Eurobot 2011 AI. {{{
+ *
+ * Copyright (C) 2011 Nicolas Schodet
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * 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 "playground.h"
+
+/** Width of a green zone. */
+#define PG_GREEN_WIDTH_MM 400
+
+#endif /* playground_2011_h */
diff --git a/digital/io-hub/src/robospierre/radar_defs.c b/digital/io-hub/src/robospierre/radar_defs.c
new file mode 100644
index 00000000..85f015e1
--- /dev/null
+++ b/digital/io-hub/src/robospierre/radar_defs.c
@@ -0,0 +1,46 @@
+/* radar_defs.c */
+/* io - Input & Output with Artificial Intelligence (ai) support on AVR. {{{
+ *
+ * Copyright (C) 2010 Nicolas Schodet
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * 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 "common.h"
+#include "radar.h"
+
+#include "modules/devices/usdist/usdist.h"
+#include "playground.h"
+
+/** Define radar configuration. */
+struct radar_sensor_t radar_sensors[RADAR_SENSOR_NB] = {
+ { &usdist_mm[0], { 20, 20 }, G_ANGLE_UF016_DEG (10) },
+ { &usdist_mm[1], { 20, -20 }, G_ANGLE_UF016_DEG (-10) },
+ { &usdist_mm[2], { -20, -20 }, G_ANGLE_UF016_DEG (180 + 10) },
+ { &usdist_mm[3], { -20, 20 }, G_ANGLE_UF016_DEG (180 - 10) },
+};
+
+/** Define exclusion area (considered as invalid point). */
+uint8_t
+radar_valid (vect_t p)
+{
+ return p.x >= RADAR_MARGIN_MM && p.x < PG_WIDTH - RADAR_MARGIN_MM
+ && p.y >= RADAR_MARGIN_MM && p.y < PG_LENGTH - RADAR_MARGIN_MM;
+}
+
diff --git a/digital/io-hub/src/robospierre/radar_defs.h b/digital/io-hub/src/robospierre/radar_defs.h
new file mode 100644
index 00000000..5f6a2a73
--- /dev/null
+++ b/digital/io-hub/src/robospierre/radar_defs.h
@@ -0,0 +1,41 @@
+#ifndef radar_defs_h
+#define radar_defs_h
+/* radar_defs.h */
+/* io - Input & Output with Artificial Intelligence (ai) support on AVR. {{{
+ *
+ * Copyright (C) 2010 Nicolas Schodet
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * 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.
+ *
+ * }}} */
+
+#define RADAR_OBSTACLE_EDGE_RADIUS_MM 40
+#define RADAR_OBSTACLE_RADIUS_MM 150
+#define RADAR_STOP_MM 350
+#define RADAR_CLEARANCE_MM 100
+#define RADAR_EPSILON_MM 70
+
+#define RADAR_SENSOR_NB 4
+
+#define RADAR_SENSOR_FRONT_FIRST 0
+#define RADAR_SENSOR_FRONT_NB 2
+#define RADAR_SENSOR_BACK_FIRST 2
+#define RADAR_SENSOR_BACK_NB 2
+
+#endif /* radar_defs_h */
diff --git a/digital/io-hub/src/robospierre/simu.host.c b/digital/io-hub/src/robospierre/simu.host.c
index 8f4019aa..70055d7d 100644
--- a/digital/io-hub/src/robospierre/simu.host.c
+++ b/digital/io-hub/src/robospierre/simu.host.c
@@ -28,10 +28,25 @@
#include "modules/utils/utils.h"
#include "modules/host/host.h"
#include "modules/host/mex.h"
+#include "modules/adc/adc.h"
+#include "modules/path/path.h"
#include "io.h"
/** AVR registers. */
-uint8_t PINE;
+uint8_t PORTA, DDRA, PINA, PINE, PINF;
+
+/** Message types. */
+uint8_t simu_mex_pos_report;
+uint8_t simu_mex_path;
+
+static void
+simu_adc_handle (void *user, mex_msg_t *msg)
+{
+ uint8_t index;
+ uint16_t value;
+ mex_msg_pop (msg, "BH", &index, &value);
+ adc_values[index] = value;
+}
/** Initialise simulation. */
void
@@ -40,6 +55,10 @@ simu_init (void)
const char *mex_instance;
mex_node_connect ();
mex_instance = host_get_instance ("io-hub0", 0);
+ uint8_t mtype = mex_node_reservef ("%s:adc", mex_instance);
+ mex_node_register (mtype, simu_adc_handle, 0);
+ simu_mex_pos_report = mex_node_reservef ("%s:pos-report", mex_instance);
+ simu_mex_path = mex_node_reservef ("%s:path", mex_instance);
}
/** Make a simulation step. */
@@ -62,3 +81,27 @@ timer_wait (void)
return 0;
}
+/** Send computed path. */
+void
+simu_send_path (vect_t *points, uint8_t len,
+ struct path_obstacle_t *obstacles, uint8_t obstacles_nb)
+{
+ int i;
+ mex_msg_t *m;
+ m = mex_msg_new (simu_mex_path);
+ for (i = 0; i < len; i++)
+ mex_msg_push (m, "hh", points[i].x, points[i].y);
+ mex_node_send (m);
+}
+
+void
+simu_send_pos_report (vect_t *pos, uint8_t pos_nb, uint8_t id)
+{
+ mex_msg_t *m;
+ m = mex_msg_new (simu_mex_pos_report);
+ mex_msg_push (m, "b", id);
+ for (; pos_nb; pos++, pos_nb--)
+ mex_msg_push (m, "hh", pos->x, pos->y);
+ mex_node_send (m);
+}
+
diff --git a/digital/io-hub/src/robospierre/simu.host.h b/digital/io-hub/src/robospierre/simu.host.h
index 4b461e86..6224e345 100644
--- a/digital/io-hub/src/robospierre/simu.host.h
+++ b/digital/io-hub/src/robospierre/simu.host.h
@@ -24,13 +24,23 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* }}} */
+#include "defs.h"
#ifdef HOST
-extern uint8_t PINE;
+extern uint8_t PORTA, DDRA, PINA, PINE, PINF;
+
+/** Send general purpose positions to indicate computation results.
+ * - pos: array of positions to report.
+ * - pos_nb: number of elements in the array.
+ * - id: identifier so that several unrelated positions could be reported. */
+void
+simu_send_pos_report (vect_t *pos, uint8_t pos_nb, uint8_t id);
#else /* !defined (HOST) */
+#define simu_send_pos_report(pos, pos_nb, id) ((void) 0)
+
#endif /* !defined (HOST) */
#endif /* simu_host_h */
diff --git a/digital/io-hub/src/robospierre/test_element.c b/digital/io-hub/src/robospierre/test_element.c
new file mode 100644
index 00000000..e200902a
--- /dev/null
+++ b/digital/io-hub/src/robospierre/test_element.c
@@ -0,0 +1,376 @@
+/* test_element.c */
+/* io - Input & Output with Artificial Intelligence (ai) support on AVR. {{{
+ *
+ * Copyright (C) 2011 Jérôme Jutteau
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * 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 "common.h"
+#include "element.h"
+
+#include "chrono.h"
+
+#include <stdio.h>
+
+#define TEST_PRINT_TYPE_SCORE_PICK 0
+#define TEST_PRINT_TYPE_SCORE_UNLOAD 1
+#define TEST_PRINT_TYPE_ELEMENT 2
+#define TEST_PRINT_TYPE_BONUS_UNLOAD 3
+#define TEST_PRINT_TYPE_BONUS_LOAD 4
+int test_print_type_ = TEST_PRINT_TYPE_SCORE_PICK;
+position_t test_robot_pos_ = {{0, 2100}, 1};
+
+uint8_t PINE;
+
+enum team_color_e team_color;
+
+/** Stubbed chrono. */
+uint32_t test_chrono_ms;
+
+void
+chrono_init (void)
+{
+ test_chrono_ms = CHRONO_MATCH_DURATION_MS;
+}
+
+uint32_t
+chrono_remaining_time (void)
+{
+ return test_chrono_ms;
+}
+
+uint8_t
+test_element_convert (const char *l, uint8_t number)
+{
+ switch (l[0])
+ {
+ case 'A':
+ switch (number)
+ {
+ case 1: return (31);
+ case 3: return (32);
+ case 5: return (33);
+ case 7: return (34);
+ case 9: return (35);
+ case 11: return (36);
+ }
+ case 'B':
+ switch (number)
+ {
+ case 2: return (0);
+ case 4: return (2);
+ case 8: return (3);
+ case 10: return (1);
+ }
+ case 'C':
+ switch (number)
+ {
+ case 1: return (37);
+ case 3: return (38);
+ case 5: return (39);
+ case 7: return (40);
+ case 9: return (41);
+ case 11: return (42);
+ }
+ case 'D':
+ switch (number)
+ {
+ case 0: return (21);
+ case 2: return (4);
+ case 4: return (6);
+ case 8: return (7);
+ case 10: return (5);
+ case 12: return (22);
+ }
+ case 'E':
+ switch (number)
+ {
+ case 1: return (43);
+ case 3: return (44);
+ case 5: return (45);
+ case 7: return (46);
+ case 9: return (47);
+ case 11: return (48);
+ }
+ case 'F':
+ switch (number)
+ {
+ case 0: return (23);
+ case 12: return (24);
+ }
+ case 'G':
+ switch (number)
+ {
+ case 2: return (8);
+ case 4: return (10);
+ case 6: return (20);
+ case 8: return (11);
+ case 10: return (9);
+ }
+ case 'H':
+ switch (number)
+ {
+ case 0: return (25);
+ case 1: return (49);
+ case 3: return (50);
+ case 5: return (51);
+ case 7: return (52);
+ case 9: return (53);
+ case 11: return (54);
+ case 12: return (26);
+ }
+ case 'I':
+ switch (number) /*12*/
+ {
+ case 2: return (12);
+ case 4: return (14);
+ case 8: return (15);
+ case 10: return (13);
+ }
+ case 'J':
+ switch (number)
+ {
+ case 0: return (27);
+ case 12: return (28);
+ }
+ case 'K':
+ switch (number)
+ {
+ case 1: return (55);
+ case 3: return (56);
+ case 5: return (57);
+ case 7: return (58);
+ case 9: return (59);
+ case 11: return (60);
+ }
+ case 'L':
+ switch (number)
+ {
+ case 2: return (16);
+ case 4: return (18);
+ case 8: return (19);
+ case 10: return (17);
+ }
+ case 'M':
+ switch (number)
+ {
+ case 0: return (29);
+ case 1: return (61);
+ case 3: return (62);
+ case 5: return (63);
+ case 7: return (64);
+ case 9: return (65);
+ case 11: return (66);
+ case 12: return (30);
+ }
+ }
+ return 0;
+}
+
+long int
+test_element_get_score (uint8_t element_id)
+{
+ if (test_print_type_ == TEST_PRINT_TYPE_SCORE_PICK)
+ return (long int) element_score (test_robot_pos_, element_id);
+ else if (test_print_type_ == TEST_PRINT_TYPE_SCORE_UNLOAD)
+ return (long int) element_unload_score (test_robot_pos_, element_id);
+ else if (test_print_type_ == TEST_PRINT_TYPE_BONUS_LOAD)
+ {
+ element_t e = element_get (element_id);
+ return (long int) e.bonus_load;
+ }
+ else if (test_print_type_ == TEST_PRINT_TYPE_BONUS_UNLOAD)
+ {
+ element_t e = element_get (element_id);
+ return (long int) e.bonus_unload;
+ }
+ else
+ return (long int) element_table[element_id].type;
+}
+
+#define p(l, n) (test_element_print (#l, n))
+long int
+test_element_print (const char *l, uint8_t number)
+{
+ return test_element_get_score (test_element_convert (l, number));
+}
+
+void
+test_element_print_table ()
+{
+ printf ("parameters:\n");
+ printf ("- robot_pos = (%u, %u)\n", test_robot_pos_.v.x, test_robot_pos_.v.y);
+ printf ("- side = %u\n", team_color);
+ printf (" _____0_________1_____2____3____4____5____6____7____8____9___10___11_________12_____ \n");
+ printf (" | | | | | | | | |\n");
+ printf (" | | | | | | | | |\n");
+ printf ("A| Red | %5ld | %5ld | %5ld | %5ld | %5ld | %5ld | Blue |\n", p (A, 1), p (A, 3), p (A, 5), p(A, 7), p (A, 9), p (A, 11));
+ printf (" | | | | | | | | |\n");
+ printf ("B| |--------%5ld-----%5ld------+--------%5ld-----%5ld------| |\n", p (B, 2), p (B, 4), p (B, 8), p (B, 10));
+ printf (" |-----------+ | | | | | +-----------|\n");
+ printf (" | | | [B] | | | [R] | | |\n");
+ printf ("C| | %5ld | %5ld | %5ld | %5ld | %5ld | %5ld | |\n", p (C, 1), p (C, 3), p (C, 5), p (C, 7), p(C, 9), p (C, 11));
+ printf (" | | | | | | | | |\n");
+ printf ("D| %5ld |--------%5ld-----%5ld------+--------%5ld-----%5ld------| %5ld |\n", p (D, 0), p (D, 2), p (D, 4), p (D, 8), p (D, 10), p (D, 12));
+ printf (" | | | | | | | | |\n");
+ printf (" | | | | | | | | |\n");
+ printf ("E| | %5ld | %5ld | %5ld | %5ld | %5ld | %5ld | |\n", p (E, 1), p (E, 3), p (E, 5), p (E, 7), p(E, 9), p(E, 11));
+ printf ("F| %5ld | | | | | | | %5ld |\n", p (F, 0), p(F, 12));
+ printf ("G| |--------%5ld-----%5ld-----%5ld-----%5ld-----%5ld------| |\n", p (G, 2), p (G, 4), p(G, 6), p (G, 8), p (G, 10));
+ printf (" | | | | | | | | |\n");
+ printf (" | | | [B] | | | [R] | | |\n");
+ printf ("H| %5ld | %5ld | %5ld | %5ld | %5ld | %5ld | %5ld | %5ld |\n", p(H, 0), p (H, 1), p (H, 3), p (H, 5), p (H, 7), p(H, 9), p(H, 11), p(H, 12));
+ printf (" | | | | | | | | |\n");
+ printf ("I| |--------%5ld-----%5ld------+--------%5ld-----%5ld------| |\n", p (I, 2), p (I, 4), p (I, 8), p (I, 10));
+ printf (" | | | | | | | | |\n");
+ printf ("J| %5ld | | | | | | | %5ld |\n", p (J, 0), p(J, 12));
+ printf ("K| | %5ld | %5ld | %5ld | %5ld | %5ld | %5ld | |\n", p (K, 1), p (K, 3), p (K, 5), p (K, 7), p(K, 9), p(K, 11));
+ printf (" | | | | | | | | |\n");
+ printf ("L| |--------%5ld-----%5ld------+--------%5ld-----%5ld------| |\n", p (L, 2), p (L, 4), p (L, 8), p (L, 10));
+ printf (" | | | | | | | | |\n");
+ printf ("M| %5ld | %5ld | %5ld | %5ld | %5ld | %5ld | %5ld | %5ld |\n", p(M, 0), p (M, 1), p (M, 3), p (M, 5), p (M, 7), p(M, 9), p(M, 11), p(M, 12));
+ printf (" | |###################| [R] | [B] |###################| |\n");
+ printf (" | |###################| | |###################| |\n");
+ printf (" +-----------|###################+---------+---------+###################+-----------+\n");
+}
+
+int main ()
+{
+ int exit = 0;
+ char cmd;
+ int x;
+ char y[10], z[10];
+ int type = 0;
+ chrono_init ();
+
+ while (!exit)
+ {
+ element_init ();
+ printf ("\ncommands:\n");
+ printf ("s: print scores, ");
+ printf ("a: print load bonus, ");
+ printf ("p: print unload scores, ");
+ printf ("z: print unload bonus, ");
+ printf ("e: print elements, ");
+ printf ("t: set match time, ");
+ printf ("c: set robot side, ");
+ printf ("r: set robot position, ");
+ printf ("i: pick up an element, ");
+ printf ("n: indicate there is no element, ");
+ printf ("m: id of nearest element, ");
+ printf ("g: get position and angle of desired element,");
+ printf ("u: call I like green,");
+ printf ("q: quit\n");
+ printf ("your choice: ");
+ fflush (stdin);
+ scanf ("%c", &cmd);
+ switch (cmd)
+ {
+ case 's':
+ test_print_type_ = TEST_PRINT_TYPE_SCORE_PICK;
+ test_element_print_table ();
+ break;
+ case 'a':
+ test_print_type_ = TEST_PRINT_TYPE_BONUS_LOAD;
+ test_element_print_table ();
+ break;
+ case 'p':
+ test_print_type_ = TEST_PRINT_TYPE_SCORE_UNLOAD;
+ test_element_print_table ();
+ break;
+ case 'z':
+ test_print_type_ = TEST_PRINT_TYPE_BONUS_UNLOAD;
+ test_element_print_table ();
+ break;
+ case 'e':
+ test_print_type_ = TEST_PRINT_TYPE_ELEMENT;
+ test_element_print_table ();
+ break;
+ case 't':
+ printf ("set match time: ");
+ scanf ("%i", &test_chrono_ms);
+ break;
+ case 'c':
+ if (team_color == TEAM_COLOR_RIGHT)
+ team_color = TEAM_COLOR_LEFT;
+ else
+ team_color = TEAM_COLOR_RIGHT;
+ team_color ^= TEAM_COLOR_RIGHT;
+ printf ("Side is now %u\n", team_color);
+ break;
+ case 'r':
+ printf ("set robot position:\n");
+ printf ("number: ");
+ scanf ("%i", &x);
+ printf ("letter: ");
+ scanf ("%s", y);
+ test_robot_pos_.v = element_table[test_element_convert (y, x)].pos;
+ break;
+ case 'i':
+ printf ("pick up an element:\n");
+ printf ("number: ");
+ scanf ("%i", &x);
+ printf ("letter: ");
+ scanf ("%s", y);
+ printf ("type: (P=Pawn Q=Queen K=King) ");
+ fflush (stdin);
+ scanf ("%s", z);
+ if (z[0] == 'P')
+ type = ELEMENT_PAWN;
+ else if (z[0] == 'Q')
+ type = ELEMENT_QUEEN;
+ else if (z[0] == 'K')
+ type = ELEMENT_KING;
+ else
+ printf ("Unknown !\n");
+ element_taken (test_element_convert (y, x), type);
+ break;
+ case 'n':
+ printf ("indicate there no element\n");
+ printf ("number: ");
+ scanf ("%i", &x);
+ printf ("letter: ");
+ scanf ("%s", y);
+ element_not_here (test_element_convert (y, x));
+ break;
+ case 'm':
+ printf ("nearest element id from robot: %u\n",
+ element_nearest_element_id (test_robot_pos_));
+ break;
+ case 'g':
+ printf ("element id: ");
+ scanf ("%i", &x);
+ vect_t pos = element_get_pos (x);
+ printf ("x: %u y: %u\n", pos.x, pos.y);
+ break;
+ case 'u':
+ printf ("call I like green ...");
+ element_i_like_green ();
+ break;
+ case 'q':
+ exit = 1;
+ break;
+ }
+ fflush (stdin);
+ scanf ("%c", &cmd);
+ }
+ return 0;
+}
+
diff --git a/digital/io-hub/src/robospierre/top.c b/digital/io-hub/src/robospierre/top.c
new file mode 100644
index 00000000..93fb447f
--- /dev/null
+++ b/digital/io-hub/src/robospierre/top.c
@@ -0,0 +1,476 @@
+/* top.c */
+/* robospierre - Eurobot 2011 AI. {{{
+ *
+ * Copyright (C) 2011 Nicolas Schodet
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * 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 "common.h"
+#include "io.h"
+
+#include "playground_2011.h"
+#include "asserv.h"
+
+#define FSM_NAME AI
+#include "fsm.h"
+
+#include "logistic.h"
+#include "move.h"
+#include "chrono.h"
+#include "pawn_sensor.h"
+#include "contact.h"
+
+/*
+ * Here is the top FSM. This FSM is suppose to give life to the robot with an
+ * impression of intelligence... Well...
+ */
+
+#define TOP_PAWN_TIME 45000l
+
+FSM_INIT
+
+FSM_STATES (
+ /* Initial state. */
+ TOP_START,
+ /* Going out of start area. */
+ TOP_GOING_OUT1,
+ /* Problem going out, wait before retry. */
+ TOP_GOING_OUT1_BLOCK_WAIT,
+ /* Going out, first pawn emplacement. */
+ TOP_GOING_OUT2,
+ /* Problem going out, wait before retry. */
+ TOP_GOING_OUT2_BLOCK_WAIT,
+
+ TOP_GOING_TO_DROP,
+ TOP_GOING_TO_ELEMENT,
+ /* Waiting clamp has finished its work. */
+ TOP_WAITING_CLAMP,
+ /* Unblocking: waiting a little bit. */
+ TOP_UNBLOCKING_SHAKE_WAIT,
+ /* Unblocking: shaking. */
+ TOP_UNBLOCKING_SHAKE,
+ /* Waiting construction is ready to drop. */
+ TOP_WAITING_READY,
+ /* Dropping, opening the doors. */
+ TOP_DROP_DROPPING,
+ /* Dropping, clearing so that doors can be closed. */
+ TOP_DROP_CLEARING)
+
+FSM_EVENTS (
+ /* Bumpers have seen something. */
+ top_bumper)
+
+FSM_START_WITH (TOP_START)
+
+/** Top context. */
+struct top_t
+{
+ /** Target element. */
+ uint8_t target_element_id;
+ /** Chaos counter. */
+ uint8_t chaos;
+ /** Broken clamp. */
+ uint8_t broken;
+ /** Saved, direction when picking element. */
+ uint8_t go_to_element_direction;
+ /** Return to our green zone again. */
+ uint8_t green_again;
+};
+
+/** Global context. */
+struct top_t top_global;
+#define ctx top_global
+
+FSM_TRANS (TOP_START, init_start_round, TOP_GOING_OUT1)
+{
+ element_init ();
+ ctx.green_again = 3;
+ asserv_goto (PG_X (PG_GREEN_WIDTH_MM + 100),
+ PG_Y (PG_LENGTH - 200), 0);
+ return FSM_NEXT (TOP_START, init_start_round);
+}
+
+FSM_TRANS (TOP_GOING_OUT1, robot_move_success, TOP_GOING_OUT2)
+{
+ asserv_goto (PG_X (1500 - 2 * 350), PG_Y (PG_LENGTH - 350), 0);
+ return FSM_NEXT (TOP_GOING_OUT1, robot_move_success);
+}
+
+FSM_TRANS (TOP_GOING_OUT1, robot_move_failure, TOP_GOING_OUT1_BLOCK_WAIT)
+{
+ return FSM_NEXT (TOP_GOING_OUT1, robot_move_failure);
+}
+
+FSM_TRANS_TIMEOUT (TOP_GOING_OUT1_BLOCK_WAIT, 250, TOP_GOING_OUT1)
+{
+ asserv_goto (PG_X (PG_GREEN_WIDTH_MM + 100),
+ PG_Y (PG_LENGTH - 200 - (++ctx.chaos % 4) * 10), 0);
+ return FSM_NEXT_TIMEOUT (TOP_GOING_OUT1_BLOCK_WAIT);
+}
+
+static uint8_t
+top_prepare_level (void)
+{
+ if (ctx.broken)
+ return 3;
+ else if (logistic_global.need_prepare
+ || chrono_remaining_time () < TOP_PAWN_TIME)
+ return 2;
+ else
+ return 1;
+}
+
+static void
+top_go_this_element (vect_t pos, int16_t shorten)
+{
+ ctx.go_to_element_direction = logistic_global.collect_direction;
+ uint8_t backward = logistic_global.collect_direction == DIRECTION_FORWARD
+ ? 0 : ASSERV_BACKWARD;
+ move_start_noangle (pos, backward, shorten);
+}
+
+static uint8_t
+top_go_element (void)
+{
+ position_t robot_pos;
+ asserv_get_position (&robot_pos);
+ ctx.target_element_id = element_best (robot_pos);
+ element_t e = element_get (ctx.target_element_id);
+ if (!ctx.broken)
+ {
+ if (e.attr & ELEMENT_GREEN)
+ {
+ logistic_global.prepare = 0;
+ pawn_sensor_bumper_enable (0);
+ }
+ else
+ {
+ logistic_global.prepare = top_prepare_level ();
+ pawn_sensor_bumper_enable (1);
+ }
+ }
+ vect_t element_pos = element_get_pos (ctx.target_element_id);
+ top_go_this_element (element_pos, 0);
+ return 1;
+}
+
+static uint8_t
+top_go_drop (void)
+{
+ position_t robot_pos;
+ asserv_get_position (&robot_pos);
+ ctx.target_element_id = element_unload_best (robot_pos);
+ position_t drop_pos;
+ drop_pos.v = element_get_pos (ctx.target_element_id);
+ if (!ctx.broken)
+ logistic_global.prepare = top_prepare_level ();
+ pawn_sensor_bumper_enable (0);
+ uint8_t backward = logistic_global.collect_direction == DIRECTION_FORWARD
+ ? 0 : ASSERV_BACKWARD;
+ /* Go above or below the drop point. */
+ if (drop_pos.v.y < 350)
+ {
+ /* Protected zone. */
+ drop_pos.v.x = PG_WIDTH / 2;
+ drop_pos.v.y = 350;
+ drop_pos.a = PG_A_DEG (45);
+ }
+ else if (drop_pos.v.y > PG_LENGTH / 2)
+ {
+ drop_pos.v.y -= 350 / 2;
+ drop_pos.a = PG_A_DEG (-90);
+ }
+ else
+ {
+ drop_pos.v.y += 350 / 2;
+ drop_pos.a = PG_A_DEG (90);
+ }
+ if (logistic_global.collect_direction == DIRECTION_BACKWARD)
+ drop_pos.a += POSITION_A_DEG (180);
+ /* Go! */
+ move_start (drop_pos, backward);
+ return 0;
+}
+
+static uint8_t
+top_decision (void)
+{
+ /* If we can make a tower. */
+ if (logistic_global.construct_possible == 1
+ || ((ctx.broken || chrono_remaining_time () < TOP_PAWN_TIME)
+ && logistic_global.construct_possible == 2))
+ return top_go_drop ();
+ if (logistic_global.need_prepare)
+ {
+ clamp_prepare (top_prepare_level ());
+ return top_go_drop ();
+ }
+ else
+ return top_go_element ();
+}
+
+FSM_TRANS (TOP_GOING_OUT2, robot_move_success,
+ clamp_working, TOP_WAITING_CLAMP,
+ drop, TOP_GOING_TO_DROP,
+ element, TOP_GOING_TO_ELEMENT)
+{
+ if (clamp_working ())
+ return FSM_NEXT (TOP_GOING_TO_ELEMENT, move_success, clamp_working);
+ switch (top_decision ())
+ {
+ default: return FSM_NEXT (TOP_GOING_OUT2, robot_move_success, drop);
+ case 1: return FSM_NEXT (TOP_GOING_OUT2, robot_move_success, element);
+ }
+}
+
+FSM_TRANS (TOP_GOING_OUT2, robot_move_failure, TOP_GOING_OUT2_BLOCK_WAIT)
+{
+ return FSM_NEXT (TOP_GOING_OUT2, robot_move_failure);
+}
+
+FSM_TRANS_TIMEOUT (TOP_GOING_OUT2_BLOCK_WAIT, 250,
+ clamp_working, TOP_WAITING_CLAMP,
+ drop, TOP_GOING_TO_DROP,
+ element, TOP_GOING_TO_ELEMENT)
+{
+ if (clamp_working ())
+ return FSM_NEXT_TIMEOUT (TOP_GOING_OUT2_BLOCK_WAIT, clamp_working);
+ switch (top_decision ())
+ {
+ default: return FSM_NEXT_TIMEOUT (TOP_GOING_OUT2_BLOCK_WAIT, drop);
+ case 1: return FSM_NEXT_TIMEOUT (TOP_GOING_OUT2_BLOCK_WAIT, element);
+ }
+}
+
+FSM_TRANS (TOP_GOING_TO_DROP, move_success,
+ ready, TOP_DROP_DROPPING,
+ wait_clamp, TOP_WAITING_READY)
+{
+ if (logistic_global.ready)
+ {
+ if (clamp_drop (logistic_global.collect_direction))
+ return FSM_NEXT (TOP_GOING_TO_DROP, move_success, ready);
+ else
+ return FSM_NEXT (TOP_GOING_TO_DROP, move_success, wait_clamp);
+ }
+ else
+ {
+ clamp_prepare (top_prepare_level ());
+ return FSM_NEXT (TOP_GOING_TO_DROP, move_success, wait_clamp);
+ }
+}
+
+FSM_TRANS (TOP_GOING_TO_DROP, move_failure,
+ clamp_working, TOP_WAITING_CLAMP,
+ drop, TOP_GOING_TO_DROP,
+ element, TOP_GOING_TO_ELEMENT)
+{
+ if (ctx.target_element_id != 0xff)
+ element_failure (ctx.target_element_id);
+ if (clamp_working ())
+ return FSM_NEXT (TOP_GOING_TO_DROP, move_failure, clamp_working);
+ switch (top_decision ())
+ {
+ default: return FSM_NEXT (TOP_GOING_TO_DROP, move_failure, drop);
+ case 1: return FSM_NEXT (TOP_GOING_TO_DROP, move_failure, element);
+ }
+}
+
+FSM_TRANS (TOP_GOING_TO_DROP, clamp_working, TOP_WAITING_CLAMP)
+{
+ move_stop ();
+ return FSM_NEXT (TOP_GOING_TO_DROP, clamp_working);
+}
+
+FSM_TRANS (TOP_GOING_TO_ELEMENT, move_success,
+ clamp_working, TOP_WAITING_CLAMP,
+ drop, TOP_GOING_TO_DROP,
+ element, TOP_GOING_TO_ELEMENT)
+{
+ if (ctx.target_element_id != 0xff)
+ element_failure (ctx.target_element_id); /* Do not take this one again. */
+ if (clamp_working ())
+ return FSM_NEXT (TOP_GOING_TO_ELEMENT, move_success, clamp_working);
+ if (ctx.green_again)
+ {
+ ctx.green_again--;
+ if (ctx.green_again == 0)
+ element_no_more_green ();
+ }
+ switch (top_decision ())
+ {
+ default: return FSM_NEXT (TOP_GOING_TO_ELEMENT, move_success, drop);
+ case 1: return FSM_NEXT (TOP_GOING_TO_ELEMENT, move_success, element);
+ }
+}
+
+FSM_TRANS (TOP_GOING_TO_ELEMENT, move_failure,
+ clamp_working, TOP_WAITING_CLAMP,
+ drop, TOP_GOING_TO_DROP,
+ element, TOP_GOING_TO_ELEMENT)
+{
+ if (ctx.target_element_id != 0xff)
+ element_failure (ctx.target_element_id);
+ if (clamp_working ())
+ return FSM_NEXT (TOP_GOING_TO_ELEMENT, move_failure, clamp_working);
+ if (ctx.green_again)
+ {
+ ctx.green_again--;
+ if (ctx.green_again == 0)
+ element_no_more_green ();
+ }
+ switch (top_decision ())
+ {
+ default: return FSM_NEXT (TOP_GOING_TO_ELEMENT, move_failure, drop);
+ case 1: return FSM_NEXT (TOP_GOING_TO_ELEMENT, move_failure, element);
+ }
+}
+
+FSM_TRANS (TOP_GOING_TO_ELEMENT, clamp_working, TOP_WAITING_CLAMP)
+{
+ move_stop ();
+ if (ctx.green_again)
+ {
+ ctx.green_again--;
+ if (ctx.green_again == 0)
+ element_no_more_green ();
+ }
+ return FSM_NEXT (TOP_GOING_TO_ELEMENT, clamp_working);
+}
+
+FSM_TRANS (TOP_GOING_TO_ELEMENT, top_bumper, TOP_GOING_TO_ELEMENT)
+{
+ if (!ctx.broken)
+ logistic_global.prepare = top_prepare_level ();
+ move_stop ();
+ ctx.target_element_id = 0xff;
+ top_go_this_element (pawn_sensor_get_last_bumped (), BOT_ELEMENT_RADIUS - 50);
+ return FSM_NEXT (TOP_GOING_TO_ELEMENT, top_bumper);
+}
+
+FSM_TRANS (TOP_WAITING_CLAMP, clamp_done,
+ drop, TOP_GOING_TO_DROP,
+ element, TOP_GOING_TO_ELEMENT)
+{
+ switch (top_decision ())
+ {
+ default: return FSM_NEXT (TOP_WAITING_CLAMP, clamp_done, drop);
+ case 1: return FSM_NEXT (TOP_WAITING_CLAMP, clamp_done, element);
+ }
+}
+
+FSM_TRANS (TOP_WAITING_CLAMP, clamp_blocked, TOP_UNBLOCKING_SHAKE_WAIT)
+{
+ return FSM_NEXT (TOP_WAITING_CLAMP, clamp_blocked);
+}
+
+FSM_TRANS (TOP_WAITING_CLAMP, clamp_taken, TOP_WAITING_CLAMP)
+{
+ position_t robot_pos;
+ asserv_get_position (&robot_pos);
+ if (robot_pos.v.x < 400 || robot_pos.v.x > PG_WIDTH - 400)
+ asserv_move_linearly (ctx.go_to_element_direction
+ == DIRECTION_FORWARD ? -50 : 50);
+ return FSM_NEXT (TOP_WAITING_CLAMP, clamp_taken);
+}
+
+FSM_TRANS_TIMEOUT (TOP_UNBLOCKING_SHAKE_WAIT, 250,
+ try_again, TOP_UNBLOCKING_SHAKE,
+ tryout, TOP_WAITING_CLAMP)
+{
+ if (ctx.chaos < 4)
+ {
+ int16_t dist = logistic_global.collect_direction
+ == DIRECTION_FORWARD ? 100 : -100;
+ asserv_move_linearly (++ctx.chaos % 2 ? -dist : dist);
+ return FSM_NEXT_TIMEOUT (TOP_UNBLOCKING_SHAKE_WAIT, try_again);
+ }
+ else
+ {
+ ctx.broken = 1;
+ clamp_prepare (3);
+ return FSM_NEXT_TIMEOUT (TOP_UNBLOCKING_SHAKE_WAIT, tryout);
+ }
+}
+
+FSM_TRANS (TOP_UNBLOCKING_SHAKE, robot_move_success, TOP_WAITING_CLAMP)
+{
+ clamp_prepare (0);
+ return FSM_NEXT (TOP_UNBLOCKING_SHAKE, robot_move_success);
+}
+
+FSM_TRANS (TOP_UNBLOCKING_SHAKE, robot_move_failure,
+ TOP_UNBLOCKING_SHAKE_WAIT)
+{
+ return FSM_NEXT (TOP_UNBLOCKING_SHAKE, robot_move_failure);
+}
+
+FSM_TRANS (TOP_WAITING_READY, clamp_done,
+ drop, TOP_DROP_DROPPING,
+ not_ready, TOP_WAITING_READY)
+{
+ if (clamp_drop (logistic_global.collect_direction))
+ return FSM_NEXT (TOP_WAITING_READY, clamp_done, drop);
+ else
+ return FSM_NEXT (TOP_WAITING_READY, clamp_done, not_ready);
+}
+
+FSM_TRANS (TOP_WAITING_READY, clamp_blocked, TOP_UNBLOCKING_SHAKE_WAIT)
+{
+ return FSM_NEXT (TOP_WAITING_CLAMP, clamp_blocked);
+}
+
+FSM_TRANS (TOP_DROP_DROPPING, clamp_drop_waiting, TOP_DROP_CLEARING)
+{
+ if (ctx.target_element_id != 0xff)
+ element_down (ctx.target_element_id,
+ logistic_drop_element_type
+ (logistic_global.collect_direction));
+ if (IO_GET (CONTACT_STRAT))
+ element_i_like_green ();
+ asserv_move_linearly (logistic_global.collect_direction
+ == DIRECTION_FORWARD ? 150 : -150);
+ return FSM_NEXT (TOP_DROP_DROPPING, clamp_drop_waiting);
+}
+
+FSM_TRANS (TOP_DROP_CLEARING, robot_move_success,
+ drop, TOP_GOING_TO_DROP,
+ element, TOP_GOING_TO_ELEMENT)
+{
+ clamp_drop_clear ();
+ switch (top_decision ())
+ {
+ default: return FSM_NEXT (TOP_DROP_CLEARING, robot_move_success, drop);
+ case 1: return FSM_NEXT (TOP_DROP_CLEARING, robot_move_success, element);
+ }
+}
+
+FSM_TRANS (TOP_DROP_CLEARING, robot_move_failure,
+ drop, TOP_GOING_TO_DROP,
+ element, TOP_GOING_TO_ELEMENT)
+{
+ clamp_drop_clear ();
+ switch (top_decision ())
+ {
+ default: return FSM_NEXT (TOP_DROP_CLEARING, robot_move_failure, drop);
+ case 1: return FSM_NEXT (TOP_DROP_CLEARING, robot_move_failure, element);
+ }
+}
+
diff --git a/digital/io-hub/tools/io_hub/io_hub.py b/digital/io-hub/tools/io_hub/io_hub.py
index a363e5f6..06d237e9 100644
--- a/digital/io-hub/tools/io_hub/io_hub.py
+++ b/digital/io-hub/tools/io_hub/io_hub.py
@@ -44,9 +44,31 @@ class Proto:
def pwm_set_timed (self, index, value, time, rest_value):
self.proto.send ('w', 'BhHh', index, value, time, rest_value)
+ def goto (self, x, y, backward):
+ self.proto.send ('m', 'hhB', x, y, backward)
+
def clamp_move (self, pos):
self.proto.send ('c', 'B', pos)
+ def clamp_move_element (self, from_, to):
+ self.proto.send ('c', 'BB', from_, to)
+
+ def drop (self, order):
+ if order == 'drop_clear':
+ self.proto.send ('d', 'B', 0x00)
+ elif order == 'drop_forward':
+ self.proto.send ('d', 'B', 0x01)
+ elif order == 'drop_backward':
+ self.proto.send ('d', 'B', 0x02)
+ else:
+ raise ValueError
+
+ def door (self, pos, open_):
+ self.proto.send ('d', 'BB', pos, (0, 1)[open_])
+
+ def clamp_openclose (self, open_):
+ self.proto.send ('d', 'BB', 0xff, (0, 1)[open_])
+
def close (self):
self.reset ()
self.proto.wait (lambda: True)
diff --git a/digital/io-hub/tools/io_hub/mex.py b/digital/io-hub/tools/io_hub/mex.py
index 7c8c0012..9b72ccde 100644
--- a/digital/io-hub/tools/io_hub/mex.py
+++ b/digital/io-hub/tools/io_hub/mex.py
@@ -31,7 +31,7 @@ ADC_NB = 8
PWM_NB = 6
PWM_VALUE_MAX = 1024
-CONTACT_NB = 4
+CONTACT_NB = 10
CONTACT_INIT = 0xffffffff
class Mex:
@@ -44,9 +44,21 @@ class Mex:
"""
- def __init__ (self):
+ def __init__ (self, node, instance, index):
Observable.__init__ (self)
- self.value = None
+ self.value = 0
+ self.__node = node
+ self.__mtype = node.reserve (instance + ':adc')
+ self.__index = index
+ self.register (self.__notified)
+
+ def __notified (self):
+ m = simu.mex.msg.Msg (self.__mtype)
+ v = int (1024 * self.value / 5)
+ v = min (v, 1023)
+ v = max (0, v)
+ m.push ('BH', self.__index, v)
+ self.__node.send (m)
class PWM (Observable):
"""PWM output.
@@ -109,11 +121,95 @@ class Mex:
m.push ('L', self.contacts)
self.node.send (m)
+ class Codebar (Observable):
+ """Codebar stub.
+
+ - element_type: 'queen', 'king', or anything else.
+
+ """
+
+ def __init__ (self, pack, index):
+ Observable.__init__ (self)
+ self.pack = pack
+ self.index = index
+ self.element_type = None
+ self.register (self.__notified)
+
+ def __notified (self):
+ self.pack.set (self.index, self.element_type)
+
+ class Pack:
+ """Handle emission of several codebar for one message."""
+
+ def __init__ (self, node, instance):
+ self.node = node
+ self.codebars = [0, 0]
+ self.mtype = node.reserve (instance + ':codebar')
+
+ def set (self, index, element_type):
+ if element_type == 'queen':
+ self.codebars[index] = 4
+ elif element_type == 'king':
+ self.codebars[index] = 8
+ else:
+ self.codebars[index] = 0
+ self.__send ()
+
+ def __send (self):
+ m = simu.mex.msg.Msg (self.mtype)
+ for c in self.codebars:
+ m.push ('b', c)
+ self.node.send (m)
+
+ class Path (Observable):
+ """Path finding algorithm report.
+
+ - path: sequence of (x, y) coordinates (millimeters).
+
+ """
+
+ def __init__ (self, node, instance):
+ Observable.__init__ (self)
+ self.path = [ ]
+ node.register (instance + ':path', self.__handle)
+
+ def __handle (self, msg):
+ self.path = [ ]
+ while len (msg) >= 4:
+ self.path.append (msg.pop ('hh'))
+ self.notify ()
+
+ class PosReport (Observable):
+ """General purpose position report.
+
+ - pos: dict of sequence of (x, y) coordinates (millimeters). The dict
+ is indexed by position identifier.
+
+ """
+
+ def __init__ (self, node, instance):
+ Observable.__init__ (self)
+ self.pos = { }
+ node.register (instance + ':pos-report', self.__handle)
+
+ def __handle (self, msg):
+ p = [ ]
+ id, = msg.pop ('b')
+ while len (msg) >= 4:
+ p.append (msg.pop ('hh'))
+ self.pos[id] = p
+ self.notify ()
+
def __init__ (self, node, instance = 'io-hub0'):
- self.adc = tuple (self.ADC () for i in range (0, ADC_NB))
+ self.adc = tuple (self.ADC (node, instance, i) for i in range (0, ADC_NB))
self.pwm = tuple (self.PWM () for i in range (0, PWM_NB))
- self.__adc_pwm = self.PWM.Pack (node, instance, self.pwm)
+ self.__pwm_pack = self.PWM.Pack (node, instance, self.pwm)
self.__contact_pack = self.Contact.Pack (node, instance)
self.contact = tuple (self.Contact (self.__contact_pack, i)
for i in range (CONTACT_NB))
+ self.__codebar_pack = self.Codebar.Pack (node, instance)
+ self.codebar = tuple (self.Codebar (self.__codebar_pack, i)
+ for i in (0, 1))
+ self.path = self.Path (node, instance)
+ self.pos_report = self.PosReport (node, instance)
diff --git a/digital/io-serial/src/codebar/Makefile b/digital/io-serial/src/codebar/Makefile
new file mode 100644
index 00000000..f607da5f
--- /dev/null
+++ b/digital/io-serial/src/codebar/Makefile
@@ -0,0 +1,16 @@
+BASE = ../../../avr
+AVR_PROGS = codebar_reader
+codebar_reader_SOURCES = codebar.c timer.avr.c
+MODULES = twi uart utils
+AI_MODULES = utils
+CONFIGFILE = avrconfig.h
+AVR_MCU = atmega164p
+# -O2 : speed
+# -Os : size
+OPTIMIZE = -Os
+
+vpath %.c $(AI_MODULES:%=../../../ai/src/%)
+vpath %.h $(AI_MODULES:%=../../../ai/src/%)
+INCLUDES += $(AI_MODULES:%=-I../../../ai/src/%)
+
+include $(BASE)/make/Makefile.gen
diff --git a/digital/io-serial/src/codebar/avrconfig.h b/digital/io-serial/src/codebar/avrconfig.h
new file mode 100644
index 00000000..b7624a5c
--- /dev/null
+++ b/digital/io-serial/src/codebar/avrconfig.h
@@ -0,0 +1,100 @@
+#ifndef avrconfig_h
+#define avrconfig_h
+/* avrconfig.h - Codebar configuration template. */
+/* io-serial.codebar - Codebar AVR module. {{{
+ *
+ * Copyright (C) 2011 Nicolas Schodet
+ *
+ * Robot APB Team/Efrei 2011.
+ * 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.
+ *
+ * }}} */
+
+/* global */
+/** AVR Frequency : 1000000, 1843200, 2000000, 3686400, 4000000, 7372800,
+ * 8000000, 11059200, 14745600, 16000000, 18432000, 20000000. */
+#define AC_FREQ 14745600
+
+/* uart - UART module. */
+/** Select hardware uart for primary uart: 0, 1 or -1 to disable. */
+#define AC_UART0_PORT 0
+/** Baudrate: 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600, 76800,
+ * 115200, 230400, 250000, 500000, 1000000. */
+#define AC_UART0_BAUDRATE 9600
+/** Send mode:
+ * - POLLING: no interrupts.
+ * - RING: interrupts, ring buffer. */
+#define AC_UART0_SEND_MODE RING
+/** Recv mode, same as send mode. */
+#define AC_UART0_RECV_MODE RING
+/** Character size: 5, 6, 7, 8, 9 (only 8 implemented). */
+#define AC_UART0_CHAR_SIZE 8
+/** Parity : ODD, EVEN, NONE. */
+#define AC_UART0_PARITY NONE
+/** Stop bits : 1, 2. */
+#define AC_UART0_STOP_BITS 1
+/** Send buffer size, should be power of 2 for RING mode. */
+#define AC_UART0_SEND_BUFFER_SIZE 32
+/** Recv buffer size, should be power of 2 for RING mode. */
+#define AC_UART0_RECV_BUFFER_SIZE 32
+/** If the send buffer is full when putc:
+ * - DROP: drop the new byte.
+ * - WAIT: wait until there is room in the send buffer. */
+#define AC_UART0_SEND_BUFFER_FULL WAIT
+/** In HOST compilation:
+ * - STDIO: use stdin/out.
+ * - PTS: use pseudo terminal. */
+#define AC_UART0_HOST_DRIVER PTS
+/** Same thing for secondary port. */
+#define AC_UART1_PORT 1
+#define AC_UART1_BAUDRATE 9600
+#define AC_UART1_SEND_MODE RING
+#define AC_UART1_RECV_MODE RING
+#define AC_UART1_CHAR_SIZE 8
+#define AC_UART1_PARITY NONE
+#define AC_UART1_STOP_BITS 1
+#define AC_UART1_SEND_BUFFER_SIZE 32
+#define AC_UART1_RECV_BUFFER_SIZE 32
+#define AC_UART1_SEND_BUFFER_FULL WAIT
+#define AC_UART1_HOST_DRIVER PTS
+
+/* twi - TWI module. */
+/** Driver to implement TWI: HARD, SOFT, or USI. */
+#define AC_TWI_DRIVER HARD
+/** Do not use interrupts. */
+#define AC_TWI_NO_INTERRUPT 0
+/** TWI frequency, should really be 100 kHz. */
+#define AC_TWI_FREQ 100000
+/** Enable slave part. */
+#define AC_TWI_SLAVE_ENABLE 1
+/** Enable master part. */
+#define AC_TWI_MASTER_ENABLE 0
+/** Use polled slave mode: received data is stored in a buffer which can be
+ * polled using twi_slave_poll. */
+#define AC_TWI_SLAVE_POLLED 1
+/** Slave reception callback to be defined by the user when not in polled
+ * mode. */
+#undef AC_TWI_SLAVE_RECV
+/** Use internal pull up. */
+#define AC_TWI_PULL_UP 0
+/** Slave reception buffer size. */
+#define AC_TWI_SLAVE_RECV_BUFFER_SIZE 16
+/** Slave transmission buffer size. */
+#define AC_TWI_SLAVE_SEND_BUFFER_SIZE 16
+
+#endif /* avrconfig_h */
diff --git a/digital/io-serial/src/codebar/codebar.c b/digital/io-serial/src/codebar/codebar.c
new file mode 100644
index 00000000..916e4ef1
--- /dev/null
+++ b/digital/io-serial/src/codebar/codebar.c
@@ -0,0 +1,159 @@
+/* codebar.c */
+/* codebar - Codebar Reader. {{{
+ *
+ * Copyright (C) 2011
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "common.h"
+#include "modules/twi/twi.h"
+#include "modules/proto/proto.h"
+#include "modules/uart/uart.h"
+#include "modules/utils/utils.h"
+#include "modules/utils/byte.h"
+#include "modules/utils/crc.h"
+#include "timer.h"
+
+/* from robospierre/element.h file */
+#define ELEMENT_UNKOWN 0
+#define ELEMENT_QUEEN 4
+#define ELEMENT_KING 8
+
+#define STRING_MAX 10
+
+struct status_t
+{
+ uint16_t age1;
+ uint8_t piece1;
+ uint16_t age2;
+ uint8_t piece2;
+};
+
+char buffer_u0[STRING_MAX], buffer_u1[STRING_MAX];
+
+uint8_t
+string_to_element (char *data, uint8_t data_len)
+{
+ uint8_t i;
+ for (i = 0; i < data_len - 5; i++)
+ {
+ if (memcmp (data + i, "QUEEN", 5) == 0)
+ {
+ data[i] = 0;
+ return ELEMENT_QUEEN;
+ }
+ if (memcmp (data + i, "QWEEN", 5) == 0)
+ {
+ data[i] = 0;
+ return ELEMENT_QUEEN;
+ }
+ }
+ for (i = 0; i < data_len - 4; i++)
+ {
+ if (memcmp (data + i, "KING", 4) == 0)
+ {
+ data[i] = 0;
+ return ELEMENT_KING;
+ }
+ }
+ return ELEMENT_UNKOWN;
+}
+
+void
+read_strings (void)
+{
+ uint8_t i;
+ while (uart0_poll ())
+ {
+ /* Insert char at end of string. */
+ for (i = 1; i < STRING_MAX; i++)
+ buffer_u0[i - 1] = buffer_u0[i];
+ buffer_u0[STRING_MAX - 1] = uart0_getc ();
+ }
+ while (uart1_poll ())
+ {
+ /* Insert char at end of string. */
+ for (i = 1; i < STRING_MAX; i++)
+ buffer_u1[i - 1] = buffer_u1[i];
+ buffer_u1[STRING_MAX - 1] = uart1_getc ();
+ }
+}
+
+int
+main (int argc, char **argv)
+{
+ struct status_t status;
+ uint8_t element_type;
+
+ status.age1 = 0;
+ status.piece1 = ELEMENT_UNKOWN;
+ status.age2 = 0;
+ status.piece2 = ELEMENT_UNKOWN;
+
+ timer_init ();
+ avr_init (argc, argv);
+ sei ();
+ uart0_init ();
+ uart1_init ();
+ /* Initialize TWI. */
+ twi_init (0x20);
+
+ while (1)
+ {
+ /* Wait until next cycle. */
+ timer_wait ();
+ if (status.age1 < (uint16_t) -1)
+ status.age1 ++;
+ if (status.age2 < (uint16_t) -1)
+ status.age2 ++;
+
+ read_strings ();
+ element_type = string_to_element (buffer_u0, STRING_MAX);
+ if (element_type)
+ {
+ status.piece1 = element_type;
+ status.age1 = 0;
+ }
+ element_type = string_to_element (buffer_u1, STRING_MAX);
+ if (element_type)
+ {
+ status.piece2 = element_type;
+ status.age2 = 0;
+ }
+
+ uint8_t status_with_crc[7];
+ uint8_t *status_twi = &status_with_crc[1];
+ status_twi[0] = v16_to_v8 (status.age1, 1);
+ status_twi[1] = v16_to_v8 (status.age1, 0);
+ status_twi[2] = status.piece1;
+ status_twi[3] = v16_to_v8 (status.age2, 1);
+ status_twi[4] = v16_to_v8 (status.age2, 0);
+ status_twi[5] = status.piece2;
+ /* Compute CRC. */
+ status_with_crc[0] = crc_compute (&status_with_crc[1], sizeof (status_with_crc) - 1);
+ twi_slave_update (status_with_crc, sizeof (status_with_crc));
+ }
+ return 0;
+}
diff --git a/digital/io/src/Makefile b/digital/io/src/Makefile
index 5cbea0ba..4ebc5a66 100644
--- a/digital/io/src/Makefile
+++ b/digital/io/src/Makefile
@@ -3,16 +3,17 @@ BASE = ../../avr
# Name of the program to build.
PROGS = io
# Sources to compile.
-io_SOURCES = main.c fsm_queue.c servo.avr.c eeprom.avr.c pwm.c \
- switch.avr.c chrono.c timer.avr.c servo_pos.c \
+io_SOURCES = main.c fsm_queue.c eeprom.avr.c pwm.c \
+ switch.avr.c chrono.c timer.avr.c \
twi_master.c asserv.c mimot.c \
- simu.host.c contact.c usdist.c radar.c \
+ simu.host.c contact.c radar.c radar_defs.c \
path.c food.c events.host.c \
fsm.host.c init.c move.c top.c hola.c loader.c fsm_AI_gen.avr.c
# Modules needed for IO.
MODULES = proto uart twi utils adc math/fixed math/geometry path/astar \
+ devices/usdist devices/servo \
trace flash spi
-AI_MODULES = twi_master common utils fsm
+AI_MODULES = twi_master common utils fsm move
# Configuration file.
CONFIGFILE = avrconfig.h
# IO board use an ATMega128.
diff --git a/digital/io/src/avrconfig.h b/digital/io/src/avrconfig.h
index dd3f2e87..cb9061fd 100644
--- a/digital/io/src/avrconfig.h
+++ b/digital/io/src/avrconfig.h
@@ -117,6 +117,23 @@
/** Heuristic callback. */
#define AC_ASTAR_HEURISTIC_CALLBACK path_astar_heuristic_callback
+/* usdist - Analog US distance sensor. */
+/** Number of sensors. */
+#define AC_USDIST_NB 4
+/** Measuring period, in number of update call. */
+#define AC_USDIST_PERIOD 1
+/** List of space separated sensor definition, see usdist.h. */
+#define AC_USDIST_SENSORS \
+ USDIST_SENSOR (0, G, 3) \
+ USDIST_SENSOR (1, G, 1) \
+ USDIST_SENSOR (2, C, 7) \
+ USDIST_SENSOR (3, D, 4)
+
+/* servo - Servo module */
+/** All servos are currently connected to the same port. */
+#define AC_SERVO_PORT PORTA
+#define AC_SERVO_DDR DDRA
+
/* io - io/ai board. */
/** TWI address of the io board. */
#define AC_IO_TWI_ADDRESS 2
diff --git a/digital/io/src/eeprom.avr.c b/digital/io/src/eeprom.avr.c
index a32b9606..febba55c 100644
--- a/digital/io/src/eeprom.avr.c
+++ b/digital/io/src/eeprom.avr.c
@@ -26,8 +26,8 @@
#include "common.h"
#include "eeprom.h"
-#include "servo.h" /* SERVO_NUMBER */
-#include "servo_pos.h"
+#include "modules/devices/servo/servo.h"
+#include "modules/devices/servo/servo_pos.h"
#include <avr/eeprom.h> /* eeprom_{read,write}_byte */
diff --git a/digital/io/src/main.c b/digital/io/src/main.c
index 22964ddd..5aa35fb7 100644
--- a/digital/io/src/main.c
+++ b/digital/io/src/main.c
@@ -28,6 +28,8 @@
#include "modules/proto/proto.h"
#include "modules/utils/utils.h"
#include "modules/path/path.h"
+#include "modules/devices/usdist/usdist.h"
+#include "modules/devices/servo/servo_pos.h"
#include "modules/flash/flash.h"
#include "modules/trace/trace.h"
#include "events.h"
@@ -50,8 +52,6 @@
#include "fsm.h"
#include "fsm_queue.h"
#include "bot.h"
-#include "servo_pos.h"
-#include "usdist.h"
#include "radar.h"
#include "chrono.h" /* chrono_end_match */
#include "pwm.h"
@@ -408,7 +408,7 @@ proto_callback (uint8_t cmd, uint8_t size, uint8_t *args)
* - 1b: servo id number;
* - 1b: pwm high time value (position).
*/
- servo_set_high_time (args[0], args[1]);
+ servo_set_position (args[0], args[1]);
break;
case c ('S', 0):
diff --git a/digital/io/src/move.c b/digital/io/src/move.c
index 60db0272..81c554fc 100644
--- a/digital/io/src/move.c
+++ b/digital/io/src/move.c
@@ -397,7 +397,7 @@ move_MOVE_MOVING_bot_move_failed_MOVE_MOVING_BACKWARD_TO_TURN_FREELY ()
position_t robot_pos;
asserv_get_position (&robot_pos);
vect_t obstacle_pos;
- int16_t dist = asserv_get_last_moving_direction () == 1
+ int16_t dist = asserv_get_last_moving_direction () == DIRECTION_FORWARD
? BOT_SIZE_FRONT + MOVE_REAL_OBSTACLE_RADIUS
: -(BOT_SIZE_BACK + MOVE_REAL_OBSTACLE_RADIUS);
vect_from_polar_uf016 (&obstacle_pos, dist, robot_pos.a);
@@ -405,8 +405,8 @@ move_MOVE_MOVING_bot_move_failed_MOVE_MOVING_BACKWARD_TO_TURN_FREELY ()
path_obstacle (0, obstacle_pos, MOVE_OBSTACLE_RADIUS, 0,
MOVE_OBSTACLE_VALIDITY);
/* Move backward to turn freely. */
- asserv_move_linearly (asserv_get_last_moving_direction () == 1 ?
- - 300 : 300);
+ asserv_move_linearly (asserv_get_last_moving_direction ()
+ == DIRECTION_FORWARD ? -300 : 300);
}
FSM_TRANS (MOVE_MOVING,
diff --git a/digital/io/src/radar_defs.c b/digital/io/src/radar_defs.c
new file mode 100644
index 00000000..2787ed97
--- /dev/null
+++ b/digital/io/src/radar_defs.c
@@ -0,0 +1,54 @@
+/* radar_defs.c */
+/* io - Input & Output with Artificial Intelligence (ai) support on AVR. {{{
+ *
+ * Copyright (C) 2010 Nicolas Schodet
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * 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 "common.h"
+#include "radar.h"
+
+#include "modules/devices/usdist/usdist.h"
+#include "playground_2010.h"
+
+/** Define radar configuration. */
+struct radar_sensor_t radar_sensors[RADAR_SENSOR_NB] = {
+#define RADAR_SENSOR_FRONT 0
+ { &usdist_mm[0], { 30 - 20, 0 }, G_ANGLE_UF016_DEG (0) },
+#define RADAR_SENSOR_LEFT 1
+ { &usdist_mm[1], { 20 - 20, 20 }, G_ANGLE_UF016_DEG (30) },
+#define RADAR_SENSOR_RIGHT 2
+ { &usdist_mm[2], { 20 - 20, -20 }, G_ANGLE_UF016_DEG (-30) },
+#define RADAR_SENSOR_BACK 3
+ { &usdist_mm[3], { -30 - 20, 0 }, G_ANGLE_UF016_DEG (180) },
+};
+
+/** Define exclusion area (considered as invalid point). */
+uint8_t
+radar_valid (vect_t p)
+{
+ return p.x >= RADAR_MARGIN_MM && p.x < PG_WIDTH - RADAR_MARGIN_MM
+ && p.y >= RADAR_MARGIN_MM && p.y < PG_LENGTH - RADAR_MARGIN_MM
+ /* Ignore points on slope, no margin for the slope start. */
+ && (p.x < PG_WIDTH / 2 - PG_SLOPE_WIDTH / 2
+ || p.x >= PG_WIDTH / 2 + PG_SLOPE_WIDTH / 2
+ || p.y < PG_LENGTH - PG_SLOPE_LENGTH - RADAR_MARGIN_MM / 2);
+}
+
diff --git a/digital/io/src/radar_defs.h b/digital/io/src/radar_defs.h
new file mode 100644
index 00000000..51bc5943
--- /dev/null
+++ b/digital/io/src/radar_defs.h
@@ -0,0 +1,41 @@
+#ifndef radar_defs_h
+#define radar_defs_h
+/* radar_defs.h */
+/* io - Input & Output with Artificial Intelligence (ai) support on AVR. {{{
+ *
+ * Copyright (C) 2010 Nicolas Schodet
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * 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.
+ *
+ * }}} */
+
+#define RADAR_OBSTACLE_EDGE_RADIUS_MM 40
+#define RADAR_OBSTACLE_RADIUS_MM 150
+#define RADAR_STOP_MM 350
+#define RADAR_CLEARANCE_MM 100
+#define RADAR_EPSILON_MM 70
+
+#define RADAR_SENSOR_NB 4
+
+#define RADAR_SENSOR_FRONT_FIRST 0
+#define RADAR_SENSOR_FRONT_NB 3
+#define RADAR_SENSOR_BACK_FIRST 3
+#define RADAR_SENSOR_BACK_NB 1
+
+#endif /* radar_defs_h */
diff --git a/digital/io/src/simu.host.c b/digital/io/src/simu.host.c
index f1b7e0d2..a35b9d12 100644
--- a/digital/io/src/simu.host.c
+++ b/digital/io/src/simu.host.c
@@ -25,7 +25,7 @@
#include "common.h"
#include "simu.host.h"
-#include "servo.h"
+#include "modules/devices/servo/servo.h"
#include "pwm.h"
#include "modules/utils/utils.h"
@@ -36,10 +36,10 @@
#include "io.h"
/** Requested servo position. */
-uint8_t servo_high_time_[SERVO_NUMBER];
+uint8_t servo_position_[SERVO_NUMBER];
/** Current servo position. */
-uint8_t servo_high_time_current_[SERVO_NUMBER];
+uint8_t servo_position_current_[SERVO_NUMBER];
/** Servo speed is about 120 ms for 60 degrees. This means about 360 ms for
* the full swing. */
@@ -112,13 +112,13 @@ simu_step (void)
/* Update servos. */
for (i = 0; i < SERVO_NUMBER; i++)
{
- if (UTILS_ABS (servo_high_time_current_[i] - servo_high_time_[i]) <
+ if (UTILS_ABS (servo_position_current_[i] - servo_position_[i]) <
SERVO_SPEED)
- servo_high_time_current_[i] = servo_high_time_[i];
- else if (servo_high_time_current_[i] < servo_high_time_[i])
- servo_high_time_current_[i] += SERVO_SPEED;
+ servo_position_current_[i] = servo_position_[i];
+ else if (servo_position_current_[i] < servo_position_[i])
+ servo_position_current_[i] += SERVO_SPEED;
else
- servo_high_time_current_[i] -= SERVO_SPEED;
+ servo_position_current_[i] -= SERVO_SPEED;
}
/* Send servos. */
if (simu_servo_update && !--simu_servo_update_cpt)
@@ -126,7 +126,7 @@ simu_step (void)
simu_servo_update_cpt = simu_servo_update;
m = mex_msg_new (simu_mex_servo);
for (i = 0; i < SERVO_NUMBER; i++)
- mex_msg_push (m, "B", servo_high_time_current_[i]);
+ mex_msg_push (m, "B", servo_position_current_[i]);
mex_node_send (m);
}
/* Update switches. */
@@ -180,15 +180,15 @@ servo_init (void)
}
void
-servo_set_high_time (uint8_t servo, uint8_t high_time)
+servo_set_position (uint8_t servo, uint8_t position)
{
- servo_high_time_[servo] = high_time;
+ servo_position_[servo] = position;
}
uint8_t
-servo_get_high_time (uint8_t servo)
+servo_get_position (uint8_t servo)
{
- return servo_high_time_[servo];
+ return servo_position_[servo];
}
void
diff --git a/digital/mimot/src/dirty/pwm.h b/digital/mimot/src/dirty/pwm.h
index e48f66b9..32000bb7 100644
--- a/digital/mimot/src/dirty/pwm.h
+++ b/digital/mimot/src/dirty/pwm.h
@@ -25,8 +25,11 @@
*
* }}} */
+/** Offset to compensate for H-bridge dead zone at low PWM values. */
+#define PWM_OFFSET 0x40
+
/** Define the absolute maximum PWM value. */
-#define PWM_MAX 0x3ff
+#define PWM_MAX (0x3ff - PWM_OFFSET)
/** PWM control state. */
struct pwm_t
diff --git a/digital/mimot/src/dirty/pwm_ocr.avr.c b/digital/mimot/src/dirty/pwm_ocr.avr.c
index f10f37e7..804d7dcd 100644
--- a/digital/mimot/src/dirty/pwm_ocr.avr.c
+++ b/digital/mimot/src/dirty/pwm_ocr.avr.c
@@ -94,12 +94,12 @@ pwm_ocr_update (void)
IO_SET (PWM1_BRK_IO);
if (PWM_VALUE (PWM1) < 0)
{
- pwm1 = -PWM_VALUE (PWM1);
+ pwm1 = -PWM_VALUE (PWM1) + PWM_OFFSET;
}
else
{
dir_d |= _BV (PWM1_DIR);
- pwm1 = PWM_VALUE (PWM1);
+ pwm1 = PWM_VALUE (PWM1) + PWM_OFFSET;
}
}
# endif /* PWM1 */
@@ -115,12 +115,12 @@ pwm_ocr_update (void)
IO_SET (PWM2_BRK_IO);
if (PWM_VALUE (PWM2) < 0)
{
- pwm2 = -PWM_VALUE (PWM2);
+ pwm2 = -PWM_VALUE (PWM2) + PWM_OFFSET;
}
else
{
dir_d |= _BV (PWM2_DIR);
- pwm2 = PWM_VALUE (PWM2);
+ pwm2 = PWM_VALUE (PWM2) + PWM_OFFSET;
}
}
# endif /* PWM2 */
diff --git a/digital/mimot/src/dirty/speed.c b/digital/mimot/src/dirty/speed.c
index cd68fec2..8aa3d54b 100644
--- a/digital/mimot/src/dirty/speed.c
+++ b/digital/mimot/src/dirty/speed.c
@@ -52,13 +52,21 @@ speed_init (void)
static void
speed_update_by_speed (struct speed_t *speed)
{
- /* Update current speed. */
- if (UTILS_ABS (speed->cons - speed->cur) < speed->acc)
- speed->cur = speed->cons;
- else if (speed->cons > speed->cur)
- speed->cur += speed->acc;
+ /* Update current speed (be careful of overflow!). */
+ if (speed->cons > speed->cur)
+ {
+ if ((uint16_t) (speed->cons - speed->cur) < (uint16_t) speed->acc)
+ speed->cur = speed->cons;
+ else
+ speed->cur += speed->acc;
+ }
else
- speed->cur -= speed->acc;
+ {
+ if ((uint16_t) (speed->cur - speed->cons) < (uint16_t) speed->acc)
+ speed->cur = speed->cons;
+ else
+ speed->cur -= speed->acc;
+ }
}
/** Compute maximum allowed speed according to: distance left, maximum speed,