fix display and support beacon in robotsim
[aversive.git] / projects / microb2010 / mainboard / robotsim.c
1 /*  
2  *  Copyright Droids Corporation, Microb Technology, Eirbot (2005)
3  * 
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  *
18  *  Revision : $Id: main.c,v 1.9.4.5 2007-06-01 09:37:22 zer0 Exp $
19  *
20  */
21
22 #include <stdio.h>
23 #include <string.h>
24 #include <stdint.h>
25 #include <unistd.h>
26 #include <sys/stat.h>
27 #include <sys/types.h>
28 #include <fcntl.h>
29 #include <unistd.h>
30
31 #include <aversive.h>
32 #include <aversive/error.h>
33
34 #include <timer.h>
35 #include <scheduler.h>
36 #include <time.h>
37
38 #include <ax12.h>
39 #include <pwm_ng.h>
40 #include <pid.h>
41 #include <quadramp.h>
42 #include <control_system_manager.h>
43 #include <trajectory_manager.h>
44 #include <blocking_detection_manager.h>
45 #include <robot_system.h>
46 #include <position_manager.h>
47 #include <trajectory_manager_utils.h>
48
49 #include <parse.h>
50 #include <rdline.h>
51
52 #include "../common/i2c_commands.h"
53 #include "strat.h"
54 #include "strat_utils.h"
55 #include "main.h"
56
57 static int32_t l_pwm, r_pwm;
58 static int32_t l_enc, r_enc;
59
60 static int fdr, fdw;
61 /*
62  * Debug with GDB:
63  *
64  * (gdb) handle SIGUSR1 pass
65  * Signal        Stop   Print   Pass to program Description
66  * SIGUSR1       Yes    Yes     Yes             User defined signal 1
67  * (gdb) handle SIGUSR2 pass
68  * Signal        Stop   Print   Pass to program Description
69  * SIGUSR2       Yes    Yes     Yes             User defined signal 2
70  * (gdb) handle SIGUSR1 noprint
71  * Signal        Stop   Print   Pass to program Description
72  * SIGUSR1       No     No      Yes             User defined signal 1
73  * (gdb) handle SIGUSR2 noprint
74  */
75
76 /* */
77 #define FILTER  98
78 #define FILTER2 (100-FILTER)
79 #define SHIFT   4
80
81 void robotsim_dump(void)
82 {
83         char buf[BUFSIZ];
84         int len;
85         int16_t x, y, a;
86
87         x = position_get_x_s16(&mainboard.pos);
88         y = position_get_y_s16(&mainboard.pos);
89         a = position_get_a_deg_s16(&mainboard.pos);
90 /*      y = COLOR_Y(y); */
91 /*      a = COLOR_A(a); */
92
93         len = snprintf(buf, sizeof(buf), "pos=%d,%d,%d\n",
94                        x, y, a);
95         hostsim_lock();
96         write(fdw, buf, len);
97         hostsim_unlock();
98 }
99
100 static int8_t
101 robotsim_i2c_ballboard_set_mode(struct i2c_cmd_ballboard_set_mode *cmd)
102 {
103         char buf[BUFSIZ];
104         int len;
105
106         ballboard.mode = cmd->mode;
107         len = snprintf(buf, sizeof(buf), "ballboard=%d\n", cmd->mode);
108         hostsim_lock();
109         write(fdw, buf, len);
110         hostsim_unlock();
111         return 0;
112 }
113
114 int8_t
115 robotsim_i2c_cobboard_set_spickles(uint8_t side, uint8_t flags)
116 {
117         char buf[BUFSIZ];
118         int len;
119
120         if (side == I2C_LEFT_SIDE) {
121                 if (cobboard.lspickle == flags)
122                         return 0;
123                 else
124                         cobboard.lspickle = flags;
125         }
126         if (side == I2C_RIGHT_SIDE) {
127                 if (cobboard.rspickle == flags)
128                         return 0;
129                 else
130                         cobboard.rspickle = flags;
131         }
132
133         len = snprintf(buf, sizeof(buf), "cobboard=%d,%d\n", side, flags);
134         hostsim_lock();
135         write(fdw, buf, len);
136         hostsim_unlock();
137         return 0;
138 }
139
140 static int8_t
141 robotsim_i2c_ballboard(uint8_t addr, uint8_t *buf, uint8_t size)
142 {
143         void *void_cmd = buf;
144
145         switch (buf[0]) {
146         case I2C_CMD_BALLBOARD_SET_MODE:
147                 {
148                         struct i2c_cmd_ballboard_set_mode *cmd = void_cmd;
149                         robotsim_i2c_ballboard_set_mode(cmd);
150                         break;
151                 }
152
153         default:
154                 break;
155         }
156         return 0;
157 }
158
159 static int8_t
160 robotsim_i2c_cobboard(uint8_t addr, uint8_t *buf, uint8_t size)
161 {
162         //      void *void_cmd = buf;
163
164         switch (buf[0]) {
165 #if 0 /* deleted */
166         case I2C_CMD_COBBOARD_SET_MODE:
167                 {
168                         struct i2c_cmd_cobboard_set_mode *cmd = void_cmd;
169                         robotsim_i2c_cobboard_set_mode(cmd);
170                         break;
171                 }
172 #endif
173         default:
174                 break;
175         }
176         return 0;
177 }
178
179 int8_t
180 robotsim_i2c(uint8_t addr, uint8_t *buf, uint8_t size)
181 {
182         if (addr == I2C_BALLBOARD_ADDR)
183                 return robotsim_i2c_ballboard(addr, buf, size);
184         else if (addr == I2C_COBBOARD_ADDR)
185                 return robotsim_i2c_cobboard(addr, buf, size);
186         return 0;
187 }
188
189 /* must be called periodically */
190 void robotsim_update(void)
191 {
192         static int32_t l_pwm_shift[SHIFT];
193         static int32_t r_pwm_shift[SHIFT];
194         static int32_t l_speed, r_speed;
195         static unsigned i = 0;
196         static unsigned cpt = 0;
197
198         uint8_t flags;
199         int32_t local_l_pwm, local_r_pwm;
200         double x, y, a, a2, d;
201         char cmd[BUFSIZ];
202         int n, pertl = 0, pertr = 0;
203
204         /* corners of the robot */
205         double xfl, yfl; /* front left */
206         double xrl, yrl; /* rear left */
207         double xrr, yrr; /* rear right */
208         double xfr, yfr; /* front right */
209
210         int oppx, oppy;
211         double oppa, oppd;
212
213         /* time shift the command */
214         l_pwm_shift[i] = l_pwm;
215         r_pwm_shift[i] = r_pwm;
216         i ++;
217         i %= SHIFT;
218         local_l_pwm = l_pwm_shift[i];
219         local_r_pwm = r_pwm_shift[i];
220
221         /* read command */
222         if (((cpt ++) & 0x7) == 0) {
223                 n = read(fdr, &cmd, BUFSIZ - 1);
224                 if (n < 1)
225                         n = 0;
226                 cmd[n] = 0;
227         }
228
229         /* perturbation */
230         if (cmd[0] == 'l')
231                 pertl = 1;
232         else if (cmd[0] == 'r')
233                 pertr = 1;
234         if (cmd[0] == 'o') {
235                 if (sscanf(cmd, "opp %d %d", &oppx, &oppy) == 2) {
236                         abs_xy_to_rel_da(oppx, oppy, &oppd, &oppa);
237                         IRQ_LOCK(flags);
238                         beaconboard.oppx = oppx;
239                         beaconboard.oppy = oppy;
240                         beaconboard.oppa = DEG(oppa);
241                         if (beaconboard.oppa < 0)
242                                 beaconboard.oppa += 360;
243                         beaconboard.oppd = oppd;
244                         IRQ_UNLOCK(flags);
245                 }
246         }
247
248         x = position_get_x_double(&mainboard.pos);
249         y = position_get_y_double(&mainboard.pos);
250         a = position_get_a_rad_double(&mainboard.pos);
251
252         l_speed = ((l_speed * FILTER) / 100) +
253                 ((local_l_pwm * 1000 * FILTER2)/1000);
254         r_speed = ((r_speed * FILTER) / 100) +
255                 ((local_r_pwm * 1000 * FILTER2)/1000);
256
257         /* basic collision detection */
258         a2 = atan2(ROBOT_WIDTH/2, ROBOT_HALF_LENGTH_REAR);
259         d = norm(ROBOT_WIDTH/2, ROBOT_HALF_LENGTH_REAR);
260
261         xfl = x + cos(a+a2) * d;
262         yfl = y + sin(a+a2) * d;
263         if (!is_in_area(xfl, yfl, 0) && l_speed > 0)
264                 l_speed = 0;
265
266         xrl = x + cos(a+M_PI-a2) * d;
267         yrl = y + sin(a+M_PI-a2) * d;
268         if (!is_in_area(xrl, yrl, 0) && l_speed < 0)
269                 l_speed = 0;
270
271         xrr = x + cos(a+M_PI+a2) * d;
272         yrr = y + sin(a+M_PI+a2) * d;
273         if (!is_in_area(xrr, yrr, 0) && r_speed < 0)
274                 r_speed = 0;
275
276         xfr = x + cos(a-a2) * d;
277         yfr = y + sin(a-a2) * d;
278         if (!is_in_area(xfr, yfr, 0) && r_speed > 0)
279                 r_speed = 0;
280
281         if (pertl)
282                 l_enc += 5000; /* push 1 cm */
283         if (pertr)
284                 r_enc += 5000; /* push 1 cm */
285
286         /* XXX should lock */
287         l_enc += (l_speed / 1000);
288         r_enc += (r_speed / 1000);
289 }
290
291 void robotsim_pwm(void *arg, int32_t val)
292 {
293         //      printf("%p, %d\n", arg, val);
294         if (arg == LEFT_PWM)
295                 l_pwm = (val / 1.55);
296         else if (arg == RIGHT_PWM)
297                 r_pwm = (val / 1.55);
298 }
299
300 int32_t robotsim_encoder_get(void *arg)
301 {
302         if (arg == LEFT_ENCODER)
303                 return l_enc;
304         else if (arg == RIGHT_ENCODER)
305                 return r_enc;
306         return 0;
307 }
308
309 int robotsim_init(void)
310 {
311         mkfifo("/tmp/.robot_sim2dis", 0600);
312         mkfifo("/tmp/.robot_dis2sim", 0600);
313         fdw = open("/tmp/.robot_sim2dis", O_WRONLY, 0);
314         if (fdw < 0)
315                 return -1;
316         fdr = open("/tmp/.robot_dis2sim", O_RDONLY | O_NONBLOCK, 0);
317         if (fdr < 0) {
318                 close(fdw);
319                 return -1;
320         }
321         return 0;
322 }