5 * @brief Display-ORTE bridge
7 * Copyright: (c) 2010 CTU Dragons
8 * CTU FEE - Department of Control Engineering
15 #include <roboorte_robottype.h>
16 //#include <pthread.h>
25 #include <can_msg_def.h>
27 struct sercom_data* sercom;
30 static void sig_handler(int sig)
37 * Subtract the `struct timespec' values X and Y,
38 * storing the result in RESULT (result = x - y).
39 * Return 1 if the difference is negative, otherwise 0.
41 int timespec_subtract (struct timespec *result,
45 /* Perform the carry for the later subtraction by updating Y. */
46 if (x->tv_nsec < y->tv_nsec) {
47 int num_sec = (y->tv_nsec - x->tv_nsec) / 1000000000 + 1;
48 y->tv_nsec -= 1000000000 * num_sec;
51 if (x->tv_nsec - y->tv_nsec > 1000000000) {
52 int num_sec = (x->tv_nsec - y->tv_nsec) / 1000000000;
53 y->tv_nsec += 1000000000 * num_sec;
57 /* Compute the time remaining to wait.
58 `tv_nsec' is certainly positive. */
59 result->tv_sec = x->tv_sec - y->tv_sec;
60 result->tv_nsec = x->tv_nsec - y->tv_nsec;
62 /* Return 1 if result is negative. */
63 return x->tv_sec < y->tv_sec;
66 bool miliseconds_elapsed_since(struct timespec *t, unsigned miliseconds)
68 struct timespec now, diff;
69 unsigned long long elapsed;
71 if (t->tv_sec == 0 && t->tv_nsec == 0)
72 return true; /* Always elapsed after program start */
74 clock_gettime(CLOCK_MONOTONIC, &now);
75 timespec_subtract(&diff, &now, t);
76 elapsed = diff.tv_sec * 1000 + diff.tv_nsec/1000000;
77 return elapsed > miliseconds;
82 void rcv_pwr_voltage_cb (const ORTERecvInfo *info, void *vinstance,
83 void *recvCallBackParam)
85 UDE_hw_status_t status = STATUS_FAILED;
86 static UDE_hw_status_t last_status;
87 static struct timespec last_sent;
88 struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
89 switch (info->status) {
91 uoled_display_voltage(orte_data->pwr_voltage.voltage33,orte_data->pwr_voltage.voltage50,
92 orte_data->pwr_voltage.voltage80, orte_data->pwr_voltage.voltageBAT);
96 uoled_display_voltage(0,0,0,0);
97 status = STATUS_FAILED;
100 if (status != last_status ||
101 miliseconds_elapsed_since(&last_sent, 1000)) {
102 uoled_display_status(PWR, status);
103 clock_gettime(CLOCK_MONOTONIC, &last_sent);
105 last_status = status;
108 void rcv_odo_data_cb(const ORTERecvInfo *info, void *vinstance,
109 void *recvCallBackParam)
111 UDE_hw_status_t status = STATUS_FAILED;
112 static UDE_hw_status_t last_status;
113 static struct timespec last_sent;
114 //struct odo_data_type *instance = (struct odo_data_type *)vinstance;
115 switch (info->status) {
120 status = STATUS_FAILED;
123 /* Neni potreba aktualizovat stav na displeji 25x za sekundu */
124 if (status != last_status ||
125 miliseconds_elapsed_since(&last_sent, 1000)) {
126 uoled_display_status(ODO, status);
127 clock_gettime(CLOCK_MONOTONIC, &last_sent);
129 last_status = status;
132 void rcv_robot_cmd_cb(const ORTERecvInfo *info, void *vinstance,
133 void *recvCallBackParam)
135 UDE_hw_status_t status = STATUS_FAILED;
136 static UDE_hw_status_t last_status;
137 static struct timespec last_sent;
138 struct robot_cmd_type *instance = (struct robot_cmd_type *)vinstance;
140 switch (info->status) {
142 switch (instance->start_condition) {
144 case COMPETITION_STARTED:
145 status = STATUS_WARNING;
147 case START_PLUGGED_IN:
153 status = STATUS_FAILED;
156 if (status != last_status ||
157 miliseconds_elapsed_since(&last_sent, 1000)) {
158 uoled_display_status(STA, status);
159 clock_gettime(CLOCK_MONOTONIC, &last_sent);
161 last_status = status;
164 void rcv_robot_swicthes_cb(const ORTERecvInfo *info, void *vinstance,
165 void *recvCallBackParam)
167 UDE_hw_status_t status = STATUS_FAILED;
168 static char last_color;
169 static struct timespec last_sent;
170 struct robot_switches_type *instance = (struct robot_switches_type *)vinstance;
172 switch (info->status) {
174 // if (instance->team_color != last_color ||
175 // miliseconds_elapsed_since(&last_sent, 1000)) {
176 // uoled_display_color(instance->team_color);
177 // clock_gettime(CLOCK_MONOTONIC, &last_sent);
179 // last_color = instance->team_color;
181 status = STATUS_FAILED;
186 void rcv_motion_status_cb(const ORTERecvInfo *info, void *vinstance,
187 void *recvCallBackParam)
189 struct motion_status_type *m = (struct motion_status_type *)vinstance;
190 UDE_hw_status_t status = STATUS_FAILED;
191 static UDE_hw_status_t last_status;
192 static struct timespec last_sent;
193 switch (info->status) {
195 if (m->err_left == 0 && m->err_right == 0)
198 status = STATUS_WARNING;
201 status = STATUS_FAILED;
204 /* Neni potreba aktualizovat stav na displeji 25x za sekundu */
205 if (status != last_status ||
206 miliseconds_elapsed_since(&last_sent, 1000)) {
207 uoled_display_status(MOT, status);
208 clock_gettime(CLOCK_MONOTONIC, &last_sent);
210 last_status = status;
213 void rcv_crane_status_cb(const ORTERecvInfo *info, void *vinstance,
214 void *recvCallBackParam)
216 struct crane_status_type *m = (struct crane_status_type *)vinstance;
217 UDE_hw_status_t status = STATUS_FAILED;
218 static UDE_hw_status_t last_status;
219 static struct timespec last_sent;
220 switch (info->status) {
225 status = STATUS_FAILED;
228 /* Neni potreba aktualizovat stav na displeji 25x za sekundu */
229 if (status != last_status ||
230 miliseconds_elapsed_since(&last_sent, 1000)) {
231 uoled_display_status(MAN, status);
232 clock_gettime(CLOCK_MONOTONIC, &last_sent);
234 last_status = status;
237 void rcv_camera_result_cb(const ORTERecvInfo *info, void *vinstance,
238 void *recvCallBackParam)
240 UDE_hw_status_t status = STATUS_FAILED;
241 static UDE_hw_status_t last_status;
242 static struct timespec last_sent;
243 struct camera_result_type *instance = (struct camera_result_type *)vinstance;
245 switch (info->status) {
247 if (instance->error == 0)
250 status = STATUS_WARNING;
253 status = STATUS_FAILED;
256 if (status != last_status ||
257 miliseconds_elapsed_since(&last_sent, 1000)) {
258 uoled_display_status(CAM, status);
259 clock_gettime(CLOCK_MONOTONIC, &last_sent);
261 last_status = status;
264 void rcv_hokuyo_scan_cb(const ORTERecvInfo *info, void *vinstance,
265 void *recvCallBackParam)
267 UDE_hw_status_t status = STATUS_FAILED;
268 static UDE_hw_status_t last_status;
269 static struct timespec last_sent;
270 //struct hokuyo_scan_type *instance = (struct hokuyo_scan_type *)vinstance;
271 switch (info->status) {
276 status = STATUS_FAILED;
279 if (status != last_status ||
280 miliseconds_elapsed_since(&last_sent, 1000)) {
281 uoled_display_status(HOK, status);
282 clock_gettime(CLOCK_MONOTONIC, &last_sent);
284 last_status = status;
287 void rcv_est_pos_best_cb (const ORTERecvInfo *info, void *vinstance,
288 void *recvCallBackParam)
290 UDE_hw_status_t status = STATUS_FAILED;
291 static UDE_hw_status_t last_status;
292 static struct timespec last_sent;
293 struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
294 switch (info->status) {
299 status = STATUS_FAILED;
302 if (status != last_status ||
303 miliseconds_elapsed_since(&last_sent, 100)) {
304 uoled_display_status(APP, status);
305 if (status == STATUS_OK)
306 uoled_display_position(orte_data->est_pos_best.x, orte_data->est_pos_best.y, orte_data->est_pos_best.phi);
307 clock_gettime(CLOCK_MONOTONIC, &last_sent);
309 last_status = status;
312 void rcv_fsm_main_cb(const ORTERecvInfo *info, void *vinstance,
313 void *recvCallBackParam)
315 char status[MGS_LENGTH_DISPLAY_SM];
316 static char last_status[MGS_LENGTH_DISPLAY_SM];
317 static struct timespec last_sent;
318 struct fsm_state_type *fsm_state = (struct fsm_state_type *)vinstance;
319 switch (info->status) {
321 strncpy(status, fsm_state->state_name, MGS_LENGTH_DISPLAY_SM);
322 status[MGS_LENGTH_DISPLAY_SM-1]='\0';
323 //uoled_display_fsm(FSM_MAIN, fsm_state->state_name);
327 //uoled_display_fsm(FSM_MAIN, "?");
330 if (strcmp(status,last_status) != 0 ||
331 miliseconds_elapsed_since(&last_sent, 1000)) {
332 uoled_display_fsm(FSM_MAIN, status);
333 clock_gettime(CLOCK_MONOTONIC, &last_sent);
335 strncpy(last_status,status,MGS_LENGTH_DISPLAY_SM);
338 void rcv_fsm_act_cb(const ORTERecvInfo *info, void *vinstance,
339 void *recvCallBackParam)
341 char status[MGS_LENGTH_DISPLAY_SM];
342 static char last_status[MGS_LENGTH_DISPLAY_SM];
343 static struct timespec last_sent;
344 struct fsm_state_type *fsm_state = (struct fsm_state_type *)vinstance;
345 switch (info->status) {
347 strncpy(status, fsm_state->state_name, MGS_LENGTH_DISPLAY_SM);
348 status[MGS_LENGTH_DISPLAY_SM-1]='\0';
354 if (strcmp(status,last_status) != 0 ||
355 miliseconds_elapsed_since(&last_sent, 1000)) {
356 uoled_display_fsm(FSM_ACT, status);
357 clock_gettime(CLOCK_MONOTONIC, &last_sent);
359 strncpy(last_status,status,MGS_LENGTH_DISPLAY_SM);
362 void rcv_fsm_motion_cb(const ORTERecvInfo *info, void *vinstance,
363 void *recvCallBackParam)
365 char status[MGS_LENGTH_DISPLAY_SM];
366 static char last_status[MGS_LENGTH_DISPLAY_SM];
367 static struct timespec last_sent;
368 struct fsm_state_type *fsm_state = (struct fsm_state_type *)vinstance;
369 switch (info->status) {
371 strncpy(status, fsm_state->state_name, MGS_LENGTH_DISPLAY_SM);
372 status[MGS_LENGTH_DISPLAY_SM-1]='\0';
378 if (strcmp(status,last_status) != 0 ||
379 miliseconds_elapsed_since(&last_sent, 1000)) {
380 uoled_display_fsm(FSM_MOVE, status);
381 clock_gettime(CLOCK_MONOTONIC, &last_sent);
383 strncpy(last_status,status,MGS_LENGTH_DISPLAY_SM);
389 int main(int argc, char *argv[])
391 //fd_set read_fd_set;
392 //struct timeval timeout;
396 struct robottype_orte_data orte;
399 signal(SIGINT, sig_handler);
400 signal(SIGTERM, sig_handler);
402 //struct can_frame frame;
403 tty = getenv("DISPLAY_TTY");
406 printf("displayd: enviroment variable 'DISPLAY_TTY' was not set, using default value '%s'.\n", tty);
409 sercom = uoled_sercom_init(tty, NULL);
410 if (strcmp(tty, "/dev/null") == 0 || sercom != NULL) {
412 printf("displayd: init serial communication OK\n");
414 fprintf(stderr, "displayd: init serial communication failed\n");
416 /* Sleep in order to that not be respawn too fast by init */
424 /* orte initialization */
425 if(robottype_roboorte_init(&orte)) {
426 fprintf(stderr, "displayd: Roboorte initialization failed! Exiting...\n");
428 /* Sleep in order to that not be respawn too fast by init */
434 printf("displayd: Roboorte OK\n");
436 /* creating publishers */
437 //robottype_publisher_pwr_voltage_create(&orte, NULL, NULL);
438 //robottype_publisher_motion_status_create(&orte, NULL, NULL);
439 //robottype_publisher_odo_data_create(&orte, NULL, NULL);
440 //robottype_publisher_motion_irc_create(&orte, NULL, NULL);
441 //robottype_publisher_robot_cmd_create(&orte, NULL, NULL);
442 //robottype_publisher_corr_trig_create(&orte, NULL, NULL);
443 //robottype_publisher_corr_distances_create(&orte, NULL, NULL);
444 //robottype_publisher_actuator_status_create(&orte, NULL, NULL);
445 //printf("Publishers OK\n");
447 /* creating subscribers */
448 robottype_subscriber_odo_data_create(&orte, rcv_odo_data_cb, &orte);
449 robottype_subscriber_motion_status_create(&orte, rcv_motion_status_cb, NULL);
450 robottype_subscriber_crane_status_create(&orte, rcv_crane_status_cb, NULL);
451 robottype_subscriber_pwr_voltage_create(&orte, rcv_pwr_voltage_cb, &orte);
452 robottype_subscriber_est_pos_best_create(&orte, rcv_est_pos_best_cb, &orte);
453 //robottype_subscriber_pwr_alert_create(&orte, rcv_pwr_alert_cb, &orte);
454 //robottype_subscriber_motion_speed_create(&orte, rcv_motion_speed_cb, &orte);
455 //robottype_subscriber_can_msg_create(&orte, rcv_can_msg_cb, &orte);
456 robottype_subscriber_hokuyo_scan_create(&orte, rcv_hokuyo_scan_cb, &orte);
457 robottype_subscriber_camera_result_create(&orte, rcv_camera_result_cb, &orte);
458 robottype_subscriber_fsm_main_create(&orte, rcv_fsm_main_cb, &orte);
459 robottype_subscriber_fsm_act_create(&orte, rcv_fsm_act_cb, &orte);
460 robottype_subscriber_fsm_motion_create(&orte, rcv_fsm_motion_cb, &orte);
461 robottype_subscriber_robot_cmd_create(&orte, rcv_robot_cmd_cb, &orte);
462 robottype_subscriber_robot_switches_create(&orte, rcv_robot_swicthes_cb, &orte);
464 printf("displayd: subscribers created OK\n");
467 UDE_recieve_cmd_t rcmd;
468 struct pollfd pfd[1] = {{
476 if (strcmp(tty, "/dev/null") != 0) {
477 ret = poll(pfd, 1, 500/*ms*/);
479 ret = uoled_recieve_cmd(&rcmd);
480 /* orte.display_cmd.command=rcmd; */
482 /* ORTEPublicationSend(orte.publication_display_cmd); */
483 /* printf("displayd: publishing command recieved from display [ 0x%2x ]\n", rcmd); */
488 perror("Error: read from display");
492 usleep(500/*ms*/*1000);
496 uoled_display_alive();
500 printf("displayd: closing serial communication...\n");
501 uoled_sercom_close();
502 // printf("displayd: destroying display_cmd publisher...\n");
503 // robottype_publisher_display_cmd_destroy(&orte);
504 printf("displayd: destroying orte instance...\n");
505 robottype_roboorte_destroy(&orte);
508 printf("Waiting 3 seconds\n");
512 printf("displayd: finished!\n");