]> rtime.felk.cvut.cz Git - eurobot/public.git/blob - src/cand/cand.cc
cand: Switch motion err status direction.
[eurobot/public.git] / src / cand / cand.cc
1 /**
2  * @file   cand.cc
3  * @date   08/04/08
4  * 
5  * @brief  CAN-ORTE bridge
6  * 
7  * Copyright: (c) 2008 CTU Dragons
8  *            CTU FEE - Department of Control Engineering
9  * License: GNU GPL v.2
10  */
11
12 #ifdef HAVE_CONFIG_H
13 #include <config.h>
14 #endif
15
16 #include <cstring>
17 #include <iostream>
18 #include <cstdlib>
19 #include <sys/socket.h>
20 #include <sys/ioctl.h>
21 #include <fcntl.h>
22 #include <poll.h>
23
24 #include <af_can.h>
25 #include <canutils.h>
26
27 #include <can_ids.h>
28 #include <can_msg_masks.h>
29 #include <can_msg_def.h>
30 #include <sharp.h>
31 #include <orte.h>
32 #include <roboorte_robottype.h>
33 #include <can_msg_masks.h>
34 #include "cand.h"
35
36 int cand_init()
37 {
38         if ((sock = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
39                 perror("cand: unable to create a socket");
40                 return -1;
41         }
42
43         can_addr.can_family = AF_CAN;
44         std::strcpy(can_ifreq.ifr_name, "can0");
45
46         if (ioctl(sock, SIOCGIFINDEX, &can_ifreq) < 0) {
47                 perror("cand: SIOCGIFINDEX");
48                 return -2;
49         }
50
51         can_addr.can_ifindex = can_ifreq.ifr_ifindex;
52                 
53         if (!can_addr.can_ifindex) {
54                 perror("cand: invalid socket interface");
55                 return -3;
56         }
57
58         if (bind(sock, (struct sockaddr *)&can_addr, sizeof(can_addr)) < 0) {
59                 perror("cand: unable to bind");
60                 return -4;
61         }
62
63         return 0;
64 }
65
66 int set_pwr_ctrl(struct robottype_orte_data *orte_data)
67 {
68         unsigned char data=0;
69         if(orte_data->pwr_ctrl.voltage33)
70                 data |= CAN_PWR_CTRL_33_ON;
71         else
72                 data |= CAN_PWR_CTRL_33_OFF;
73
74         if(orte_data->pwr_ctrl.voltage50)
75                 data |= CAN_PWR_CTRL_50_ON;
76         else
77                 data |= CAN_PWR_CTRL_50_OFF;
78
79         if(orte_data->pwr_ctrl.voltage80)
80                 data |= CAN_PWR_CTRL_80_ON;
81         else
82                 data |= CAN_PWR_CTRL_80_OFF;
83
84         can_send(CAN_PWR, 1, &data);
85
86         return 0;
87 }
88
89 int set_pwr_alert(struct robottype_orte_data *orte_data)
90 {
91         unsigned char data=0;
92         data = orte_data->pwr_alert.value;
93
94         can_send(CAN_PWR_ALERT, 1, &data);
95
96         return 0;
97 }
98
99 int send_can_msg(struct robottype_orte_data *orte_data)
100 {
101         return can_send(orte_data->can_msg.id, orte_data->can_msg.len, orte_data->can_msg.data);
102 }
103
104 int set_motor_speed(struct robottype_orte_data *orte_data)
105 {
106         unsigned char data[4];
107
108         data[0] = orte_data->motion_speed.left >> 8;
109         data[1] = orte_data->motion_speed.left & 0xff;
110         data[2] = orte_data->motion_speed.right >> 8;
111         data[3] = orte_data->motion_speed.right & 0xff;
112         can_send(CAN_MOTION_CMD, 4, data);
113
114         return 0;
115 }
116
117 int set_jaws_cmd(struct robottype_orte_data *orte_data)
118 {
119         unsigned char data[3];
120
121         data[0] = orte_data->jaws_cmd.req_pos.left >> 8;
122         data[1] = orte_data->jaws_cmd.req_pos.left & 0xff;
123         data[2] = orte_data->jaws_cmd.speed.left;
124         can_send(CAN_JAW_LEFT_CMD, 3, data);
125
126         data[0] = orte_data->jaws_cmd.req_pos.right >> 8;
127         data[1] = orte_data->jaws_cmd.req_pos.right & 0xff;
128         data[2] = orte_data->jaws_cmd.speed.right;
129         can_send(CAN_JAW_RIGHT_CMD, 3, data);
130
131         return 0;
132 }
133
134 int set_lift_cmd(struct robottype_orte_data *orte_data)
135 {
136         unsigned char data[4];
137
138         data[0] = orte_data->lift_cmd.req_pos >> 8;
139         data[1] = orte_data->lift_cmd.req_pos & 0xff;
140         data[2] = orte_data->lift_cmd.speed;
141         data[3] = orte_data->lift_cmd.homing;
142         can_send(CAN_LIFT_CMD, 4, data);
143
144         return 0;
145 }
146
147 int can_send(canid_t id, unsigned char length, unsigned char *data)
148 {
149         struct can_frame frame;
150         size_t size;
151
152         frame.can_id = id;
153         frame.can_dlc = length;
154
155         for(int i=0; i<length; i++)
156                 frame.data[i] = data[i];
157
158         if ((size = write(sock, &frame, sizeof(struct can_frame))) < 0) {
159                 perror("cand: can send: write()");
160                 return -1;
161         } else if (size < sizeof(struct can_frame)) {
162                 perror("cand: can send: incomplete CAN frame\n");
163                 return 1;
164         }
165
166         return 0;
167 }
168
169 /**
170  * Parse frame ID and react as required
171  */
172 void cand_parse_frame(struct robottype_orte_data *orte, struct can_frame frame)
173 {
174         static int status_cnt = 0;
175
176         switch(frame.can_id) {
177                 /* voltage measurements from power board */
178
179                 /* robot commands (start, ..) */
180                 case CAN_JAW_LEFT_STATUS:
181                         orte->jaws_status.act_pos.left = (frame.data[0] << 8) | frame.data[1];
182                         orte->jaws_status.response.left = (frame.data[2] << 8) | frame.data[3];
183                         orte->jaws_status.flags.left = frame.data[4];
184                         ORTEPublicationSend(orte->publication_jaws_status);
185                         break;
186                 case CAN_JAW_RIGHT_STATUS:
187                         orte->jaws_status.act_pos.right = (frame.data[0] << 8) | frame.data[1];
188                         orte->jaws_status.response.right = (frame.data[2] << 8) | frame.data[3];
189                         orte->jaws_status.flags.right = frame.data[4];
190                         ORTEPublicationSend(orte->publication_jaws_status);
191                 break;
192                 case CAN_LIFT_STATUS:
193                         orte->lift_status.act_pos = (frame.data[0] << 8) | frame.data[1];
194                         orte->lift_status.response = (frame.data[2] << 8) | frame.data[3];
195                         orte->lift_status.flags = frame.data[4];
196                         ORTEPublicationSend(orte->publication_lift_status);
197                 break;
198                 case CAN_ROBOT_CMD:
199                         orte->robot_cmd.start_condition = frame.data[0];
200                         ORTEPublicationSend(orte->publication_robot_cmd);
201                         break;
202                 case CAN_ROBOT_SWITCHES:
203                         orte->robot_switches.team_color = (frame.data[0] & CAN_SWITCH_COLOR) ? 1 : 0;
204                         orte->robot_switches.strategy = !!(frame.data[0] & CAN_SWITCH_STRATEGY);
205                         ORTEPublicationSend(orte->publication_robot_switches);
206                         break;
207                 case CAN_ROBOT_BUMPERS:
208                         orte->robot_bumpers.bumper_left = !!(frame.data[0] & CAN_BUMPER_LEFT);
209                         orte->robot_bumpers.bumper_left_across = !!(frame.data[0] & CAN_BUMPER_LEFT_ACROSS);
210                         orte->robot_bumpers.bumper_right = !!(frame.data[0] & CAN_BUMPER_RIGHT);
211                         orte->robot_bumpers.bumper_right_across = !!(frame.data[0] & CAN_BUMPER_RIGHT_ACROSS);
212                         orte->robot_bumpers.bumper_rear = !!(frame.data[0] & CAN_BUMPER_REAR);
213                         ORTEPublicationSend(orte->publication_robot_switches);
214                 break;
215
216                 /* positioning by odometry */
217                 case CAN_ODO_DATA:
218                         orte->odo_data.left = 
219                                         ((frame.data[0]<<24)|
220                                          (frame.data[1]<<16)|
221                                          (frame.data[2]<<8));
222                         orte->odo_data.right = 
223                                         ((frame.data[3]<<24)|
224                                          (frame.data[4]<<16)|
225                                          (frame.data[5]<<8));
226                         ORTEPublicationSend(orte->publication_odo_data);
227                         break;
228
229                 /* positioning by odometry */
230                 case CAN_MOTION_ODOMETRY_SIMPLE:
231                         orte->motion_irc.right = 
232                                         ((frame.data[0]<<24)|
233                                          (frame.data[1]<<16)|
234                                          (frame.data[2]<<8));
235                         orte->motion_irc.left = 
236                                         ((frame.data[3]<<24)|
237                                          (frame.data[4]<<16)|
238                                          (frame.data[5]<<8));
239                         orte->motion_irc.seq = frame.data[6];
240                         ORTEPublicationSend(orte->publication_motion_irc);
241                         break;
242
243                 /* motion status */
244                 case CAN_MOTION_STATUS:
245                         orte->motion_status.err_right =
246                                         (frame.data[0]<<8)|(frame.data[1]);
247                         orte->motion_status.err_left =
248                                         (frame.data[2]<<8)|(frame.data[3]);
249                         if(++status_cnt == 2) { // h8eurobot sends duplicite can messages
250                                 ORTEPublicationSend(orte->publication_motion_status);
251                                 status_cnt = 0;
252                         }
253                         break;
254                 case CAN_PWR_ADC1:
255                         double volt33, voltBAT;
256                         voltBAT = ((frame.data[0] << 24) | (frame.data[1] << 16) | \
257                                  (frame.data[2] << 8) | (frame.data[3]))/10000.0;
258                         volt33 = ((frame.data[4] << 24) | (frame.data[5] << 16) | \
259                                  (frame.data[6] << 8) | (frame.data[7]))/10000.0;
260                         orte->pwr_voltage.voltage33 = volt33;
261                         orte->pwr_voltage.voltageBAT = voltBAT;
262                         break;
263
264                 case CAN_PWR_ADC2:
265                         double volt80, volt50;
266                         volt50 = ((frame.data[0] << 24) | (frame.data[1] << 16) | \
267                                  (frame.data[2] << 8) | (frame.data[3]))/10000.0;
268                         volt80 = ((frame.data[4] << 24) | (frame.data[5] << 16) | \
269                                  (frame.data[6] << 8) | (frame.data[7]))/10000.0;
270                         orte->pwr_voltage.voltage80 = volt80;
271                         orte->pwr_voltage.voltage50 = volt50;
272
273                         ORTEPublicationSend(orte->publication_pwr_voltage);
274                         
275                         break;
276                 default:
277                         //FIXME: add logging here (Filip)
278 //                      printf("received CAN msg with unknown id: %x\n",frame.can_id);
279                         break;
280         }
281 }
282
283 void rcv_pwr_ctrl_cb (const ORTERecvInfo *info, void *vinstance, 
284                         void *recvCallBackParam) 
285 {
286         struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
287
288         switch (info->status) {
289                 case NEW_DATA:
290                         set_pwr_ctrl(orte_data);
291                         break;
292                 case DEADLINE:
293                         //printf("ORTE deadline occurred - PWR_CTRL receive\n");
294                         break;
295         }
296 }
297
298 void rcv_can_msg_cb (const ORTERecvInfo *info, void *vinstance, 
299                         void *recvCallBackParam) 
300 {
301         struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
302
303         switch (info->status) {
304                 case NEW_DATA:
305                         send_can_msg(orte_data);
306                         break;
307                 case DEADLINE:
308                         //printf("ORTE deadline occurred - PWR_CTRL receive\n");
309                         break;
310         }
311 }
312 void rcv_pwr_alert_cb (const ORTERecvInfo *info, void *vinstance, 
313                         void *recvCallBackParam) 
314 {
315
316         struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
317         switch (info->status) {
318                 case NEW_DATA:
319                         set_pwr_alert(orte_data);
320                         break;
321                 case DEADLINE:
322                         //printf("ORTE deadline occurred - PWR_CTRL receive\n");
323                         break;
324         }
325 }
326
327 void rcv_motion_speed_cb(const ORTERecvInfo *info, void *vinstance, 
328                                 void *recvCallBackParam)
329 {
330         struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
331
332         switch (info->status) {
333                 case NEW_DATA:
334                         /* reversing motion direction, as it is different, than last year */
335                         orte_data->motion_speed.left *= -1;
336                         orte_data->motion_speed.right *=-1;
337                         set_motor_speed(orte_data);
338                         /*printf("motor cmd received\n");*/
339                         break;
340                 case DEADLINE:
341                         //printf("motor cmd deadline occurred, stopping motors\n");
342                         orte_data->motion_speed.left = 0;
343                         orte_data->motion_speed.right = 0;
344                         set_motor_speed(orte_data);
345                         break;
346         }
347 }
348
349 void rcv_jaws_cmd_cb(const ORTERecvInfo *info, void *vinstance,
350                       void *recvCallBackParam)
351 {
352         struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
353
354         switch (info->status) {
355                 case NEW_DATA:
356                         set_jaws_cmd(orte_data);
357                         break;
358                 case DEADLINE:
359                         break;
360         }
361 }
362
363 void rcv_lift_cmd_cb(const ORTERecvInfo *info, void *vinstance,
364                       void *recvCallBackParam)
365 {
366         struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
367
368         switch (info->status) {
369                 case NEW_DATA:
370                         set_lift_cmd(orte_data);
371                         break;
372                 case DEADLINE:
373                         break;
374 }
375 }
376
377 int main(int argc, char *argv[])
378 {
379         int ret;
380         int size;
381
382         struct robottype_orte_data orte;
383         struct can_frame frame;
384
385         if (cand_init() < 0) {
386                 printf("cand: init failed\n");
387                 exit(1);
388         } else {
389                 printf("cand: init OK\n");
390         }
391
392         orte.strength = 1;
393
394         /* orte initialization */
395         if(robottype_roboorte_init(&orte)) {
396                 printf("Roboorte initialization failed! Exiting...\n");
397                 exit(-1);
398         }
399         else
400                 printf("Roboorte OK\n");
401
402         /* creating publishers */
403         robottype_publisher_pwr_voltage_create(&orte, NULL, NULL);
404         robottype_publisher_motion_status_create(&orte, NULL, NULL);
405         robottype_publisher_odo_data_create(&orte, NULL, NULL);
406         robottype_publisher_motion_irc_create(&orte, NULL, NULL);
407         robottype_publisher_robot_cmd_create(&orte, NULL, NULL);
408         robottype_publisher_robot_switches_create(&orte, NULL, NULL);
409         robottype_publisher_robot_bumpers_create(&orte, NULL, NULL);
410         robottype_publisher_jaws_status_create(&orte, NULL, NULL);
411         robottype_publisher_lift_status_create(&orte, NULL, NULL);
412         printf("Publishers OK\n");
413
414         /* creating subscribers */
415         robottype_subscriber_pwr_ctrl_create(&orte, rcv_pwr_ctrl_cb, &orte);
416         robottype_subscriber_pwr_alert_create(&orte, rcv_pwr_alert_cb, &orte);
417         robottype_subscriber_motion_speed_create(&orte, rcv_motion_speed_cb, &orte);
418         robottype_subscriber_jaws_cmd_create(&orte, rcv_jaws_cmd_cb, &orte);
419         robottype_subscriber_lift_cmd_create(&orte, rcv_lift_cmd_cb, &orte);
420         robottype_subscriber_can_msg_create(&orte, rcv_can_msg_cb, &orte);
421
422
423         printf("subscribers OK\n");
424
425         /* main loop */
426         for(;;) {
427                 struct pollfd pfd[1] = {{sock, POLLIN, 0}};
428
429                 ret = poll(pfd, 1, -1);
430                 if (ret < 0) {
431                         perror("cand: poll() error");
432                         goto err;
433                 }
434
435                 /* timeout expired, nothing to be done */
436                 if (ret == 0)
437                         continue;
438
439                 /* read data from SocketCAN */
440                 size = read(sock, &frame, sizeof(struct can_frame));
441
442                 /* parse data */
443                 if (size > 0)
444                         cand_parse_frame(&orte, frame);
445         }
446         return EXIT_SUCCESS;
447
448 err:
449         close(sock);
450         return 1;
451 }