sync_generator2.py 35 KB

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