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>
30 #include <can_msg_masks.h>
31 #include <can_msg_def.h>
33 #include <roboorte_robottype.h>
34 #include <can_msg_masks.h>
39 if ((sock = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
40 perror("cand: unable to create a socket");
44 can_addr.can_family = AF_CAN;
45 std::strcpy(can_ifreq.ifr_name, "can0");
47 if (ioctl(sock, SIOCGIFINDEX, &can_ifreq) < 0) {
48 perror("cand: SIOCGIFINDEX");
52 can_addr.can_ifindex = can_ifreq.ifr_ifindex;
54 if (!can_addr.can_ifindex) {
55 perror("cand: invalid socket interface");
59 if (bind(sock, (struct sockaddr *)&can_addr, sizeof(can_addr)) < 0) {
60 perror("cand: unable to bind");
67 int set_pwr_ctrl(struct robottype_orte_data *orte_data)
70 if(orte_data->pwr_ctrl.voltage33)
71 data |= CAN_PWR_CTRL_33_ON;
73 data |= CAN_PWR_CTRL_33_OFF;
75 if(orte_data->pwr_ctrl.voltage50)
76 data |= CAN_PWR_CTRL_50_ON;
78 data |= CAN_PWR_CTRL_50_OFF;
80 if(orte_data->pwr_ctrl.voltage80)
81 data |= CAN_PWR_CTRL_80_ON;
83 data |= CAN_PWR_CTRL_80_OFF;
85 can_send(CAN_PWR, 1, &data);
90 int send_can_msg(struct robottype_orte_data *orte_data)
92 return can_send(orte_data->can_msg.id, orte_data->can_msg.len, orte_data->can_msg.data);
95 int set_motor_speed(struct robottype_orte_data *orte_data)
97 unsigned char data[4];
99 data[0] = orte_data->motion_speed.right >> 8;
100 data[1] = orte_data->motion_speed.right & 0xff;
101 data[2] = orte_data->motion_speed.left >> 8;
102 data[3] = orte_data->motion_speed.left & 0xff;
103 can_send(CAN_MOTION_CMD, 4, data);
108 int can_send(canid_t id, unsigned char length, unsigned char *data)
110 struct can_frame frame;
114 frame.can_dlc = length;
116 for(int i=0; i<length; i++)
117 frame.data[i] = data[i];
119 if ((size = write(sock, &frame, sizeof(struct can_frame))) < 0) {
120 perror("cand: can send: write()");
122 } else if (size < sizeof(struct can_frame)) {
123 perror("cand: can send: incomplete CAN frame\n");
131 * Parse frame ID and react as required
133 void cand_parse_frame(struct robottype_orte_data *orte, struct can_frame frame)
135 static int status_cnt = 0;
137 switch(frame.can_id) {
138 /* robot commands (start, ..) */
139 case CAN_CL_SENSOR_STATUS:
140 orte->cl_sensor_status.pattern_match = frame.data[0];
141 ORTEPublicationSend(orte->publication_cl_sensor_status);
144 orte->robot_cmd.start_condition = frame.data[0];
145 ORTEPublicationSend(orte->publication_robot_cmd);
147 case CAN_ROBOT_SWITCHES:
150 if (frame.data[0] & CAN_SWITCH_COLOR_0) tmp_color += 1;
151 if (frame.data[0] & CAN_SWITCH_COLOR_1) tmp_color += 2;
152 orte->robot_switches.team_color = tmp_color;
154 orte->robot_switches.team_color = frame.data[0] & (CAN_SWITCH_COLOR_0 + CAN_SWITCH_COLOR_1);
155 orte->robot_switches.strategy = (frame.data[0] & CAN_SWITCH_STRATEGY ? 1 : 0);
156 orte->robot_switches.home = (frame.data[0] & CAN_SWITCH_HOME ? 1 : 0);
157 ORTEPublicationSend(orte->publication_robot_switches);
159 case CAN_ROBOT_BUMPERS:
160 orte->robot_bumpers.bumper_left = (frame.data[0] & CAN_BUMPER_LEFT) ? 0 : 1;
161 orte->robot_bumpers.bumper_left_across = (frame.data[0] & CAN_BUMPER_LEFT_ACROSS) ? 0 : 1;
162 orte->robot_bumpers.bumper_right = (frame.data[0] & CAN_BUMPER_RIGHT) ? 0 : 1;
163 orte->robot_bumpers.bumper_right_across = (frame.data[0] & CAN_BUMPER_RIGHT_ACROSS) ? 0 : 1;
164 orte->robot_bumpers.bumper_rear_left = (frame.data[0] & CAN_BUMPER_REAR_LEFT) ? 0 : 1;
165 orte->robot_bumpers.bumper_rear_right = (frame.data[0] & CAN_BUMPER_REAR_RIGHT) ? 0 : 1;
166 ORTEPublicationSend(orte->publication_robot_bumpers);
169 /* positioning by independent odometry */
171 orte->odo_data.right =
172 ((frame.data[0]<<24)|
175 orte->odo_data.left =
176 ((frame.data[3]<<24)|
179 ORTEPublicationSend(orte->publication_odo_data);
182 /* positioning by odometry from motors*/
183 case CAN_MOTION_ODOMETRY_SIMPLE:
184 orte->motion_irc.left =
185 ((frame.data[0]<<24)|
188 orte->motion_irc.right =
189 ((frame.data[3]<<24)|
192 orte->motion_irc.seq = frame.data[6];
193 ORTEPublicationSend(orte->publication_motion_irc);
197 case CAN_MOTION_STATUS:
198 orte->motion_status.err_left =
199 (frame.data[0]<<8)|(frame.data[1]);
200 orte->motion_status.err_right =
201 (frame.data[2]<<8)|(frame.data[3]);
202 if(++status_cnt == 2) { // h8eurobot sends duplicite can messages
203 ORTEPublicationSend(orte->publication_motion_status);
207 /* voltage measurements from power board */
209 double volt33, voltBAT;
210 voltBAT = ((frame.data[0] << 24) | (frame.data[1] << 16) | \
211 (frame.data[2] << 8) | (frame.data[3]))/10000.0;
212 volt33 = ((frame.data[4] << 24) | (frame.data[5] << 16) | \
213 (frame.data[6] << 8) | (frame.data[7]))/10000.0;
214 orte->pwr_voltage.voltage33 = volt33;
215 orte->pwr_voltage.voltageBAT = voltBAT;
219 double volt80, volt50;
220 volt50 = ((frame.data[0] << 24) | (frame.data[1] << 16) | \
221 (frame.data[2] << 8) | (frame.data[3]))/10000.0;
222 volt80 = ((frame.data[4] << 24) | (frame.data[5] << 16) | \
223 (frame.data[6] << 8) | (frame.data[7]))/10000.0;
224 orte->pwr_voltage.voltage80 = volt80;
225 orte->pwr_voltage.voltage50 = volt50;
227 ORTEPublicationSend(orte->publication_pwr_voltage);
232 orte->pwr_alert.alert_33 = (frame.data[0] & CAN_PWR_ALERT_33 ? 1 : 0);
233 orte->pwr_alert.alert_50 = (frame.data[0] & CAN_PWR_ALERT_50 ? 1 : 0);
234 orte->pwr_alert.alert_80 = (frame.data[0] & CAN_PWR_ALERT_80 ? 1 : 0);
235 orte->pwr_alert.bat_full = (frame.data[0] & CAN_PWR_BATT_FULL ? 1 : 0);
236 orte->pwr_alert.bat_mean = (frame.data[0] & CAN_PWR_BATT_MEAN ? 1 : 0);
237 orte->pwr_alert.bat_low = (frame.data[0] & CAN_PWR_BATT_LOW ? 1 : 0);
238 orte->pwr_alert.bat_critical = (frame.data[0] & CAN_PWR_BATT_CRITICAL ? 1 : 0);
240 ORTEPublicationSend(orte->publication_pwr_alert);
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");
280 void rcv_motion_speed_cb(const ORTERecvInfo *info, void *vinstance,
281 void *recvCallBackParam)
283 struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
285 switch (info->status) {
287 /* reversing motion direction, as it is different, than last year */
288 orte_data->motion_speed.left *= 1;
289 orte_data->motion_speed.right *= 1;
290 set_motor_speed(orte_data);
291 /*printf("motor cmd received\n");*/
294 //printf("motor cmd deadline occurred, stopping motors\n");
295 orte_data->motion_speed.left = 0;
296 orte_data->motion_speed.right = 0;
297 set_motor_speed(orte_data);
302 void rcv_cl_sensor_cmd_cb(const ORTERecvInfo *info, void *vinstance,
303 void *recvCallBackParam)
305 struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
307 switch (info->status) {
309 unsigned char data[1];
310 data[0] = orte_data->cl_sensor_cmd.bank_nbr;
311 can_send(CAN_CL_SENSOR_CMD, 1, data);
318 int main(int argc, char *argv[])
323 struct robottype_orte_data orte;
324 struct can_frame frame;
326 if (cand_init() < 0) {
327 printf("cand: init failed\n");
330 printf("cand: init OK\n");
335 /* orte initialization */
336 if(robottype_roboorte_init(&orte)) {
337 printf("Roboorte initialization failed! Exiting...\n");
341 printf("Roboorte OK\n");
343 /* creating publishers */
344 robottype_publisher_pwr_voltage_create(&orte, NULL, NULL);
345 robottype_publisher_motion_status_create(&orte, NULL, NULL);
346 robottype_publisher_odo_data_create(&orte, NULL, NULL);
347 robottype_publisher_motion_irc_create(&orte, NULL, NULL);
348 robottype_publisher_robot_cmd_create(&orte, NULL, NULL);
349 robottype_publisher_robot_switches_create(&orte, NULL, NULL);
350 robottype_publisher_robot_bumpers_create(&orte, NULL, NULL);
351 robottype_publisher_cl_sensor_status_create(&orte, NULL, NULL);
352 printf("Publishers OK\n");
354 /* creating subscribers */
355 robottype_subscriber_pwr_ctrl_create(&orte, rcv_pwr_ctrl_cb, &orte);
356 robottype_subscriber_motion_speed_create(&orte, rcv_motion_speed_cb, &orte);
357 robottype_subscriber_can_msg_create(&orte, rcv_can_msg_cb, &orte);
358 robottype_subscriber_cl_sensor_cmd_create(&orte, rcv_cl_sensor_cmd_cb, &orte);
359 printf("subscribers OK\n");
363 struct pollfd pfd[1] = {{sock, POLLIN, 0}};
365 ret = poll(pfd, 1, -1);
367 perror("cand: poll() error");
371 /* timeout expired, nothing to be done */
375 /* read data from SocketCAN */
376 size = read(sock, &frame, sizeof(struct can_frame));
380 cand_parse_frame(&orte, frame);