Advertisement
Guest User

TP3 SE

a guest
Mar 20th, 2019
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.90 KB | None | 0 0
  1. /*
  2. \file deadreck.c
  3. \author ${user}
  4. \date ${date}
  5. \brief Simple Hello World! for the Ev3
  6. */
  7. #include <stdio.h>
  8. #include <math.h>
  9. #include <stdlib.h>
  10. #include <unistd.h>
  11. #include <ev3.h>
  12. #include <ev3_tacho.h>
  13. #include <ev3_port.h>
  14. #include <ev3_sensor.h>
  15. #include <pthread.h>
  16. #include <time.h>
  17. #include "time_util.h"
  18. #include "mdd.h"
  19. #include "communication.h"
  20. #include "myev3.h"
  21. #include "workers.h"
  22.  
  23. // Shared data and mailboxes
  24. volatile MDD_int MDD_power;
  25. volatile MDD_int MDD_quit;
  26. volatile MDD_int MDD_status;
  27. volatile MDD_int MDD_auto_command;
  28.  
  29. volatile MB MB_direct_command;
  30.  
  31. volatile MDD_gen MDD_scan;
  32. volatile MDD_gen MDD_position;
  33. volatile MDD_gen MDD_reset;
  34. volatile MDD_gen MDD_target;
  35.  
  36. typedef struct s_position {
  37. double x;
  38. double y;
  39. double a;
  40. } * position;
  41.  
  42. void init_comms() {
  43. MDD_power = MDD_int_init(0);
  44. MDD_quit = MDD_int_init(0);
  45. MDD_status = MDD_int_init(0);
  46. MDD_auto_command = MDD_int_init(0);
  47.  
  48. MB_direct_command = MB_init();
  49.  
  50. int obs[5]= {0,0,0,0,0};
  51. MDD_scan = MDD_gen_init(obs, 5 * sizeof(int));
  52.  
  53. struct s_position pos= {0,0,0};
  54. MDD_position = MDD_gen_init(&pos, sizeof(struct s_position));
  55.  
  56. //MDD_reset = MDD_gen_init("", 1);
  57. //MDD_target = MDD_gen_init("", 1);
  58. }
  59.  
  60. /**
  61. * Thread scanning in the front and the sides of the robot with the ultrasonic sensor
  62. * Look for scanWorkerInit and scanWorker functions in workers.h
  63. * The obstacles array is supposed to be sent to the sendThread in order to be sent to the ground station
  64. * This thread should end when the application quits
  65. */
  66. void* scanThread(void* dummy) {
  67. struct timespec horloge;
  68. clock_gettime(CLOCK_REALTIME, &horloge);
  69. int obstacles[5];
  70. scanWorkerInit();
  71. while (!MDD_int_read(MDD_quit)) {
  72. scanWorker(obstacles);
  73.  
  74. // TODO: inform the MDD_scan
  75. MDD_gen_write(&MDD_scan, obstacles);
  76.  
  77. add_ms(&horloge, 1000);
  78. clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &horloge, 0);
  79. }
  80. return 0;
  81. }
  82.  
  83. /**
  84. * Thread sending information to the ground station
  85. * It should read the obstacles array, and, if modified, fprintf it on outStream
  86. * It should read the status, and, if modified, fprintf it on outStream
  87. * It should read the position and angle, and fprintf this information on outStream
  88. * Protocol format:
  89. * Obstacle array: o scan-90� scan-45� scan0� scan45� scan90�\n
  90. * Status: s status\n
  91. * Position: p x y a\n where x, y and a are integers!
  92. * Do not forget to fflush outStream at the end of each iteration, or data will be buffered but not sent
  93. * This thread should end when the application quits, and fclose the outStream socket
  94. */
  95. void *sendThread(FILE * outStream) {
  96. int obstacles[5];
  97. struct s_position pos;
  98. int status;
  99. struct timespec horloge;
  100. clock_gettime(CLOCK_REALTIME, &horloge);
  101.  
  102. while (!MDD_int_read(MDD_quit)) {
  103.  
  104. // TODO : complete this
  105. if (MDD_gen_read2(MDD_scan, obstacles)) {
  106. fprintf(outStream, "o %d %d %d %d %d\n", obstacles[0], obstacles[1],
  107. obstacles[2], obstacles[3], obstacles[4]);
  108. }
  109. if (MDD_int_read2(MDD_status, &status)) {
  110. fprintf(outStream, "s %d\n", status);
  111. }
  112. if (MDD_gen_read2(MDD_position, &pos)) {
  113. fprintf(outStream, "p %f %f %f\n", pos.x, pos.y, pos.a);
  114. }
  115.  
  116. fflush(outStream);
  117. add_ms(&horloge, 200);
  118. clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &horloge, 0);
  119. }
  120. fclose(outStream);
  121. return 0;
  122. }
  123.  
  124. /**
  125. * Thread commanding the robot in direct mode, it should wait everytime for a new command
  126. * As long as the application does not quit, this thread should apply the
  127. * received direct commands, using the current power, while updating the status
  128. * of the application (STATUS_STANDBY, STATUS_DIRECT_MOVE)
  129. *
  130. * ev3dev-c functions that will be useful are:
  131. * set_tacho_command_inx (for commands TACHO_STOP and TACHO_RUN_DIRECT),
  132. * set_tacho_duty_cycle_sp in order to configure the power between -100 and 100
  133. */
  134. void *directThread(void*dummy) {
  135.  
  136. // TODO : this is a bit long of a switch/case structure but it's fun
  137. switch (MB_receive(MB_direct_command)) {
  138. case 0:
  139. set_tacho_command_inx(MY_LEFT_TACHO, TACHO_STOP);
  140. set_tacho_command_inx(MY_RIGHT_TACHO, TACHO_STOP);
  141. MDD_int_write(MDD_status, STATUS_STANDBY);
  142. break;
  143. case 1:
  144. set_tacho_duty_cycle_sp(MY_LEFT_TACHO, MDD_int_read(MDD_power));
  145. set_tacho_duty_cycle_sp(MY_RIGHT_TACHO, MDD_int_read(MDD_power));
  146. MDD_int_write(MDD_status, STATUS_DIRECT_MOVE);
  147. break;
  148. case 2:
  149. set_tacho_duty_cycle_sp(MY_LEFT_TACHO, -MDD_int_read(MDD_power));
  150. set_tacho_duty_cycle_sp(MY_RIGHT_TACHO, -MDD_int_read(MDD_power));
  151. MDD_int_write(MDD_status, STATUS_DIRECT_MOVE);
  152. break;
  153. case 3:
  154. set_tacho_duty_cycle_sp(MY_LEFT_TACHO, -MDD_int_read(MDD_power));
  155. set_tacho_duty_cycle_sp(MY_RIGHT_TACHO, MDD_int_read(MDD_power));
  156. MDD_int_write(MDD_status, STATUS_DIRECT_MOVE);
  157. break;
  158. case 4:
  159. set_tacho_duty_cycle_sp(MY_LEFT_TACHO, MDD_int_read(MDD_power));
  160. set_tacho_duty_cycle_sp(MY_RIGHT_TACHO, -MDD_int_read(MDD_power));
  161. MDD_int_write(MDD_status, STATUS_DIRECT_MOVE);
  162. break;
  163. case 5:
  164. set_tacho_command_inx(MY_LEFT_TACHO, TACHO_RUN_DIRECT);
  165. set_tacho_command_inx(MY_RIGHT_TACHO, TACHO_RUN_DIRECT);
  166. MDD_int_write(MDD_status, STATUS_AUTO_MOVE);
  167. break;
  168.  
  169. }
  170.  
  171. return 0;
  172. }
  173.  
  174. /**
  175. * deadrecknoning thread, should first initialize (see deadRWorkerInit)
  176. * and then periodically, until quit:
  177. * if reset has been required, reset the coords
  178. * call its worker (see deadRWorker)
  179. * and then update the shared variable of the coords
  180. * Note: careful, the deadRWorker assumes angles in radian, while
  181. * ground station assumes angles in degrees (reset, and data sent)
  182. */
  183. void * deadreckoningThread(void *dummy) {
  184.  
  185. // TODO : all by yourself
  186. deadRWorkerInit();
  187. struct timespec horloge;
  188. position oldposition;
  189. position newposition;
  190. while (!MDD_int_read(MDD_quit)) {
  191. if (MDD_gen_read2(MDD_reset,oldposition)){
  192. MDD_gen_write(MDD_position,newposition);
  193. deadRWorker(oldposition->x,oldposition->y,oldposition->a, &(newposition->x),&(newposition->y), &(newposition->a));
  194. MDD_gen_write(MDD_position, newposition);
  195. }
  196. add_ms(&horloge, 30);
  197. clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &horloge, 0);
  198. }
  199. return 0;
  200. }
  201.  
  202. /**
  203. * auto move thread
  204. * when a target is defined, sets its mode to running (and updates the MDD status),
  205. * until STOP is received, or quit is received, or the target is reached with an acceptable error.
  206. */
  207. void * autoThread(void *dummy) {
  208. // TODO : keep this as the bonus question, at the end
  209. return 0;
  210. }
  211.  
  212. /**
  213. * The main function will be used as one of the application thread: readGroundstationThread
  214. * It will be in charge of initializing the ev3: ev3_init ev3_port_init ev3_tacho_init ev3_sensor_init
  215. * then initializing our specific ev3 ports: my_init_ev3
  216. * Then it will initialize every shared data and mailbox,
  217. * Then it will wait for ground station connection: WaitClient
  218. * Then it will create the threads
  219. * Then it will read the ground station orders using fscanf on the inStream
  220. * Protocol:
  221. * q\n -> quit
  222. * p pow\n -> current power to be set to pow
  223. * r x y alpha\n -> current position and heading should be reset to (x,y,alpha)
  224. * m 0|1\n -> set the mode to MODE_DIRECT (0) or MODE_AUTO (1)
  225. * S\n -> stop
  226. * F\n -> direct Forward
  227. * B\n -> direct Backward
  228. * L\n -> direct Left
  229. * R\n -> direct Right
  230. * g x y\n -> auto goto (x,y)
  231. * Note : when fscanf returns EOF, this means the ground station closed the connection, and
  232. * the application should stop.
  233. * Before exiting, we should send the quitting information to the other threads,
  234. * in order to cleanup (stop engines, close sockets, etc.)
  235. * Cleanup made in this thread, after making sure that every other thread is finished (pthread_join):
  236. * Every motor should be stopped, inStream should be closed,and mini tacho should be set in COAST mode
  237. * before stopping it : set_tacho_stop_action_inx(MY_MINI_TACHO, TACHO_COAST);
  238. */
  239. int main(void) {
  240. char cmd;
  241. char buf[256];
  242. int mode = MODE_DIRECT;
  243. FILE *inStream, *outStream;
  244. ev3_init();
  245. ev3_port_init();
  246. ev3_tacho_init();
  247. ev3_sensor_init();
  248. if (my_init_ev3()) {
  249. return 1;
  250. }
  251. init_comms();
  252. printf("Ready and waiting for incoming connection...\n");
  253. if (WaitClient(&outStream, &inStream)) {
  254. return 1;
  255. }
  256. // TODO: run the threads
  257. int quit = 0;
  258. while (!quit) {
  259. if (fgets(buf, 256, inStream)) {
  260. cmd = buf[0];
  261. switch (cmd) {
  262. // TODO: add every command treatment, think about using sscanf on buf to extract arguments
  263. default:
  264. printf("Unrecognized command: %s\n", buf);
  265. }
  266. } else {
  267. // Connection closed
  268. quit = 1;
  269. }
  270. }
  271. MDD_int_write(MDD_quit, 1);
  272. // TODO: wait for threads termination (pthread_join)
  273. fclose(inStream);
  274. set_tacho_command_inx(MY_RIGHT_TACHO, TACHO_STOP);
  275. set_tacho_command_inx(MY_LEFT_TACHO, TACHO_STOP);
  276. set_tacho_stop_action_inx(MY_MINI_TACHO, TACHO_COAST);
  277. set_tacho_command_inx(MY_MINI_TACHO, TACHO_STOP);
  278. ev3_uninit();
  279. CloseSockets();
  280. return 0;
  281. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement