5 * @brief CAN-ORTE bridge
7 * Copyright: (c) 2008 CTU Dragons
8 * CTU FEE - Department of Control Engineering
19 #include <sys/socket.h>
20 #include <sys/ioctl.h>
27 #include <can_msg_masks.h>
28 #include <can_msg_def.h>
31 #include <roboorte_robottype.h>
32 #include <can_msg_masks.h>
37 if ((sock = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
38 perror("cand: unable to create a socket");
42 can_addr.can_family = AF_CAN;
43 std::strcpy(can_ifreq.ifr_name, "can0");
45 if (ioctl(sock, SIOCGIFINDEX, &can_ifreq) < 0) {
46 perror("cand: SIOCGIFINDEX");
50 can_addr.can_ifindex = can_ifreq.ifr_ifindex;
52 if (!can_addr.can_ifindex) {
53 perror("cand: invalid socket interface");
57 if (bind(sock, (struct sockaddr *)&can_addr, sizeof(can_addr)) < 0) {
58 perror("cand: unable to bind");
65 int set_pwr_ctrl(struct robottype_orte_data *orte_data)
68 if(orte_data->pwr_ctrl.voltage33)
69 data |= CAN_PWR_CTRL_33_ON;
71 data |= CAN_PWR_CTRL_33_OFF;
73 if(orte_data->pwr_ctrl.voltage50)
74 data |= CAN_PWR_CTRL_50_ON;
76 data |= CAN_PWR_CTRL_50_OFF;
78 if(orte_data->pwr_ctrl.voltage80)
79 data |= CAN_PWR_CTRL_80_ON;
81 data |= CAN_PWR_CTRL_80_OFF;
83 can_send(CAN_PWR, 1, &data);
88 int set_pwr_alert(struct robottype_orte_data *orte_data)
91 data = orte_data->pwr_alert.value;
93 can_send(CAN_PWR_ALERT, 1, &data);
98 int send_can_msg(struct robottype_orte_data *orte_data)
100 can_send(orte_data->can_msg.id, orte_data->can_msg.len, orte_data->can_msg.data);
103 int set_motor_speed(struct robottype_orte_data *orte_data)
105 unsigned char data[4];
107 data[0] = orte_data->motion_speed.right >> 8;
108 data[1] = orte_data->motion_speed.right & 0xff;
109 data[2] = orte_data->motion_speed.left >> 8;
110 data[3] = orte_data->motion_speed.left & 0xff;
111 can_send(CAN_MOTION_CMD, 4, data);
117 * Sends #CAN_HOKUYO_PITCH message.
119 * - data = orte_data->pusher.pos
121 int set_hokuyo_pitch(struct robottype_orte_data *orte_data)
123 unsigned char data = orte_data->hokuyo_pitch.angle;
125 can_send(CAN_HOKUYO_PITCH, sizeof(data), &data);
130 int can_send(canid_t id, unsigned char length, unsigned char *data)
132 struct can_frame frame;
136 frame.can_dlc = length;
138 for(int i=0; i<length; i++)
139 frame.data[i] = data[i];
141 if ((size = write(sock, &frame, sizeof(struct can_frame))) < 0) {
142 perror("cand: can send: write()");
144 } else if (size < sizeof(struct can_frame)) {
145 perror("cand: can send: incomplete CAN frame\n");
153 * Parse frame ID and react as required
155 int cand_parse_frame(struct robottype_orte_data *orte, struct can_frame frame)
159 switch(frame.can_id) {
160 /* voltage measurements from power board */
162 /* robot commands (start, ..) */
164 orte->robot_cmd.start = frame.data[0];
165 orte->robot_cmd.stop = frame.data[1];
166 ORTEPublicationSend(orte->publication_robot_cmd);
169 /* global sampling period -- time trigger */
171 orte->corr_trig.seq = frame.data[0];
172 ORTEPublicationSend(orte->publication_corr_trig);
175 /* distances measured by ULoPoS */
177 orte->corr_distances.t1 = (frame.data[1]<<8)|(frame.data[0]);
178 orte->corr_distances.t2 = (frame.data[3]<<8)|(frame.data[2]);
179 orte->corr_distances.t3 = (frame.data[5]<<8)|(frame.data[4]);
180 ORTEPublicationSend(orte->publication_corr_distances);
183 /* positioning by odometry */
185 orte->odo_data.left =
186 ((frame.data[0]<<24)|
189 orte->odo_data.right =
190 ((frame.data[3]<<24)|
193 ORTEPublicationSend(orte->publication_odo_data);
196 /* positioning by odometry */
197 case CAN_MOTION_ODOMETRY_SIMPLE:
198 orte->motion_irc.right =
199 ((frame.data[0]<<24)|
202 orte->motion_irc.left =
203 ((frame.data[3]<<24)|
206 orte->motion_irc.seq = frame.data[6];
207 ORTEPublicationSend(orte->publication_motion_irc);
211 case CAN_MOTION_STATUS:
212 orte->motion_status.err_left =
213 (frame.data[0]<<8)|(frame.data[1]);
214 orte->motion_status.err_right =
215 (frame.data[2]<<8)|(frame.data[3]);
216 if(++status_cnt == 5) {
217 ORTEPublicationSend(orte->publication_motion_status);
222 double volt33, voltBAT;
223 voltBAT = ((frame.data[0] << 24) | (frame.data[1] << 16) | \
224 (frame.data[2] << 8) | (frame.data[3]))/10000.0;
225 volt33 = ((frame.data[4] << 24) | (frame.data[5] << 16) | \
226 (frame.data[6] << 8) | (frame.data[7]))/10000.0;
227 orte->pwr_voltage.voltage33 = volt33;
228 orte->pwr_voltage.voltageBAT = voltBAT;
232 double volt80, volt50;
233 volt50 = ((frame.data[0] << 24) | (frame.data[1] << 16) | \
234 (frame.data[2] << 8) | (frame.data[3]))/10000.0;
235 volt80 = ((frame.data[4] << 24) | (frame.data[5] << 16) | \
236 (frame.data[6] << 8) | (frame.data[7]))/10000.0;
237 orte->pwr_voltage.voltage80 = volt80;
238 orte->pwr_voltage.voltage50 = volt50;
240 ORTEPublicationSend(orte->publication_pwr_voltage);
244 //FIXME: add logging here (Filip)
245 // printf("received CAN msg with unknown id: %x\n",frame.can_id);
250 void rcv_pwr_ctrl_cb (const ORTERecvInfo *info, void *vinstance,
251 void *recvCallBackParam)
253 struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
255 switch (info->status) {
257 set_pwr_ctrl(orte_data);
260 //printf("ORTE deadline occurred - PWR_CTRL receive\n");
265 void rcv_can_msg_cb (const ORTERecvInfo *info, void *vinstance,
266 void *recvCallBackParam)
268 struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
270 switch (info->status) {
272 send_can_msg(orte_data);
275 //printf("ORTE deadline occurred - PWR_CTRL receive\n");
279 void rcv_pwr_alert_cb (const ORTERecvInfo *info, void *vinstance,
280 void *recvCallBackParam)
283 struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
284 switch (info->status) {
286 set_pwr_alert(orte_data);
289 //printf("ORTE deadline occurred - PWR_CTRL receive\n");
294 void rcv_motion_speed_cb(const ORTERecvInfo *info, void *vinstance,
295 void *recvCallBackParam)
297 struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
299 switch (info->status) {
301 /* reversing motion direction, as it is different, than last year */
302 orte_data->motion_speed.left *= -1;
303 orte_data->motion_speed.right *=-1;
304 set_motor_speed(orte_data);
305 /*printf("motor cmd received\n");*/
308 //printf("motor cmd deadline occurred, stopping motors\n");
309 orte_data->motion_speed.left = 0;
310 orte_data->motion_speed.right = 0;
311 set_motor_speed(orte_data);
316 void rcv_hokuyo_pitch_cb (const ORTERecvInfo *info, void *vinstance,
317 void *recvCallBackParam)
319 struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
321 switch (info->status) {
323 set_hokuyo_pitch(orte_data);
326 // printf("ORTE deadline occurred - hokuyo pitch receive\n");
332 int main(int argc, char *argv[])
335 struct timeval timeout;
339 struct robottype_orte_data orte;
340 struct can_frame frame;
342 if (cand_init() < 0) {
343 printf("cand: init failed\n");
346 printf("cand: init OK\n");
351 /* orte initialization */
352 if(robottype_roboorte_init(&orte)) {
353 printf("Roboorte initialization failed! Exiting...\n");
357 printf("Roboorte OK\n");
359 /* creating publishers */
360 robottype_publisher_pwr_voltage_create(&orte, NULL, NULL);
361 robottype_publisher_motion_status_create(&orte, NULL, NULL);
362 robottype_publisher_odo_data_create(&orte, NULL, NULL);
363 robottype_publisher_motion_irc_create(&orte, NULL, NULL);
364 robottype_publisher_robot_cmd_create(&orte, NULL, NULL);
365 robottype_publisher_corr_trig_create(&orte, NULL, NULL);
366 robottype_publisher_corr_distances_create(&orte, NULL, NULL);
367 robottype_publisher_actuator_status_create(&orte, NULL, NULL);
368 printf("Publishers OK\n");
370 /* creating subscribers */
371 robottype_subscriber_pwr_ctrl_create(&orte, rcv_pwr_ctrl_cb, &orte);
372 robottype_subscriber_pwr_alert_create(&orte, rcv_pwr_alert_cb, &orte);
373 robottype_subscriber_motion_speed_create(&orte, rcv_motion_speed_cb, &orte);
374 robottype_subscriber_can_msg_create(&orte, rcv_can_msg_cb, &orte);
375 robottype_subscriber_hokuyo_pitch_create(&orte, rcv_hokuyo_pitch_cb, &orte);
377 printf("subscribers OK\n");
381 FD_ZERO(&read_fd_set);
382 FD_SET(sock, &read_fd_set);
384 timeout.tv_usec = 10000;
386 ret = select(FD_SETSIZE, &read_fd_set, NULL, NULL, &timeout);
388 perror("cand: select() error");
392 /* timeout expired, nothing to be done */
396 if (!FD_ISSET(sock, &read_fd_set))
399 /* read data from SocketCAN */
400 size = read(sock, &frame, sizeof(struct can_frame));
403 cand_parse_frame(&orte, frame);