2 * robot_orte.c 08/04/21
6 * Copyright: (c) 2008 CTU Dragons
7 * CTU FEE - Department of Control Engineering
12 #include <roboorte_robottype.h>
16 #include <movehelper.h>
19 #include <laser-nav.h>
20 #include "map_handling.h"
23 #include <can_msg_def.h>
26 #define DBG(format, ...) printf(format, ##__VA_ARGS__)
28 #define DBG(format, ...)
32 extern sem_t measurement_received;
34 /* ----------------------------------------------------------------------
35 * PUBLISHER CALLBACKS - GENERIC
36 * ---------------------------------------------------------------------- */
38 void send_ref_pos_cb(const ORTESendInfo *info, void *vinstance,
39 void *sendCallBackParam)
41 struct robot_pos_type *instance = (struct robot_pos_type *)vinstance;
44 *instance = robot.ref_pos;
45 ROBOT_UNLOCK(ref_pos);
48 void send_est_pos_uzv_cb(const ORTESendInfo *info, void *vinstance,
49 void *sendCallBackParam)
51 struct robot_pos_type *instance = (struct robot_pos_type *)vinstance;
53 ROBOT_LOCK(est_pos_uzv);
54 *instance = robot.est_pos_uzv;
55 ROBOT_UNLOCK(est_pos_uzv);
58 void send_est_pos_odo_cb(const ORTESendInfo *info, void *vinstance,
59 void *sendCallBackParam)
61 struct robot_pos_type *instance = (struct robot_pos_type *)vinstance;
63 ROBOT_LOCK(est_pos_odo);
64 *instance = robot.est_pos_odo;
65 ROBOT_UNLOCK(est_pos_odo);
68 void send_dummy_cb(const ORTESendInfo *info, void *vinstance,
69 void *sendCallBackParam)
73 /* ----------------------------------------------------------------------
74 * SUBSCRIBER CALLBACKS - GENERIC
75 * ---------------------------------------------------------------------- */
77 void rcv_motion_irc_cb(const ORTERecvInfo *info, void *vinstance,
78 void *recvCallBackParam)
80 struct motion_irc_type *instance = (struct motion_irc_type *)vinstance;
81 double dleft, dright, dtang, dphi;
82 static bool first_run = true;
83 /* spocitat prevodovy pomer */
84 const double n = (double)(28.0 / 1.0);
86 /* vzdalenost na pulz IRC */
87 const double c = (M_PI*2*ROBOT_WHEEL_RADIUS_M) / (n * 4*500.0);
89 switch (info->status) {
92 ROBOT_LOCK(motion_irc);
93 robot.motion_irc = *instance;
94 ROBOT_UNLOCK(motion_irc);
99 dleft = ((robot.motion_irc.left - instance->left) >> 8) * c;
100 dright = ((instance->right - robot.motion_irc.right) >> 8) * c;
102 dtang = (dleft + dright) / 2.0;
103 dphi = (dright - dleft) / (2.0*ROBOT_ROTATION_RADIUS_M);
105 ROBOT_LOCK(motion_irc);
106 double a = robot.est_pos_odo.phi;
107 robot.est_pos_odo.x += dtang*cos(a);
108 robot.est_pos_odo.y += dtang*sin(a);
109 robot.est_pos_odo.phi += dphi;
110 ROBOT_UNLOCK(motion_irc);
112 /* locking should not be needed, but... */
113 ROBOT_LOCK(motion_irc);
114 robot.motion_irc = *instance;
115 robot.motion_irc_received = 1;
116 ROBOT_UNLOCK(motion_irc);
118 robot.hw_status[STATUS_MOTION] = HW_STATUS_OK;
121 robot.hw_status[STATUS_MOTION] = HW_STATUS_FAILED;
122 DBG("ORTE deadline occurred - motion_irc receive\n");
127 void rcv_corr_distances_cb(const ORTERecvInfo *info, void *vinstance,
128 void *recvCallBackParam)
130 struct corr_distances_type *instance =
131 (struct corr_distances_type *)vinstance;
133 switch (info->status) {
135 /* locking should not be needed, but... */
136 ROBOT_LOCK(corr_distances);
137 robot.corr_distances = *instance;
138 ROBOT_UNLOCK(corr_distances);
140 /* wake up motion-control/thread_trajectory_follower */
141 sem_post(&measurement_received);
143 /*FIXME: is following OK? (pecam1) */
144 robot.hw_status[STATUS_UZV] = HW_STATUS_OK;
147 robot.hw_status[STATUS_UZV] = HW_STATUS_FAILED;
153 void rcv_motion_speed_cb(const ORTERecvInfo *info, void *vinstance,
154 void *recvCallBackParam)
156 switch (info->status) {
160 DBG("ORTE deadline occurred - motion_speed receive\n");
165 void rcv_motion_status_cb(const ORTERecvInfo *info, void *vinstance,
166 void *recvCallBackParam)
168 switch (info->status) {
172 DBG("ORTE deadline occurred - motion_status receive\n");
177 void rcv_pwr_voltage_cb(const ORTERecvInfo *info, void *vinstance,
178 void *recvCallBackParam)
180 switch (info->status) {
182 robot.hw_status[STATUS_PWR]=HW_STATUS_OK;
185 robot.hw_status[STATUS_PWR]=HW_STATUS_FAILED;
186 DBG("ORTE deadline occurred - pwr_voltage receive\n");
191 void rcv_pwr_ctrl_cb(const ORTERecvInfo *info, void *vinstance,
192 void *recvCallBackParam)
194 switch (info->status) {
198 DBG("ORTE deadline occurred - pwr_ctrl receive\n");
203 void rcv_robot_cmd_cb(const ORTERecvInfo *info, void *vinstance,
204 void *recvCallBackParam)
206 struct robot_cmd_type *instance = (struct robot_cmd_type *)vinstance;
207 static struct robot_cmd_type last_instance;
209 switch (info->status) {
211 /* Stupid way of controlling the robot by
212 * pluggin in and out start connector. */
213 switch (robot.state) {
215 if (instance->start) {
216 robot.hw_status[STATUS_STA] = HW_STATUS_WARNING;
218 robot.hw_status[STATUS_STA] = HW_STATUS_OK;
220 if (!instance->start) {
221 robot.state = START_PLUGGED_IN;
222 printf("START_PLUGGED_IN\n");
226 case START_PLUGGED_IN:
227 robot.hw_status[STATUS_STA] = HW_STATUS_OK;
228 /* Competition starts when plugged out */
229 if (instance->start) {
230 FSM_SIGNAL(MAIN, EV_START, NULL);
231 robot.state = COMPETITION_STARTED;
236 case COMPETITION_STARTED: {
237 /* Subsequent plug-in stops the robot */
239 if (!instance->start) {
240 robot.hw_status[STATUS_STA] = HW_STATUS_WARNING;
247 last_instance = *instance;
250 robot.hw_status[STATUS_STA] = HW_STATUS_FAILED;
251 DBG("ORTE deadline occurred - robot_cmd receive\n");
256 void rcv_hokuyo_scan_cb(const ORTERecvInfo *info, void *vinstance,
257 void *recvCallBackParam)
259 struct hokuyo_scan_type *instance = (struct hokuyo_scan_type *)vinstance;
261 switch (info->status) {
264 robot.hokuyo = *instance;
265 robot.hw_status[STATUS_HOK] = HW_STATUS_OK;
266 ROBOT_UNLOCK(hokuyo);
267 update_map_hokuyo(instance);
271 robot.hw_status[STATUS_HOK] = HW_STATUS_FAILED;
272 system("killall -9 hokuyo");
273 DBG("%s: ORTE deadline occurred\n", __FUNCTION__);
278 void rcv_camera_result_cb(const ORTERecvInfo *info, void *vinstance,
279 void *recvCallBackParam)
281 struct camera_result_type *instance = (struct camera_result_type *)vinstance;
283 switch (info->status) {
285 ROBOT_LOCK(camera_result);
286 robot.game_conf = instance->lot;
287 ROBOT_UNLOCK(camera_result);
288 robot.hw_status[STATUS_CAM] = HW_STATUS_OK;
292 robot.hw_status[STATUS_CAM] = HW_STATUS_FAILED;
293 system("killall -9 rozpuk");
295 DBG("%s: ORTE deadline occurred\n", __FUNCTION__);
299 /* ----------------------------------------------------------------------
300 * SUBSCRIBER CALLBACKS - EB2008
301 * ---------------------------------------------------------------------- */
303 void rcv_actuator_status_cb(const ORTERecvInfo *info, void *vinstance,
304 void *recvCallBackParam)
306 static unsigned short old_lift_pos=0;
307 static unsigned short old_pusher_pos=0;
308 switch (info->status) {
310 // new data arrived and requested position equals actual position
311 ROBOT_LOCK(lift_cmd);
312 if (robot.orte.actuator_status.lift_pos == robot.orte.lift.pos &&
313 robot.lift_cmd > 0) {
314 FSM_SIGNAL(ACT, EV_LIFT_IN_POS, NULL);
317 ROBOT_UNLOCK(lift_cmd);
318 if (robot.orte.actuator_status.pusher_pos == robot.orte.pusher.pos &&
319 robot.orte.actuator_status.pusher_pos != old_pusher_pos)
320 FSM_SIGNAL(ACT, EV_PUSHER_IN_POS, NULL);
321 if (robot.orte.actuator_status.status & ~LIFT_ENDSW_MASK) {
322 robot.hw_status[STATUS_LFT]=HW_STATUS_WARNING;
324 robot.hw_status[STATUS_LFT]=HW_STATUS_OK;
326 old_lift_pos = robot.orte.actuator_status.lift_pos;
327 old_pusher_pos = robot.orte.actuator_status.pusher_pos;
330 robot.hw_status[STATUS_LFT]=HW_STATUS_FAILED;
331 DBG("ORTE deadline occurred - actuator_status receive\n");
336 void rcv_puck_distance_cb(const ORTERecvInfo *info, void *vinstance,
337 void *recvCallBackParam)
339 switch (info->status) {
341 double old_distance_value = robot.puck_distance;
344 robot.puck_distance = robot.orte.puck_distance.distance;
345 ROBOT_UNLOCK(sharps);
347 if (PUCK_INSIDE(robot.orte.puck_distance.distance) && !PUCK_INSIDE(old_distance_value)) {
348 // signal puck is inside
349 FSM_SIGNAL(ACT, EV_PUCK_INSIDE, NULL);
351 if (PUCK_REACHABLE(robot.orte.puck_distance.distance) && !PUCK_REACHABLE(old_distance_value)) {
352 // signal puck is reachable
353 FSM_SIGNAL(MAIN, EV_PUCK_REACHABLE, NULL);
358 // FIXME F.J. (?) inform display in case of invalid data?
359 // FIXME F.J. (?) limited space on the display...
360 //robot.hw_status[STATUS_ACTUATORS]=HW_STATUS_FAILED;
361 DBG("ORTE deadline occurred - servos receive\n");
366 void rcv_puck_inside_cb(const ORTERecvInfo *info, void *vinstance,
367 void *recvCallBackParam)
369 switch (info->status) {
371 if (robot.use_back_switch) {
372 static bool previous_switch_status = 0;
373 if (robot.orte.puck_inside.status & 0x02) {
374 //FSM_SIGNAL(ACT, EV_PUCK_INSIDE, NULL);
376 /* React on the first switch or when moving backward. */
377 if ((previous_switch_status & 0x02) == 0 ||
378 robot.moves_backward) {
379 FSM_SIGNAL(MOTION, EV_OBSTACLE_BEHIND, NULL);
381 previous_switch_status = robot.orte.puck_inside.status;
385 static bool previous = false;
386 bool switched = ((robot.orte.puck_inside.status & 0x01) != 0);
388 if (switched && !previous) {
389 FSM_SIGNAL(ACT, EV_PUCK_INSIDE, NULL);
394 robot.hw_status[STATUS_CHE]=HW_STATUS_OK;
398 robot.hw_status[STATUS_CHE]=HW_STATUS_FAILED;
399 DBG("ORTE deadline occurred - servos receive\n");
406 static int cmp_double(const void *v1, const void *v2)
408 const double *d1 = v1, *const d2 = v2;
418 int robot_init_orte()
422 robot.orte.strength = 20;
424 rv = robottype_roboorte_init(&robot.orte);
428 /* creating publishers */
429 robottype_publisher_motion_speed_create(&robot.orte, NULL, &robot.orte);
430 robottype_publisher_ref_pos_create(&robot.orte, send_ref_pos_cb, &robot.orte);
431 robottype_publisher_est_pos_uzv_create(&robot.orte, send_est_pos_uzv_cb, &robot.orte);
432 robottype_publisher_est_pos_odo_create(&robot.orte, send_est_pos_odo_cb, &robot.orte);
433 //???robottype_publisher_pwr_ctrl_create(&robot.orte, NULL, &robot.orte);
435 // I didn't know what was the difference between the callback function pointer
436 // being NULL and being set to pointer to empty send_dummy_cb function. The DIFFERENCE
438 // - NULL: message is published only when OrtePublicationSend called
439 // - pointer to empty function: message is published periodically
440 robottype_publisher_lift_create(&robot.orte, send_dummy_cb, &robot.orte);
441 robottype_publisher_pusher_create(&robot.orte, send_dummy_cb, &robot.orte);
442 robottype_publisher_chelae_create(&robot.orte, send_dummy_cb, &robot.orte);
443 robottype_publisher_belts_create(&robot.orte, send_dummy_cb, &robot.orte);
444 robottype_publisher_holder_create(&robot.orte, send_dummy_cb, &robot.orte);
445 robottype_publisher_fsm_main_create(&robot.orte, send_dummy_cb, &robot.orte);
446 robottype_publisher_fsm_act_create(&robot.orte, send_dummy_cb, &robot.orte);
447 robottype_publisher_fsm_motion_create(&robot.orte, send_dummy_cb, &robot.orte);
448 robottype_publisher_camera_control_create(&robot.orte, send_dummy_cb, &robot.orte);
450 /* create generic subscribers */
451 robottype_subscriber_motion_irc_create(&robot.orte, rcv_motion_irc_cb, &robot.orte);
452 robottype_subscriber_motion_speed_create(&robot.orte, rcv_motion_speed_cb, &robot.orte);
453 robottype_subscriber_motion_status_create(&robot.orte, rcv_motion_status_cb, &robot.orte);
454 robottype_subscriber_corr_distances_create(&robot.orte, rcv_corr_distances_cb, &robot.orte);
455 robottype_subscriber_pwr_voltage_create(&robot.orte, rcv_pwr_voltage_cb, &robot.orte);
456 //robottype_subscriber_pwr_ctrl_create(&robot.orte, rcv_pwr_ctrl_cb, &robot.orte);
457 robottype_subscriber_robot_cmd_create(&robot.orte, rcv_robot_cmd_cb, &robot.orte);
458 robottype_subscriber_hokuyo_scan_create(&robot.orte, rcv_hokuyo_scan_cb, &robot.orte);
460 /* create subscribers */
461 robottype_subscriber_actuator_status_create(&robot.orte, rcv_actuator_status_cb, &robot.orte);
462 //robottype_subscriber_puck_distance_create(&robot.orte, rcv_puck_distance_cb, &robot.orte);
463 robottype_subscriber_puck_inside_create(&robot.orte, rcv_puck_inside_cb, &robot.orte);
464 robottype_subscriber_camera_result_create(&robot.orte, rcv_camera_result_cb, &robot.orte);