]> rtime.felk.cvut.cz Git - eurobot/public.git/blob - src/cand/cand.cc
cand, common, robofsm, types: change bumper rear to bumper rear left and bumper rear...
[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.right >> 8;
109         data[1] = orte_data->motion_speed.right & 0xff;
110         data[2] = orte_data->motion_speed.left >> 8;
111         data[3] = orte_data->motion_speed.left & 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) ? 0 : 1;
209                         orte->robot_bumpers.bumper_left_across = (frame.data[0] & CAN_BUMPER_LEFT_ACROSS) ? 0 : 1;
210                         orte->robot_bumpers.bumper_right = (frame.data[0] & CAN_BUMPER_RIGHT) ? 0 : 1;
211                         orte->robot_bumpers.bumper_right_across = (frame.data[0] & CAN_BUMPER_RIGHT_ACROSS) ? 0 : 1;
212                         orte->robot_bumpers.bumper_rear_left = (frame.data[0] & CAN_BUMPER_REAR_LEFT) ? 0 : 1;
213                         orte->robot_bumpers.bumper_rear_right = (frame.data[0] & CAN_BUMPER_REAR_RIGHT) ? 0 : 1;
214                         ORTEPublicationSend(orte->publication_robot_bumpers);
215                 break;
216
217                 /* positioning by odometry */
218                 case CAN_ODO_DATA:
219                         orte->odo_data.right =
220                                         ((frame.data[0]<<24)|
221                                          (frame.data[1]<<16)|
222                                          (frame.data[2]<<8));
223                         orte->odo_data.left =
224                                         ((frame.data[3]<<24)|
225                                          (frame.data[4]<<16)|
226                                          (frame.data[5]<<8));
227                         ORTEPublicationSend(orte->publication_odo_data);
228                         break;
229
230                 /* positioning by odometry */
231                 case CAN_MOTION_ODOMETRY_SIMPLE:
232                         orte->motion_irc.left =
233                                         ((frame.data[0]<<24)|
234                                          (frame.data[1]<<16)|
235                                          (frame.data[2]<<8));
236                         orte->motion_irc.right =
237                                         ((frame.data[3]<<24)|
238                                          (frame.data[4]<<16)|
239                                          (frame.data[5]<<8));
240                         orte->motion_irc.seq = frame.data[6];
241                         ORTEPublicationSend(orte->publication_motion_irc);
242                         break;
243
244                 /* motion status */
245                 case CAN_MOTION_STATUS:
246                         orte->motion_status.err_left =
247                                         (frame.data[0]<<8)|(frame.data[1]);
248                         orte->motion_status.err_right =
249                                         (frame.data[2]<<8)|(frame.data[3]);
250                         if(++status_cnt == 2) { // h8eurobot sends duplicite can messages
251                                 ORTEPublicationSend(orte->publication_motion_status);
252                                 status_cnt = 0;
253                         }
254                         break;
255                 case CAN_PWR_ADC1:
256                         double volt33, voltBAT;
257                         voltBAT = ((frame.data[0] << 24) | (frame.data[1] << 16) | \
258                                  (frame.data[2] << 8) | (frame.data[3]))/10000.0;
259                         volt33 = ((frame.data[4] << 24) | (frame.data[5] << 16) | \
260                                  (frame.data[6] << 8) | (frame.data[7]))/10000.0;
261                         orte->pwr_voltage.voltage33 = volt33;
262                         orte->pwr_voltage.voltageBAT = voltBAT;
263                         break;
264
265                 case CAN_PWR_ADC2:
266                         double volt80, volt50;
267                         volt50 = ((frame.data[0] << 24) | (frame.data[1] << 16) | \
268                                  (frame.data[2] << 8) | (frame.data[3]))/10000.0;
269                         volt80 = ((frame.data[4] << 24) | (frame.data[5] << 16) | \
270                                  (frame.data[6] << 8) | (frame.data[7]))/10000.0;
271                         orte->pwr_voltage.voltage80 = volt80;
272                         orte->pwr_voltage.voltage50 = volt50;
273
274                         ORTEPublicationSend(orte->publication_pwr_voltage);
275                         
276                         break;
277                 default:
278                         //FIXME: add logging here (Filip)
279 //                      printf("received CAN msg with unknown id: %x\n",frame.can_id);
280                         break;
281         }
282 }
283
284 void rcv_pwr_ctrl_cb (const ORTERecvInfo *info, void *vinstance, 
285                         void *recvCallBackParam) 
286 {
287         struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
288
289         switch (info->status) {
290                 case NEW_DATA:
291                         set_pwr_ctrl(orte_data);
292                         break;
293                 case DEADLINE:
294                         //printf("ORTE deadline occurred - PWR_CTRL receive\n");
295                         break;
296         }
297 }
298
299 void rcv_can_msg_cb (const ORTERecvInfo *info, void *vinstance, 
300                         void *recvCallBackParam) 
301 {
302         struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
303
304         switch (info->status) {
305                 case NEW_DATA:
306                         send_can_msg(orte_data);
307                         break;
308                 case DEADLINE:
309                         //printf("ORTE deadline occurred - PWR_CTRL receive\n");
310                         break;
311         }
312 }
313 void rcv_pwr_alert_cb (const ORTERecvInfo *info, void *vinstance, 
314                         void *recvCallBackParam) 
315 {
316
317         struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
318         switch (info->status) {
319                 case NEW_DATA:
320                         set_pwr_alert(orte_data);
321                         break;
322                 case DEADLINE:
323                         //printf("ORTE deadline occurred - PWR_CTRL receive\n");
324                         break;
325         }
326 }
327
328 void rcv_motion_speed_cb(const ORTERecvInfo *info, void *vinstance, 
329                                 void *recvCallBackParam)
330 {
331         struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
332
333         switch (info->status) {
334                 case NEW_DATA:
335                         /* reversing motion direction, as it is different, than last year */
336                         orte_data->motion_speed.left *= 1;
337                         orte_data->motion_speed.right *= 1;
338                         set_motor_speed(orte_data);
339                         /*printf("motor cmd received\n");*/
340                         break;
341                 case DEADLINE:
342                         //printf("motor cmd deadline occurred, stopping motors\n");
343                         orte_data->motion_speed.left = 0;
344                         orte_data->motion_speed.right = 0;
345                         set_motor_speed(orte_data);
346                         break;
347         }
348 }
349
350 void rcv_jaws_cmd_cb(const ORTERecvInfo *info, void *vinstance,
351                       void *recvCallBackParam)
352 {
353         struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
354
355         switch (info->status) {
356                 case NEW_DATA:
357                         set_jaws_cmd(orte_data);
358                         break;
359                 case DEADLINE:
360                         break;
361         }
362 }
363
364 void rcv_lift_cmd_cb(const ORTERecvInfo *info, void *vinstance,
365                       void *recvCallBackParam)
366 {
367         struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
368
369         switch (info->status) {
370                 case NEW_DATA:
371                         set_lift_cmd(orte_data);
372                         break;
373                 case DEADLINE:
374                         break;
375 }
376 }
377
378 int main(int argc, char *argv[])
379 {
380         int ret;
381         int size;
382
383         struct robottype_orte_data orte;
384         struct can_frame frame;
385
386         if (cand_init() < 0) {
387                 printf("cand: init failed\n");
388                 exit(1);
389         } else {
390                 printf("cand: init OK\n");
391         }
392
393         orte.strength = 1;
394
395         /* orte initialization */
396         if(robottype_roboorte_init(&orte)) {
397                 printf("Roboorte initialization failed! Exiting...\n");
398                 exit(-1);
399         }
400         else
401                 printf("Roboorte OK\n");
402
403         /* creating publishers */
404         robottype_publisher_pwr_voltage_create(&orte, NULL, NULL);
405         robottype_publisher_motion_status_create(&orte, NULL, NULL);
406         robottype_publisher_odo_data_create(&orte, NULL, NULL);
407         robottype_publisher_motion_irc_create(&orte, NULL, NULL);
408         robottype_publisher_robot_cmd_create(&orte, NULL, NULL);
409         robottype_publisher_robot_switches_create(&orte, NULL, NULL);
410         robottype_publisher_robot_bumpers_create(&orte, NULL, NULL);
411         robottype_publisher_jaws_status_create(&orte, NULL, NULL);
412         robottype_publisher_lift_status_create(&orte, NULL, NULL);
413         printf("Publishers OK\n");
414
415         /* creating subscribers */
416         robottype_subscriber_pwr_ctrl_create(&orte, rcv_pwr_ctrl_cb, &orte);
417         robottype_subscriber_pwr_alert_create(&orte, rcv_pwr_alert_cb, &orte);
418         robottype_subscriber_motion_speed_create(&orte, rcv_motion_speed_cb, &orte);
419         robottype_subscriber_jaws_cmd_create(&orte, rcv_jaws_cmd_cb, &orte);
420         robottype_subscriber_lift_cmd_create(&orte, rcv_lift_cmd_cb, &orte);
421         robottype_subscriber_can_msg_create(&orte, rcv_can_msg_cb, &orte);
422
423
424         printf("subscribers OK\n");
425
426         /* main loop */
427         for(;;) {
428                 struct pollfd pfd[1] = {{sock, POLLIN, 0}};
429
430                 ret = poll(pfd, 1, -1);
431                 if (ret < 0) {
432                         perror("cand: poll() error");
433                         goto err;
434                 }
435
436                 /* timeout expired, nothing to be done */
437                 if (ret == 0)
438                         continue;
439
440                 /* read data from SocketCAN */
441                 size = read(sock, &frame, sizeof(struct can_frame));
442
443                 /* parse data */
444                 if (size > 0)
445                         cand_parse_frame(&orte, frame);
446         }
447         return EXIT_SUCCESS;
448
449 err:
450         close(sock);
451         return 1;
452 }