vt100: include pgmspace.h as we use PROGMEM macro
[aversive.git] / 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
48 #include <parse.h>
49 #include <rdline.h>
50
51 #include "../common/i2c_commands.h"
52 #include "strat.h"
53 #include "strat_utils.h"
54 #include "main.h"
55
56 static int32_t l_pwm, r_pwm;
57 static int32_t l_enc, r_enc;
58
59 static int fdr, fdw;
60 /*
61  * Debug with GDB:
62  *
63  * (gdb) handle SIGUSR1 pass
64  * Signal        Stop   Print   Pass to program Description
65  * SIGUSR1       Yes    Yes     Yes             User defined signal 1
66  * (gdb) handle SIGUSR2 pass
67  * Signal        Stop   Print   Pass to program Description
68  * SIGUSR2       Yes    Yes     Yes             User defined signal 2
69  * (gdb) handle SIGUSR1 noprint
70  * Signal        Stop   Print   Pass to program Description
71  * SIGUSR1       No     No      Yes             User defined signal 1
72  * (gdb) handle SIGUSR2 noprint
73  */
74
75 /* */
76 #define FILTER  98
77 #define FILTER2 (100-FILTER)
78 #define SHIFT   4
79
80 void robotsim_dump(void)
81 {
82         char buf[BUFSIZ];
83         int len;
84         int16_t x, y, a;
85
86         x = position_get_x_s16(&mainboard.pos);
87         y = position_get_y_s16(&mainboard.pos);
88         a = position_get_a_deg_s16(&mainboard.pos);
89 /*      y = COLOR_Y(y); */
90 /*      a = COLOR_A(a); */
91
92         len = snprintf(buf, sizeof(buf), "pos=%d,%d,%d\n",
93                        x, y, a);
94         hostsim_lock();
95         write(fdw, buf, len);
96         hostsim_unlock();
97 }
98
99 static int8_t
100 robotsim_i2c_ballboard_set_mode(struct i2c_cmd_ballboard_set_mode *cmd)
101 {
102         char buf[BUFSIZ];
103         int len;
104
105         ballboard.mode = cmd->mode;
106         len = snprintf(buf, sizeof(buf), "ballboard=%d\n", cmd->mode);
107         hostsim_lock();
108         write(fdw, buf, len);
109         hostsim_unlock();
110         return 0;
111 }
112
113 int8_t
114 robotsim_i2c_cobboard_set_mode(uint8_t mode)
115 {
116         char buf[BUFSIZ];
117         int len;
118
119         if (cobboard.mode == mode)
120                 return 0;
121
122         cobboard.mode = mode;
123         len = snprintf(buf, sizeof(buf), "cobboard=%d\n", mode);
124         hostsim_lock();
125         write(fdw, buf, len);
126         hostsim_unlock();
127         return 0;
128 }
129
130 static int8_t
131 robotsim_i2c_ballboard(uint8_t addr, uint8_t *buf, uint8_t size)
132 {
133         void *void_cmd = buf;
134
135         switch (buf[0]) {
136         case I2C_CMD_BALLBOARD_SET_MODE:
137                 {
138                         struct i2c_cmd_ballboard_set_mode *cmd = void_cmd;
139                         robotsim_i2c_ballboard_set_mode(cmd);
140                         break;
141                 }
142
143         default:
144                 break;
145         }
146         return 0;
147 }
148
149 static int8_t
150 robotsim_i2c_cobboard(uint8_t addr, uint8_t *buf, uint8_t size)
151 {
152         //      void *void_cmd = buf;
153
154         switch (buf[0]) {
155 #if 0 /* deleted */
156         case I2C_CMD_COBBOARD_SET_MODE:
157                 {
158                         struct i2c_cmd_cobboard_set_mode *cmd = void_cmd;
159                         robotsim_i2c_cobboard_set_mode(cmd);
160                         break;
161                 }
162 #endif
163         default:
164                 break;
165         }
166         return 0;
167 }
168
169 int8_t
170 robotsim_i2c(uint8_t addr, uint8_t *buf, uint8_t size)
171 {
172         if (addr == I2C_BALLBOARD_ADDR)
173                 return robotsim_i2c_ballboard(addr, buf, size);
174         else if (addr == I2C_COBBOARD_ADDR)
175                 return robotsim_i2c_cobboard(addr, buf, size);
176         return 0;
177 }
178
179 /* must be called periodically */
180 void robotsim_update(void)
181 {
182         static int32_t l_pwm_shift[SHIFT];
183         static int32_t r_pwm_shift[SHIFT];
184         static int32_t l_speed, r_speed;
185         static unsigned i = 0;
186         static unsigned cpt = 0;
187         int32_t local_l_pwm, local_r_pwm;
188         double x, y, a, a2, d;
189         char cmd = 0;
190
191         /* corners of the robot */
192         double xfl, yfl; /* front left */
193         double xrl, yrl; /* rear left */
194         double xrr, yrr; /* rear right */
195         double xfr, yfr; /* front right */
196
197         /* time shift the command */
198         l_pwm_shift[i] = l_pwm;
199         r_pwm_shift[i] = r_pwm;
200         i ++;
201         i %= SHIFT;
202         local_l_pwm = l_pwm_shift[i];
203         local_r_pwm = r_pwm_shift[i];
204
205         /* read command */
206         if (((cpt ++) & 0x7) == 0) {
207                 if (read(fdr, &cmd, 1) != 1)
208                         cmd = 0;
209         }
210
211         x = position_get_x_double(&mainboard.pos);
212         y = position_get_y_double(&mainboard.pos);
213         a = position_get_a_rad_double(&mainboard.pos);
214
215         l_speed = ((l_speed * FILTER) / 100) +
216                 ((local_l_pwm * 1000 * FILTER2)/1000);
217         r_speed = ((r_speed * FILTER) / 100) +
218                 ((local_r_pwm * 1000 * FILTER2)/1000);
219
220         /* basic collision detection */
221         a2 = atan2(ROBOT_WIDTH/2, ROBOT_HALF_LENGTH_REAR);
222         d = norm(ROBOT_WIDTH/2, ROBOT_HALF_LENGTH_REAR);
223
224         xfl = x + cos(a+a2) * d;
225         yfl = y + sin(a+a2) * d;
226         if (!is_in_area(xfl, yfl, 0) && l_speed > 0)
227                 l_speed = 0;
228
229         xrl = x + cos(a+M_PI-a2) * d;
230         yrl = y + sin(a+M_PI-a2) * d;
231         if (!is_in_area(xrl, yrl, 0) && l_speed < 0)
232                 l_speed = 0;
233
234         xrr = x + cos(a+M_PI+a2) * d;
235         yrr = y + sin(a+M_PI+a2) * d;
236         if (!is_in_area(xrr, yrr, 0) && r_speed < 0)
237                 r_speed = 0;
238
239         xfr = x + cos(a-a2) * d;
240         yfr = y + sin(a-a2) * d;
241         if (!is_in_area(xfr, yfr, 0) && r_speed > 0)
242                 r_speed = 0;
243
244         /* perturbation */
245         if (cmd == 'l')
246                 l_enc += 5000; /* push 1 cm */
247         if (cmd == 'r')
248                 r_enc += 5000; /* push 1 cm */
249
250         /* XXX should lock */
251         l_enc += (l_speed / 1000);
252         r_enc += (r_speed / 1000);
253 }
254
255 void robotsim_pwm(void *arg, int32_t val)
256 {
257         //      printf("%p, %d\n", arg, val);
258         if (arg == LEFT_PWM)
259                 l_pwm = (val / 1.55);
260         else if (arg == RIGHT_PWM)
261                 r_pwm = (val / 1.55);
262 }
263
264 int32_t robotsim_encoder_get(void *arg)
265 {
266         if (arg == LEFT_ENCODER)
267                 return l_enc;
268         else if (arg == RIGHT_ENCODER)
269                 return r_enc;
270         return 0;
271 }
272
273 int robotsim_init(void)
274 {
275         mkfifo("/tmp/.robot_sim2dis", 0600);
276         mkfifo("/tmp/.robot_dis2sim", 0600);
277         fdw = open("/tmp/.robot_sim2dis", O_WRONLY, 0);
278         if (fdw < 0)
279                 return -1;
280         fdr = open("/tmp/.robot_dis2sim", O_RDONLY | O_NONBLOCK, 0);
281         if (fdr < 0) {
282                 close(fdw);
283                 return -1;
284         }
285         return 0;
286 }