sync_generator.py 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  1. # -*- coding: utf-8 -*-
  2. import yaml
  3. import sys
  4. argvs = sys.argv
  5. argc = len(argvs)
  6. text = ""
  7. if __name__ == "__main__":
  8. if (argc != 3):
  9. print '%python sync_generator.py argv[1] argv[2]'
  10. print '\t' + 'argv[1]: input *.yaml file'
  11. print '\t' + 'argv[2]: output *.cpp file'
  12. quit()
  13. f_config = open(argvs[1], 'r')
  14. f_generate = open(argvs[2], 'w')
  15. data = yaml.load(f_config)
  16. text = '/* ----header---- */\n'
  17. text += '/* common header */\n'
  18. text += '#include "ros/ros.h"\n'
  19. text += '#include <ros/callback_queue.h>\n'
  20. text += '#include <boost/circular_buffer.hpp>\n'
  21. text += '#include <vector>\n'
  22. text += '#include <stdio.h>\n'
  23. text += '#include <stdlib.h>\n'
  24. text += '#include <string.h>\n'
  25. text += '#include <signal.h>\n'
  26. text += '#include <sys/stat.h>\n'
  27. text += '#include <sys/select.h>\n'
  28. text += '#include <mqueue.h>\n'
  29. text += '#include <fcntl.h>\n'
  30. text += '#include <errno.h>\n'
  31. text += '#include <unistd.h>\n'
  32. text += '#include <pthread.h>\n'
  33. text += '#include "t_sync_message.h"\n'
  34. text += '/* user header */\n'
  35. text += '#include "%s.h"\n' % data['sub1_header']
  36. text += '#include "%s.h"\n' % data['sub2_header']
  37. text += '#include "%s.h"\n' % data['sync_sub1_header']
  38. text += '#include "%s.h"\n' % data['sync_sub2_header']
  39. text += '\n/* ----mode---- */\n'
  40. text += '#define _REQ_PUB %s\n\n' % data['req_pub_mode']
  41. text += '/* ----var---- */\n'
  42. text += '/* common var */\n'
  43. text += 'bool buf_flag;\n'
  44. text += 'pthread_mutex_t mutex;\n'
  45. text += '/* user var */\n'
  46. text += 'boost::circular_buffer<%s> %s_ringbuf(%s);\n' % (data['sub1_header'].replace('/', '::'), data['sub1'].split('/')[-1], data['sub1_ringbuf'])
  47. text += 'boost::circular_buffer<%s> %s_ringbuf(%s);\n' % (data['sub2_header'].replace('/', '::'), data['sub2'].split('/')[-1], data['sub2_ringbuf'])
  48. text += 'ros::Publisher %s_pub;\n' % data['pub1'].split('/')[-1]
  49. text += 'ros::Publisher %s_pub;\n' % data['pub2'].split('/')[-1]
  50. text += 'bool %s_flag;\n' % data['sync_sub1'].split('/')[-1]
  51. text += 'bool %s_flag;\n\n' % data['sync_sub2'].split('/')[-1]
  52. text += '/* ----function---- */\n'
  53. text += 'double fabs_time_diff(std_msgs::Header *timespec1, std_msgs::Header *timespec2) {\n'
  54. text += ' double time1 = (double)timespec1->stamp.sec + (double)timespec1->stamp.nsec/1000000000L;\n'
  55. text += ' double time2 = (double)timespec2->stamp.sec + (double)timespec2->stamp.nsec/1000000000L;\n\n'
  56. text += ' return fabs(time1 - time2);\n'
  57. text += '}\n\n'
  58. text += 'double get_time(const std_msgs::Header *timespec) {\n'
  59. text += ' return (double)timespec->stamp.sec + (double)timespec->stamp.nsec/1000000000L;\n'
  60. text += '}\n\n\n'
  61. text += '#if _REQ_PUB\n'
  62. text += '%s* p_%s_buf;\n' % (data['sub1_header'].replace('/', '::'), data['sub1'].split('/')[-1])
  63. text += '%s* p_%s_buf;\n\n' % (data['sub2_header'].replace('/', '::'), data['sub2'].split('/')[-1])
  64. text += 'void %s_callback(const %s::ConstPtr& %s_msg) {\n' % (data['sub1'].split('/')[-1], data['sub1_header'].replace('/', '::'), data['sub1'].split('/')[-1])
  65. text += ' pthread_mutex_lock(&mutex);\n'
  66. text += ' %s_ringbuf.push_front(*%s_msg);\n' % (data['sub1'].split('/')[-1], data['sub1'].split('/')[-1])
  67. text += ' //%s is empty\n' % data['sub2'].split('/')[-1]
  68. text += ' if (%s_ringbuf.begin() == %s_ringbuf.end()) {\n' % (data['sub2'].split('/')[-1], data['sub2'].split('/')[-1])
  69. text += ' pthread_mutex_unlock(&mutex);\n'
  70. text += ' ROS_INFO("%s ring buffer is empty");\n' % data['sub2'].split('/')[-1]
  71. text += ' return\n'
  72. text += ' }\n'
  73. text += ' buf_flag = true;\n'
  74. text += ' pthread_mutex_unlock(&mutex);\n'
  75. text += '}\n\n'
  76. text += 'void %s_callback(const %s::ConstPtr& %s_msg) {\n' % (data['sub2'].split('/')[-1], data['sub2_header'].replace('/', '::'), data['sub2'].split('/')[-1])
  77. text += ' pthread_mutex_lock(&mutex);\n'
  78. text += ' %s_ringbuf.push_front(*%s_msg);\n' % (data['sub2'].split('/')[-1], data['sub2'].split('/')[-1])
  79. text += ' //%s is empty\n' % data['sub1'].split('/')[-1]
  80. text += ' if (%s_ringbuf.begin() == %s_ringbuf.end()) {\n' % (data['sub1'].split('/')[-1], data['sub1'].split('/')[-1])
  81. text += ' ROS_INFO("%s ring buffer is empty");\n' % data['sub1'].split('/')[-1]
  82. text += ' pthread_mutex_unlock(&mutex);\n'
  83. text += ' return;\n'
  84. text += ' }\n\n'
  85. text += ' buf_flag = true;\n'
  86. text += ' pthread_mutex_unlock(&mutex);\n'
  87. text += '}\n'
  88. text += '\n'
  89. text += 'void publish_msg(%s* p_%s_buf, %s* p_%s_buf)\n' % (data['sub1_header'].replace('/', '::'), data['sub1'].split('/')[-1], data['sub2_header'].replace('/', '::'), data['sub2'].split('/')[-1])
  90. text += '{\n'
  91. text += ' ROS_INFO("publish");\n'
  92. text += ' %s_pub.publish(*p_%s_buf);\n' % (data['pub1'].split('/')[-1], data['sub1'].split('/')[-1])
  93. text += ' %s_pub.publish(*p_%s_buf);\n' % (data['pub2'].split('/')[-1], data['sub2'].split('/')[-1])
  94. text += '}\n\n'
  95. text += 'bool publish() {\n'
  96. text += ' if (buf_flag) {\n'
  97. text += ' pthread_mutex_lock(&mutex)\n\n'
  98. text += ' //%s is empty\n' % data['sub1'].split('/')[-1]
  99. text += ' if (%s_ringbuf.begin() == %s_ringbuf.end()) {\n' % (data['sub1'].split('/')[-1], data['sub1'].split('/')[-1])
  100. text += ' pthread_mutex_unlock(&mutex);\n'
  101. text += ' ROS_INFO("%s ring buffer is empty");\n'% data['sub1'].split('/')[-1]
  102. text += ' return false;\n'
  103. text += ' }\n\n'
  104. text += ' //%s is empty\n' % data['sub2'].split('/')[-1]
  105. text += ' if (%s_ringbuf.begin() == %s_ringbuf.end()) {\n' % (data['sub2'].split('/')[-1], data['sub2'].split('/')[-1])
  106. text += ' pthread_mutex_unlock(&mutex);\n'
  107. text += ' ROS_INFO("%s ring buffer is empty");\n'% data['sub2'].split('/')[-1]
  108. text += ' return false;\n'
  109. text += ' }\n\n'
  110. if data['sched_policy'] == 1:
  111. text += ' // %s > %s\n' % (data['sub1'].split('/')[-1], data['sub2'].split('/')[-1])
  112. text += ' if (get_time(&(%s_ringbuf.front().header)) >= get_time(&(%s_ringbuf.front().header))) {\n' % (data['sub1'].split('/')[-1], data['sub2'].split('/')[-1])
  113. text += ' p_%s_buf = &(%s_ringbuf.front());\n' % (data['sub2'].split('/')[-1], data['sub2'].split('/')[-1])
  114. text += ' boost::circular_buffer<%s>::iterator it = %s_ringbuf.begin();\n' % (data['sub1_header'].replace('/', '::'), data['sub1'].split('/')[-1])
  115. text += ' if (%s_ringbuf.size() == 1) {\n' % data['sub1'].split('/')[-1]
  116. text += ' p_%s_buf = &*it;\n' % data['sub1'].split('/')[-1]
  117. text += ' publish_msg(p_%s_buf, p_%s_buf);\n' % (data['sub1'].split('/')[-1], data['sub2'].split('/')[-1])
  118. text += ' pthread_mutex_unlock(&mutex);\n'
  119. text += ' return true;\n'
  120. text += ' } else {\n'
  121. text += ' for (it++; it != %s_ringbuf.end(); it++) {\n' % data['sub1'].split('/')[-1]
  122. text += ' if (fabs_time_diff(&(%s_ringbuf.front().header), &((it-1)->header))\n' % data['sub2'].split('/')[-1]
  123. text += ' < fabs_time_diff(&(%s_ringbuf.front().header), &(it->header))) {\n' % data['sub2'].split('/')[-1]
  124. text += ' p_%s_buf = &*(it-1);\n' % data['sub1'].split('/')[-1]
  125. text += ' break;\n'
  126. text += ' }\n'
  127. text += ' }\n'
  128. text += ' if (it == %s_ringbuf.end()) {\n' % data['sub1'].split('/')[-1]
  129. text += ' p_%s_buf = &(%s_ringbuf.back());\n' % (data['sub1'].split('/')[-1], data['sub1'].split('/')[-1])
  130. text += ' }\n'
  131. text += ' }\n'
  132. text += ' }\n'
  133. text += ' // %s < %s\n' % (data['sub1'].split('/')[-1], data['sub2'].split('/')[-1])
  134. text += ' else {\n'
  135. text += ' p_%s_buf = &(%s_ringbuf.front());\n' % (data['sub1'].split('/')[-1], data['sub1'].split('/')[-1])
  136. text += ' boost::circular_buffer<%s>::iterator it = %s_ringbuf.begin();\n' % (data['sub2_header'].replace('/', '::'), data['sub2'].split('/')[-1])
  137. text += ' if (%s_ringbuf.size() == 1) {\n' % data['sub2'].split('/')[-1]
  138. text += ' p_%s_buf = &*it;\n' % data['sub2'].split('/')[-1]
  139. text += ' publish_msg(p_%s_buf, p_%s_buf);\n' % (data['sub1'].split('/')[-1], data['sub2'].split('/')[-1])
  140. text += ' pthread_mutex_unlock(&mutex);\n'
  141. text += ' return true;\n'
  142. text += ' }\n\n'
  143. text += ' for (it++; it != %s_ringbuf.end(); it++) {\n' % data['sub2'].split('/')[-1]
  144. text += ' if (fabs_time_diff(&(%s_ringbuf.front().header), &((it-1)->header))\n' % data['sub1'].split('/')[-1]
  145. text += ' < fabs_time_diff(&(%s_ringbuf.front().header), &(it->header))) {\n' % data['sub1'].split('/')[-1]
  146. text += ' p_%s_buf = &*(it-1);\n' % data['sub2'].split('/')[-1]
  147. text += ' break;\n'
  148. text += ' }\n'
  149. text += ' }\n\n'
  150. text += ' if (it == %s_ringbuf.end()) {\n' % data['sub2'].split('/')[-1]
  151. text += ' p_%s_buf = &(%s_ringbuf.back());\n' % (data['sub2'].split('/')[-1], data['sub2'].split('/')[-1])
  152. text += ' }\n'
  153. text += ' }\n'
  154. elif data['sched_policy'] == 2:
  155. text += ' p_%s_buf = &(%s_ringbuf.front());\n' % (data['short_rate'].split('/')[-1], data['short_rate'].split('/')[-1])
  156. if data['short_rate'] == data['sub1'] :
  157. text += ' boost::circular_buffer<%s>::iterator it = %s_ringbuf.begin();\n' % (data['sub2_header'].replace('/', '::'), data['sub2'].split('/')[-1])
  158. text += ' if (%s_ringbuf.size() == 1) {\n' % data['sub2'].split('/')[-1]
  159. text += ' p_%s_buf = &*it;\n' % data['sub2'].split('/')[-1]
  160. text += ' publish_msg(p_%s_buf, p_%s_buf);\n' % (data['short_rate'].split('/')[-1], data['sub2'].split('/')[-1])
  161. text += ' pthread_mutex_unlock(&mutex);\n'
  162. text += ' return true;\n'
  163. text += ' }\n\n'
  164. text += ' for (it++; it != %s_ringbuf.end(); it++) {\n' % data['sub2'].split('/')[-1]
  165. text += ' if (fabs_time_diff(&(%s_ringbuf.front().header), &((it-1)->header))\n' % data['short_rate'].split('/')[-1]
  166. text += ' < fabs_time_diff(&(%s_ringbuf.front().header), &(it->header))) {\n' % data['short_rate'].split('/')[-1]
  167. text += ' p_%s_buf = &*(it-1);\n' % data['sub2'].split('/')[-1]
  168. text += ' break;\n'
  169. text += ' }\n'
  170. text += ' }\n\n'
  171. text += ' if (it == %s_ringbuf.end()) {\n' % data['sub2'].split('/')[-1]
  172. text += ' p_%s_buf = &(%s_ringbuf.back());\n' % (data['sub2'].split('/')[-1], data['sub2'].split('/')[-1])
  173. text += ' }\n'
  174. elif data['short_rate'] == data['sub2']:
  175. text += ' boost::circular_buffer<%s>::iterator it = %s_ringbuf.begin();\n' % (data['sub1_header'].replace('/', '::'), data['sub1'].split('/')[-1])
  176. text += ' if (%s_ringbuf.size() == 1) {\n' % data['sub1'].split('/')[-1]
  177. text += ' p_%s_buf = &*it;\n' % data['sub1'].split('/')[-1]
  178. text += ' publish_msg(p_%s_buf, p_%s_buf);\n' % (data['short_rate'].split('/')[-1], data['sub1'].split('/')[-1])
  179. text += ' pthread_mutex_unlock(&mutex);\n'
  180. text += ' return true;\n'
  181. text += ' }\n\n'
  182. text += ' for (it++; it != %s_ringbuf.end(); it++) {\n' % data['sub1'].split('/')[-1]
  183. text += ' if (fabs_time_diff(&(%s_ringbuf.front().header), &((it-1)->header))\n' % data['short_rate'].split('/')[-1]
  184. text += ' < fabs_time_diff(&(%s_ringbuf.front().header), &(it->header))) {\n' % data['short_rate'].split('/')[-1]
  185. text += ' p_%s_buf = &*(it-1);\n' % data['sub1'].split('/')[-1]
  186. text += ' break;\n'
  187. text += ' }\n'
  188. text += ' }\n\n'
  189. text += ' if (it == %s_ringbuf.end()) {\n' % data['sub1'].split('/')[-1]
  190. text += ' p_%s_buf = &(%s_ringbuf.back());\n' % (data['sub1'].split('/')[-1], data['sub1'].split('/')[-1])
  191. text += ' }\n'
  192. else :
  193. print "failed: sched_policy 2, short_rate unmatched sub1 or sub2"
  194. text += ' publish_msg(p_%s_buf, p_%s_buf);\n' % (data['sub1'].split('/')[-1], data['sub2'].split('/')[-1])
  195. text += ' pthread_mutex_unlock(&mutex);\n'
  196. text += ' return true;\n'
  197. text += ' } else {\n'
  198. text += ' return false;\n'
  199. text += ' }\n'
  200. text += '}\n'
  201. text += '#else\n'
  202. text += '%s %s_buf;\n' % (data['sub1_header'].replace('/', '::'), data['sub1'].split('/')[-1])
  203. text += '%s %s_buf;\n\n' % (data['sub2_header'].replace('/', '::'), data['sub2'].split('/')[-1])
  204. text += 'void %s_callback(const %s::ConstPtr& %s_msg) {\n' % (data['sub1'].split('/')[-1], data['sub1_header'].replace('/', '::'), data['sub1'].split('/')[-1])
  205. text += ' pthread_mutex_lock(&mutex);\n'
  206. text += ' %s_ringbuf.push_front(*%s_msg);\n\n' % (data['sub1'].split('/')[-1], data['sub1'].split('/')[-1])
  207. text += ' //%s is empty\n' % data['sub2'].split('/')[-1]
  208. text += ' if (%s_ringbuf.begin() == %s_ringbuf.end()) {\n' % (data['sub2'].split('/')[-1], data['sub2'].split('/')[-1])
  209. text += ' pthread_mutex_unlock(&mutex);\n'
  210. text += ' ROS_INFO("%s ring buffer is empty");\n' % data['sub2'].split('/')[-1]
  211. text += ' return;\n'
  212. text += ' }\n\n'
  213. text += ' buf_flag = true;\n\n'
  214. if data['sched_policy'] == 1:
  215. text += ' // %s > %s\n' % (data['sub1'].split('/')[-1], data['sub2'].split('/')[-1])
  216. text += ' if (get_time(&(%s_ringbuf.front().header)) >= get_time(&(%s_ringbuf.front().header))) {\n' % (data['sub1'].split('/')[-1], data['sub2'].split('/')[-1])
  217. text += ' %s_buf = %s_ringbuf.front();\n' % (data['sub2'].split('/')[-1], data['sub2'].split('/')[-1])
  218. text += ' boost::circular_buffer<%s>::iterator it = %s_ringbuf.begin();\n' % (data['sub1_header'].replace('/', '::'), data['sub1'].split('/')[-1])
  219. text += ' if (%s_ringbuf.size() == 1) {\n' % data['sub1'].split('/')[-1]
  220. text += ' %s_buf = *it;\n' % data['sub1'].split('/')[-1]
  221. text += ' pthread_mutex_unlock(&mutex);\n'
  222. text += ' return;\n'
  223. text += ' } else {\n'
  224. text += ' for (it++; it != %s_ringbuf.end(); it++) {\n' % data['sub1'].split('/')[-1]
  225. text += ' if (fabs_time_diff(&(%s_ringbuf.front().header), &((it-1)->header))\n' % data['sub2'].split('/')[-1]
  226. text += ' < fabs_time_diff(&(%s_ringbuf.front().header), &(it->header))) {\n' % data['sub2'].split('/')[-1]
  227. text += ' %s_buf = *(it-1);\n' % data['sub1'].split('/')[-1]
  228. text += ' break;\n'
  229. text += ' }\n'
  230. text += ' }\n'
  231. text += ' if (it == %s_ringbuf.end()) {\n' % data['sub1'].split('/')[-1]
  232. text += ' %s_buf = %s_ringbuf.back();\n' % (data['sub1'].split('/')[-1], data['sub1'].split('/')[-1])
  233. text += ' }\n'
  234. text += ' }\n\n'
  235. text += ' } else {\n'
  236. text += ' %s_buf = %s_ringbuf.front();\n' % (data['sub1'].split('/')[-1], data['sub1'].split('/')[-1])
  237. text += ' boost::circular_buffer<%s>::iterator it = %s_ringbuf.begin();\n' % (data['sub2_header'].replace('/', '::'), data['sub2'].split('/')[-1])
  238. text += ' if (%s_ringbuf.size() == 1) {\n' % data['sub2'].split('/')[-1]
  239. text += ' %s_buf = *it;\n' % data['sub2'].split('/')[-1]
  240. text += ' pthread_mutex_unlock(&mutex);\n'
  241. text += ' return;\n'
  242. text += ' }\n\n'
  243. text += ' for (it++; it != %s_ringbuf.end(); it++) {\n' % data['sub2'].split('/')[-1]
  244. text += ' if (fabs_time_diff(&(%s_ringbuf.front().header), &((it-1)->header))\n' % data['sub1'].split('/')[-1]
  245. text += ' < fabs_time_diff(&(%s_ringbuf.front().header), &(it->header))) {\n' % data['sub1'].split('/')[-1]
  246. text += ' %s_buf = *(it-1);\n' % data['sub2'].split('/')[-1]
  247. text += ' break;\n'
  248. text += ' }\n'
  249. text += ' }\n\n'
  250. text += ' if (it == %s_ringbuf.end()) {\n' % data['sub2'].split('/')[-1]
  251. text += ' %s_buf = %s_ringbuf.back();\n' % (data['sub2'].split('/')[-1], data['sub2'].split('/')[-1])
  252. text += ' }\n'
  253. text += ' }\n'
  254. elif data['sched_policy'] == 2:
  255. text += ' %s_buf = %s_ringbuf.front();\n' % (data['short_rate'].split('/')[-1], data['short_rate'].split('/')[-1])
  256. if data['short_rate'] == data['sub1'] :
  257. text += ' boost::circular_buffer<%s>::iterator it = %s_ringbuf.begin();\n' % (data['sub2_header'].replace('/', '::'), data['sub2'].split('/')[-1])
  258. text += ' if (%s_ringbuf.size() == 1) {\n' % data['sub2'].split('/')[-1]
  259. text += ' %s_buf = *it;\n' % data['sub2'].split('/')[-1]
  260. text += ' pthread_mutex_unlock(&mutex);\n'
  261. text += ' return;\n'
  262. text += ' }\n\n'
  263. text += ' for (it++; it != %s_ringbuf.end(); it++) {\n' % data['sub2'].split('/')[-1]
  264. text += ' if (fabs_time_diff(&(%s_ringbuf.front().header), &((it-1)->header))\n' % data['short_rate'].split('/')[-1]
  265. text += ' < fabs_time_diff(&(%s_ringbuf.front().header), &(it->header))) {\n' % data['short_rate'].split('/')[-1]
  266. text += ' %s_buf = *(it-1);\n' % data['sub2'].split('/')[-1]
  267. text += ' break;\n'
  268. text += ' }\n'
  269. text += ' }\n\n'
  270. text += ' if (it == %s_ringbuf.end()) {\n' % data['sub2'].split('/')[-1]
  271. text += ' %s_buf = %s_ringbuf.back();\n' % (data['sub2'].split('/')[-1], data['sub2'].split('/')[-1])
  272. text += ' }\n'
  273. elif data['short_rate'] == data['sub2']:
  274. text += ' boost::circular_buffer<%s>::iterator it = %s_ringbuf.begin();\n' % (data['sub1_header'].replace('/', '::'), data['sub1'].split('/')[-1])
  275. text += ' if (%s_ringbuf.size() == 1) {\n' % data['sub1'].split('/')[-1]
  276. text += ' %s_buf = *it;\n' % data['sub1'].split('/')[-1]
  277. text += ' pthread_mutex_unlock(&mutex);\n'
  278. text += ' return;\n'
  279. text += ' }\n\n'
  280. text += ' for (it++; it != %s_ringbuf.end(); it++) {\n' % data['sub1'].split('/')[-1]
  281. text += ' if (fabs_time_diff(&(%s_ringbuf.front().header), &((it-1)->header))\n' % data['short_rate'].split('/')[-1]
  282. text += ' < fabs_time_diff(&(%s_ringbuf.front().header), &(it->header))) {\n' % data['short_rate'].split('/')[-1]
  283. text += ' %s_buf = *(it-1);\n' % data['sub1'].split('/')[-1]
  284. text += ' break;\n'
  285. text += ' }\n'
  286. text += ' }\n\n'
  287. text += ' if (it == %s_ringbuf.end()) {\n' % data['sub1'].split('/')[-1]
  288. text += ' %s_buf = %s_ringbuf.back();\n' % (data['sub1'].split('/')[-1], data['sub1'].split('/')[-1])
  289. text += ' }\n'
  290. else :
  291. print "failed: sched_policy 2, short_rate unmatched sub1 or sub2"
  292. text += ' pthread_mutex_unlock(&mutex);\n'
  293. text += '}\n\n'
  294. text += 'void %s_callback(const %s::ConstPtr& %s_msg) {\n' % (data['sub2'].split('/')[-1], data['sub2_header'].replace('/', '::'), data['sub2'].split('/')[-1])
  295. text += ' pthread_mutex_lock(&mutex);\n'
  296. text += ' %s_ringbuf.push_front(*%s_msg);\n' % (data['sub2'].split('/')[-1], data['sub2'].split('/')[-1])
  297. text += ' //%s is empty\n' % data['sub1'].split('/')[-1]
  298. text += ' if (%s_ringbuf.begin() == %s_ringbuf.end()) {\n' % (data['sub1'].split('/')[-1], data['sub1'].split('/')[-1])
  299. text += ' ROS_INFO("%s ring buffer is empty");\n' % data['sub1'].split('/')[-1]
  300. text += ' pthread_mutex_unlock(&mutex);\n'
  301. text += ' return;\n'
  302. text += ' }\n\n'
  303. text += ' buf_flag = true;\n\n'
  304. if data['sched_policy'] == 1:
  305. text += ' // %s > %s\n' % (data['sub1'].split('/')[-1], data['sub2'].split('/')[-1])
  306. text += ' if (get_time(&(%s_ringbuf.front().header)) >= get_time(&(%s_ringbuf.front().header))) {\n' % (data['sub1'].split('/')[-1], data['sub2'].split('/')[-1])
  307. text += ' %s_buf = %s_ringbuf.front();\n' % (data['sub2'].split('/')[-1], data['sub2'].split('/')[-1])
  308. text += ' boost::circular_buffer<%s>::iterator it = %s_ringbuf.begin();\n' % (data['sub1_header'].replace('/', '::'), data['sub1'].split('/')[-1])
  309. text += ' if (%s_ringbuf.size() == 1) {\n' % data['sub1'].split('/')[-1]
  310. text += ' %s_buf = *it;\n' % data['sub1'].split('/')[-1]
  311. text += ' pthread_mutex_unlock(&mutex);\n'
  312. text += ' return;\n'
  313. text += ' } else {\n'
  314. text += ' for (it++; it != %s_ringbuf.end(); it++) {\n' % data['sub1'].split('/')[-1]
  315. text += ' if (fabs_time_diff(&(%s_ringbuf.front().header), &((it-1)->header))\n' % data['sub2'].split('/')[-1]
  316. text += ' < fabs_time_diff(&(%s_ringbuf.front().header), &(it->header))) {\n' % data['sub2'].split('/')[-1]
  317. text += ' %s_buf = *(it-1);\n' % data['sub1'].split('/')[-1]
  318. text += ' break;\n'
  319. text += ' }\n'
  320. text += ' }\n'
  321. text += ' if (it == %s_ringbuf.end()) {\n' % data['sub1'].split('/')[-1]
  322. text += ' %s_buf = %s_ringbuf.back();\n' % (data['sub1'].split('/')[-1], data['sub1'].split('/')[-1])
  323. text += ' }\n'
  324. text += ' }\n\n'
  325. text += ' } else {\n'
  326. text += ' %s_buf = %s_ringbuf.front();\n' % (data['sub1'].split('/')[-1], data['sub1'].split('/')[-1])
  327. text += ' boost::circular_buffer<%s>::iterator it = %s_ringbuf.begin();\n' % (data['sub2_header'].replace('/', '::'), data['sub2'].split('/')[-1])
  328. text += ' if (%s_ringbuf.size() == 1) {\n' % data['sub2'].split('/')[-1]
  329. text += ' %s_buf = *it;\n' % data['sub2'].split('/')[-1]
  330. text += ' pthread_mutex_unlock(&mutex);\n'
  331. text += ' return;\n'
  332. text += ' }\n\n'
  333. text += ' for (it++; it != %s_ringbuf.end(); it++) {\n' % data['sub2'].split('/')[-1]
  334. text += ' if (fabs_time_diff(&(%s_ringbuf.front().header), &((it-1)->header))\n' % data['sub1'].split('/')[-1]
  335. text += ' < fabs_time_diff(&(%s_ringbuf.front().header), &(it->header))) {\n' % data['sub1'].split('/')[-1]
  336. text += ' %s_buf = *(it-1);\n' % data['sub2'].split('/')[-1]
  337. text += ' break;\n'
  338. text += ' }\n'
  339. text += ' }\n\n'
  340. text += ' if (it == %s_ringbuf.end()) {\n' % data['sub2'].split('/')[-1]
  341. text += ' %s_buf = %s_ringbuf.back();\n' % (data['sub2'].split('/')[-1], data['sub2'].split('/')[-1])
  342. text += ' }\n'
  343. text += ' }\n'
  344. elif data['sched_policy'] == 2:
  345. text += ' %s_buf = %s_ringbuf.front();\n' % (data['short_rate'].split('/')[-1], data['short_rate'].split('/')[-1])
  346. if data['short_rate'] == data['sub1'] :
  347. text += ' boost::circular_buffer<%s>::iterator it = %s_ringbuf.begin();\n' % (data['sub2_header'].replace('/', '::'), data['sub2'].split('/')[-1])
  348. text += ' if (%s_ringbuf.size() == 1) {\n' % data['sub2'].split('/')[-1]
  349. text += ' %s_buf = *it;\n' % data['sub2'].split('/')[-1]
  350. text += ' pthread_mutex_unlock(&mutex);\n'
  351. text += ' return;\n'
  352. text += ' }\n\n'
  353. text += ' for (it++; it != %s_ringbuf.end(); it++) {\n' % data['sub2'].split('/')[-1]
  354. text += ' if (fabs_time_diff(&(%s_ringbuf.front().header), &((it-1)->header))\n' % data['short_rate'].split('/')[-1]
  355. text += ' < fabs_time_diff(&(%s_ringbuf.front().header), &(it->header))) {\n' % data['short_rate'].split('/')[-1]
  356. text += ' %s_buf = *(it-1);\n' % data['sub2'].split('/')[-1]
  357. text += ' break;\n'
  358. text += ' }\n'
  359. text += ' }\n\n'
  360. text += ' if (it == %s_ringbuf.end()) {\n' % data['sub2'].split('/')[-1]
  361. text += ' %s_buf = %s_ringbuf.back();\n' % (data['sub2'].split('/')[-1], data['sub2'].split('/')[-1])
  362. text += ' }\n'
  363. elif data['short_rate'] == data['sub2']:
  364. text += ' boost::circular_buffer<%s>::iterator it = %s_ringbuf.begin();\n' % (data['sub1_header'].replace('/', '::'), data['sub1'].split('/')[-1])
  365. text += ' if (%s_ringbuf.size() == 1) {\n' % data['sub1'].split('/')[-1]
  366. text += ' %s_buf = *it;\n' % data['sub1'].split('/')[-1]
  367. text += ' pthread_mutex_unlock(&mutex);\n'
  368. text += ' return;\n'
  369. text += ' }\n\n'
  370. text += ' for (it++; it != %s_ringbuf.end(); it++) {\n' % data['sub1'].split('/')[-1]
  371. text += ' if (fabs_time_diff(&(%s_ringbuf.front().header), &((it-1)->header))\n' % data['short_rate'].split('/')[-1]
  372. text += ' < fabs_time_diff(&(%s_ringbuf.front().header), &(it->header))) {\n' % data['short_rate'].split('/')[-1]
  373. text += ' %s_buf = *(it-1);\n' % data['sub1'].split('/')[-1]
  374. text += ' break;\n'
  375. text += ' }\n'
  376. text += ' }\n\n'
  377. text += ' if (it == %s_ringbuf.end()) {\n' % data['sub1'].split('/')[-1]
  378. text += ' %s_buf = %s_ringbuf.back();\n' % (data['sub1'].split('/')[-1], data['sub1'].split('/')[-1])
  379. text += ' }\n'
  380. else :
  381. print "failed: sched_policy 2, short_rate unmatched sub1 or sub2"
  382. text += ' pthread_mutex_unlock(&mutex);\n'
  383. text += '}\n\n'
  384. text += 'bool publish() {\n'
  385. text += ' if (buf_flag) {\n'
  386. text += ' pthread_mutex_lock(&mutex);\n'
  387. text += ' // scan_ringbuf.clear();\n'
  388. text += ' // image_ringbuf.clear();\n'
  389. text += ' // scan_ringbuf.push_front(scan_buf);\n'
  390. text += ' // image_ringbuf.push_front(image_buf);\n'
  391. text += ' ROS_INFO("publish");\n'
  392. text += ' %s_pub.publish(%s_buf);\n' % (data['pub1'].split('/')[-1], data['sub1'].split('/')[-1])
  393. text += ' %s_pub.publish(%s_buf);\n' % (data['pub2'].split('/')[-1], data['sub2'].split('/')[-1])
  394. text += ' pthread_mutex_unlock(&mutex);\n'
  395. text += ' return true;\n'
  396. text += ' } else {\n'
  397. text += ' ROS_INFO("publish failed");\n'
  398. text += ' return false;\n'
  399. text += ' }\n'
  400. text += '}\n'
  401. text += '#endif\n\n'
  402. text += 'void %s_callback(const %s::ConstPtr& %s_msg) {\n' % (data['sync_sub1'].split('/')[-1], data['sync_sub1_header'].replace('/', '::'), data['sync_sub1'].split('/')[-1])
  403. text += ' if (%s_flag) {\n' % data['sync_sub1'].split('/')[-1]
  404. text += ' %s_flag = false;\n' % data['sync_sub1'].split('/')[-1]
  405. text += ' %s_flag = false;\n' % data['sync_sub2'].split('/')[-1]
  406. text += ' return;\n'
  407. text += ' }\n\n'
  408. text += ' %s_flag = true;\n' % data['sync_sub1'].split('/')[-1]
  409. text += ' if (%s_flag) {\n' % data['sync_sub2'].split('/')[-1]
  410. text += ' ROS_INFO("catch publish request");\n'
  411. text += ' if(!publish()) {\n'
  412. text += ' /* when to publish is failure, republish */\n'
  413. text += ' struct timespec sleep_time;\n'
  414. text += ' sleep_time.tv_sec = 0;\n'
  415. text += ' sleep_time.tv_nsec = 200000000; //5Hz\n'
  416. text += ' while (!publish() || ros::ok())\n'
  417. text += ' nanosleep(&sleep_time, NULL);\n'
  418. text += ' }\n'
  419. text += ' %s_flag = false;\n' % data['sync_sub1'].split('/')[-1]
  420. text += ' %s_flag = false;\n' % data['sync_sub2'].split('/')[-1]
  421. text += ' }\n'
  422. text += '}\n'
  423. text += 'void %s_callback(const %s::ConstPtr& %s_msg) {\n' % (data['sync_sub2'].split('/')[-1], data['sync_sub2_header'].replace('/', '::'), data['sync_sub2'].split('/')[-1])
  424. text += ' if (%s_flag) {\n' % data['sync_sub2'].split('/')[-1]
  425. text += ' %s_flag = false;\n' % data['sync_sub1'].split('/')[-1]
  426. text += ' %s_flag = false;\n' % data['sync_sub2'].split('/')[-1]
  427. text += ' return;\n'
  428. text += ' }\n\n'
  429. text += ' %s_flag = true;\n' % data['sync_sub2'].split('/')[-1]
  430. text += ' if (%s_flag) {\n' % data['sync_sub1'].split('/')[-1]
  431. text += ' ROS_INFO("catch publish request");\n'
  432. text += ' if(!publish()) {\n'
  433. text += ' /* when to publish is failure, republish */\n'
  434. text += ' struct timespec sleep_time;\n'
  435. text += ' sleep_time.tv_sec = 0;\n'
  436. text += ' sleep_time.tv_nsec = 200000000; //5Hz\n'
  437. text += ' while (!publish() || ros::ok())\n'
  438. text += ' nanosleep(&sleep_time, NULL);\n'
  439. text += ' }\n'
  440. text += ' %s_flag = false;\n' % data['sync_sub1'].split('/')[-1]
  441. text += ' %s_flag = false;\n' % data['sync_sub2'].split('/')[-1]
  442. text += ' }\n'
  443. text += '}\n\n'
  444. text += 'void* thread(void* args)\n'
  445. text += '{\n'
  446. text += ' ros::NodeHandle nh_rcv;\n'
  447. text += ' ros::CallbackQueue rcv_callbackqueue;\n'
  448. text += ' nh_rcv.setCallbackQueue(&rcv_callbackqueue);\n'
  449. text += ' ros::Subscriber %s_sub = nh_rcv.subscribe("%s", 5, %s_callback);\n' % (data['sync_sub1'].split('/')[-1], data['sync_sub1'].split('/')[-1], data['sync_sub1'].split('/')[-1])
  450. text += ' ros::Subscriber %s_sub = nh_rcv.subscribe("%s", 5, %s_callback);\n' % (data['sync_sub2'].split('/')[-1], data['sync_sub2'].split('/')[-1], data['sync_sub2'].split('/')[-1])
  451. text += ' while (nh_rcv.ok())\n'
  452. text += ' rcv_callbackqueue.callAvailable(ros::WallDuration(1.0f));\n'
  453. text += ' return NULL;\n'
  454. text += '}\n\n'
  455. text += 'int main(int argc, char **argv) {\n'
  456. text += ' ros::init(argc, argv, "%s");\n' % data['node_name'].split('/')[-1]
  457. text += ' ros::NodeHandle nh;\n\n'
  458. text += ' /* create server thread */\n'
  459. text += ' pthread_t th;\n'
  460. text += ' pthread_create(&th, NULL, thread, (void *)NULL );\n\n'
  461. text += ' ros::Subscriber %s_sub = nh.subscribe("%s", 1, %s_callback);\n' % (data['sub1'].split('/')[-1], data['sub1'], data['sub1'].split('/')[-1])
  462. text += ' ros::Subscriber %s_sub = nh.subscribe("%s", 1, %s_callback);\n' % (data['sub2'].split('/')[-1], data['sub2'], data['sub2'].split('/')[-1])
  463. text += ' %s_pub = nh.advertise<%s>("%s", 5);\n' % (data['pub1'].split('/')[-1], data['sub1_header'].replace('/', '::'), data['pub1'])
  464. text += ' %s_pub = nh.advertise<%s>("%s", 5);\n' % (data['pub2'].split('/')[-1], data['sub2_header'].replace('/', '::'), data['pub2'])
  465. text += ' while (!buf_flag) {\n'
  466. text += ' ros::spinOnce();\n'
  467. text += ' }\n'
  468. text += ' if(!publish()) {\n'
  469. text += ' /* when to publish is failure, republish */\n'
  470. text += ' struct timespec sleep_time;\n'
  471. text += ' sleep_time.tv_sec = 0;\n'
  472. text += ' sleep_time.tv_nsec = 200000000; //5Hz\n'
  473. text += ' while (!publish() || ros::ok())\n'
  474. text += ' nanosleep(&sleep_time, NULL);\n'
  475. text += ' }\n\n'
  476. text += ' ros::spin();\n\n'
  477. text += ' /* shutdown server thread */\n'
  478. text += ' ROS_INFO("wait until shutdown a thread");\n'
  479. text += ' pthread_kill(th, SIGINT);\n'
  480. text += ' pthread_join(th, NULL);\n\n'
  481. text += ' return 0;\n'
  482. text += '}\n'
  483. f_generate.write(text)
  484. f_config.close()
  485. f_generate.close()
  486. print "generate "