PageRenderTime 45ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/Lib/Platform/OP/Comm/luaNSLComm.cc

http://github.com/UPenn-RoboCup/UPennalizers
C++ | 400 lines | 279 code | 76 blank | 45 comment | 36 complexity | b6c314fb21362c6bbc40443b2d551f47 MD5 | raw file
Possible License(s): GPL-3.0
  1. #include <string>
  2. #include <deque>
  3. #include "string.h"
  4. #include <stdlib.h>
  5. #include <fcntl.h>
  6. #include <unistd.h>
  7. #include <sys/types.h>
  8. #include <sys/socket.h>
  9. #include <netinet/in.h>
  10. #include <arpa/inet.h>
  11. #include <netdb.h>
  12. #ifdef __cplusplus
  13. extern "C"
  14. {
  15. #endif
  16. #include "lua.h"
  17. #include "lualib.h"
  18. #include "lauxlib.h"
  19. #ifdef __cplusplus
  20. }
  21. #endif
  22. #include <vector>
  23. #include <stdint.h>
  24. // Set the IP address for where to listen
  25. //#define IP "255.255.255.255"
  26. //#define IP "172.18.255.255"
  27. //#define IP "192.168.123.255" // OP wired
  28. #define IP "192.168.1.255" // OP, wireless
  29. //#define IP "192.168.255.255"
  30. //#define IP "158.130.103.255" // AirPennNet-Guest specific
  31. //#define IP "158.130.104.255" //AIRPENNET
  32. //#define IP "10.66.68.255"
  33. //#define IP "192.168.118.255" // OP, Istanbul
  34. #define PORT 54321
  35. #define MDELAY 2
  36. #define TTL 16
  37. #define MAX_LENGTH 160000 //Size for sending 640*480 yuyv data without resampling
  38. const int maxQueueSize = 6;
  39. static std::deque<std::string> recvQueue;
  40. static int send_fd, recv_fd;
  41. /*
  42. void mexExit(void)
  43. {
  44. if (send_fd > 0)
  45. close(send_fd);
  46. if (recv_fd > 0)
  47. close(recv_fd);
  48. }
  49. */
  50. static int lua_darwinopcomm_update(lua_State *L) {
  51. static sockaddr_in source_addr;
  52. static char data[MAX_LENGTH];
  53. static bool init = false;
  54. if (!init) {
  55. struct hostent *hostptr = gethostbyname(IP);
  56. if (hostptr == NULL) {
  57. printf("Could not get hostname\n");
  58. return -1;
  59. }
  60. send_fd = socket(AF_INET, SOCK_DGRAM, 0);
  61. if (send_fd < 0) {
  62. printf("Could not open datagram send socket\n");
  63. return -1;
  64. }
  65. int i = 1;
  66. if (setsockopt(send_fd, SOL_SOCKET, SO_BROADCAST, (const char *) &i, sizeof(i)) < 0) {
  67. printf("Could not set broadcast option\n");
  68. return -1;
  69. }
  70. struct sockaddr_in dest_addr;
  71. bzero((char *) &dest_addr, sizeof(dest_addr));
  72. dest_addr.sin_family = AF_INET;
  73. bcopy(hostptr->h_addr, (char *) &dest_addr.sin_addr, hostptr->h_length);
  74. dest_addr.sin_port = htons(PORT);
  75. if (connect(send_fd, (struct sockaddr *) &dest_addr, sizeof(dest_addr)) < 0) {
  76. printf("Could not connect to destination address\n");
  77. return -1;
  78. }
  79. recv_fd = socket(AF_INET, SOCK_DGRAM, 0);
  80. if (recv_fd < 0) {
  81. printf("Could not open datagram recv socket\n");
  82. return -1;
  83. }
  84. struct sockaddr_in local_addr;
  85. bzero((char *) &local_addr, sizeof(local_addr));
  86. local_addr.sin_family = AF_INET;
  87. local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  88. local_addr.sin_port = htons(PORT);
  89. if (bind(recv_fd, (struct sockaddr *) &local_addr, sizeof(local_addr)) < 0) {
  90. printf("Could not bind to port\n");
  91. return -1;
  92. }
  93. // Nonblocking receive:
  94. int flags = fcntl(recv_fd, F_GETFL, 0);
  95. if (flags == -1)
  96. flags = 0;
  97. if (fcntl(recv_fd, F_SETFL, flags | O_NONBLOCK) < 0) {
  98. printf("Could not set nonblocking mode\n");
  99. return -1;
  100. }
  101. // TODO: set at exit
  102. init = true;
  103. }
  104. // Process incoming messages:
  105. socklen_t source_addr_len = sizeof(source_addr);
  106. int len = recvfrom(recv_fd, data, MAX_LENGTH, 0, (struct sockaddr *) &source_addr, &source_addr_len);
  107. while (len > 0) {
  108. std::string msg((const char *) data, len);
  109. recvQueue.push_back(msg);
  110. len = recvfrom(recv_fd, data, MAX_LENGTH, 0, (struct sockaddr *) &source_addr, &source_addr_len);
  111. }
  112. // Remove older messages:
  113. while (recvQueue.size() > maxQueueSize) {
  114. recvQueue.pop_front();
  115. }
  116. return 1;
  117. }
  118. static int lua_darwinopcomm_size(lua_State *L) {
  119. int updateRet = lua_darwinopcomm_update(L);
  120. lua_pushinteger(L, recvQueue.size());
  121. return 1;
  122. }
  123. static int lua_darwinopcomm_receive(lua_State *L) {
  124. int updateRet = lua_darwinopcomm_update(L);
  125. if (recvQueue.empty()) {
  126. lua_pushnil(L);
  127. return 1;
  128. }
  129. // TODO: is this enough or do i need to pass an array with the bytes
  130. lua_pushstring(L, recvQueue.front().c_str());
  131. recvQueue.pop_front();
  132. /*
  133. int n = recvQueue.front().size();
  134. mwSize dims[2];
  135. dims[0] = 1;
  136. dims[1] = n;
  137. plhs[0] = mxCreateNumericArray(2, dims, mxUINT8_CLASS, mxREAL);
  138. memcpy(mxGetData(plhs[0]), recvQueue.front().c_str(), n);
  139. recvQueue.pop_front();
  140. */
  141. return 1;
  142. }
  143. static int lua_darwinopcomm_send(lua_State *L) {
  144. int updateRet = lua_darwinopcomm_update(L);
  145. // TODO: implement send command
  146. const char *data = luaL_checkstring(L, 1);
  147. std::string dataStr(data);
  148. int ret = send(send_fd, dataStr.c_str(), dataStr.size(), 0);
  149. lua_pushinteger(L, ret);
  150. /*
  151. if (nrhs < 2)
  152. mexErrMsgTxt("No input argument");
  153. int n = mxGetNumberOfElements(prhs[1])*mxGetElementSize(prhs[1]);
  154. int ret = send(send_fd, mxGetData(prhs[1]), n, 0);
  155. plhs[0] = mxCreateDoubleScalar(ret);
  156. // Put it in receive queue as well:
  157. //std::string msg((const char *) mxGetData(prhs[1]), n);
  158. //recvQueue.push_back(msg);
  159. */
  160. return 1;
  161. }
  162. static int lua_darwinopcomm_send_yuyv(lua_State *L) {
  163. int updateRet = lua_darwinopcomm_update(L);
  164. std::string dataStrY;
  165. std::string dataStrU;
  166. std::string dataStrV;
  167. uint32_t *yuyv = (uint32_t *) lua_touserdata(L, 1);//yuyv image
  168. if ((yuyv == NULL) || !lua_islightuserdata(L, 1)) {
  169. return luaL_error(L, "Input YUYV not light user data");
  170. }
  171. int m = luaL_checkint(L, 2); //Width (in macro pixel)
  172. int n = luaL_checkint(L, 3); //Height
  173. int samplerate = luaL_checkint(L, 4); //sampling rate
  174. int robotid = luaL_checkint(L, 5); //robot ID
  175. int m_sample=m/samplerate;
  176. int n_sample=n/samplerate;
  177. dataStrY.push_back(14); //yuyv data Y
  178. dataStrY.push_back(m_sample/256); //High bit of width
  179. dataStrY.push_back(m_sample%256); //Low bit of width
  180. dataStrY.push_back(n_sample/256); //High bit of height
  181. dataStrY.push_back(n_sample%256); //Low bit of height
  182. dataStrY.push_back(robotid); //robot ID
  183. dataStrU.push_back(15); //yuyv data U
  184. dataStrU.push_back(m_sample/256); //High bit of width
  185. dataStrU.push_back(m_sample%256); //Low bit of width
  186. dataStrU.push_back(n_sample/256); //High bit of height
  187. dataStrU.push_back(n_sample%256); //Low bit of height
  188. dataStrU.push_back(robotid); //robot ID
  189. dataStrV.push_back(16); //yuyv data V
  190. dataStrV.push_back(m_sample/256); //High bit of width
  191. dataStrV.push_back(m_sample%256); //Low bit of width
  192. dataStrV.push_back(n_sample/256); //High bit of height
  193. dataStrV.push_back(n_sample%256); //Low bit of height
  194. dataStrV.push_back(robotid); //robot ID
  195. for (int j = 0; j < n; j++) {
  196. for (int i = 0; i < m; i++) {
  197. if (((i%samplerate==0) && (j%samplerate==0)) || samplerate==1) {
  198. char indexY= (*yuyv & 0xFC000000) >> 26;
  199. char indexU= (*yuyv & 0x0000FC00) >> 10;
  200. char indexV= (*yuyv & 0xFC0000FC) >> 2;
  201. dataStrY.push_back(indexY);
  202. dataStrU.push_back(indexU);
  203. dataStrV.push_back(indexV);
  204. }
  205. yuyv++;
  206. }
  207. }
  208. int ret1 = send(send_fd, dataStrY.c_str(), dataStrY.size(), 0);
  209. int ret2 = send(send_fd, dataStrU.c_str(), dataStrU.size(), 0);
  210. int ret3 = send(send_fd, dataStrV.c_str(), dataStrV.size(), 0);
  211. lua_pushinteger(L, ret1+ret2+ret3);
  212. return 1;
  213. }
  214. static int lua_darwinopcomm_send_label(lua_State *L) {
  215. int updateRet = lua_darwinopcomm_update(L);
  216. std::string dataStr;
  217. uint8_t *label = (uint8_t *) lua_touserdata(L, 1);//label image
  218. if ((label == NULL) || !lua_islightuserdata(L, 1)) {
  219. return luaL_error(L, "Input Label not light user data");
  220. }
  221. int m = luaL_checkint(L, 2); //Width
  222. int n = luaL_checkint(L, 3); //Height
  223. int samplerate = luaL_checkint(L, 4); //downsample rate
  224. int robotid = luaL_checkint(L, 5); //robot ID
  225. int m_sample=m/samplerate;
  226. int n_sample=n/samplerate;
  227. dataStr.push_back(17); //Label data
  228. dataStr.push_back(m_sample/256); //High bit of width
  229. dataStr.push_back(m_sample%256); //Low bit of width
  230. dataStr.push_back(n_sample/256); //High bit of height
  231. dataStr.push_back(n_sample%256); //Low bit of height
  232. dataStr.push_back(robotid); //robot ID
  233. for (int j = 0; j < n; j++) {
  234. for (int i = 0; i < m; i++) {
  235. if( ( (i%samplerate==0) && (j%samplerate==0)) || (samplerate==1))
  236. dataStr.push_back(*label);
  237. label++;
  238. }
  239. }
  240. int ret = send(send_fd, dataStr.c_str(), dataStr.size(), 0);
  241. lua_pushinteger(L, ret);
  242. return 1;
  243. }
  244. static int lua_darwinopcomm_send_yuyv2(lua_State *L) {
  245. int updateRet = lua_darwinopcomm_update(L);
  246. std::string dataStrY;
  247. std::string dataStrU;
  248. std::string dataStrV;
  249. uint32_t *yuyv = (uint32_t *) lua_touserdata(L, 1);//yuyv image
  250. if ((yuyv == NULL) || !lua_islightuserdata(L, 1)) {
  251. return luaL_error(L, "Input YUYV not light user data");
  252. }
  253. int m = luaL_checkint(L, 2); //Width (in macro pixel)
  254. int n = luaL_checkint(L, 3); //Height
  255. int robotid = luaL_checkint(L, 4); //robot ID
  256. //I had to divide the image into sections and send one by one
  257. int division = luaL_checkint(L, 5); //How many division?
  258. int section = luaL_checkint(L, 6); //Which section?
  259. yuyv=yuyv+ m*(n/division)*section; //Skip unused section
  260. dataStrY.push_back(18); //Partitioned yuyv data Y
  261. dataStrY.push_back(robotid); //robot ID
  262. dataStrY.push_back(division); //division
  263. dataStrY.push_back(section); //section
  264. dataStrU.push_back(19); //Partitioned yuyv data U
  265. dataStrU.push_back(robotid); //robot ID
  266. dataStrU.push_back(division); //division
  267. dataStrU.push_back(section); //section
  268. dataStrV.push_back(20); //Partitioned yuyv data V
  269. dataStrV.push_back(robotid); //robot ID
  270. dataStrV.push_back(division); //division
  271. dataStrV.push_back(section); //section
  272. for (int j = 0; j < n/division; j++) {
  273. for (int i = 0; i < m; i++) {
  274. char indexY= (*yuyv & 0xFC000000) >> 26;
  275. char indexU= (*yuyv & 0x0000FC00) >> 10;
  276. char indexV= (*yuyv & 0xFC0000FC) >> 2;
  277. dataStrY.push_back(indexY);
  278. dataStrU.push_back(indexU);
  279. dataStrV.push_back(indexV);
  280. yuyv++;
  281. }
  282. }
  283. int ret1 = send(send_fd, dataStrY.c_str(), dataStrY.size(), 0);
  284. int ret2 = send(send_fd, dataStrU.c_str(), dataStrU.size(), 0);
  285. int ret3 = send(send_fd, dataStrV.c_str(), dataStrV.size(), 0);
  286. lua_pushinteger(L,ret1+ret2+ret3);
  287. return 1;
  288. }
  289. static int lua_darwinopcomm_send_particle(lua_State *L) {
  290. int updateRet = lua_darwinopcomm_update(L);
  291. std::string dataStr;
  292. int n_sample = luaL_checkint(L, 1);
  293. int robotid = luaL_checkint(L, 2); //robot ID
  294. const char *data = luaL_checkstring(L, 3);
  295. dataStr.push_back(21); //Particle data
  296. dataStr.push_back(robotid); //robot ID
  297. dataStr.push_back(n_sample); //robot ID
  298. for (int i=0;i<n_sample;i++){
  299. dataStr.push_back(*data++);
  300. dataStr.push_back(*data++);
  301. dataStr.push_back(*data++);
  302. }
  303. int ret = send(send_fd, dataStr.c_str(), dataStr.size(), 0);
  304. lua_pushinteger(L, ret);
  305. return 1;
  306. }
  307. static const struct luaL_reg NSLComm_lib [] = {
  308. {"size", lua_darwinopcomm_size},
  309. {"receive", lua_darwinopcomm_receive},
  310. {"send", lua_darwinopcomm_send},
  311. {"send_label", lua_darwinopcomm_send_label},
  312. {"send_yuyv", lua_darwinopcomm_send_yuyv},
  313. {"send_yuyv2", lua_darwinopcomm_send_yuyv2},
  314. {"send_particle", lua_darwinopcomm_send_particle},
  315. {NULL, NULL}
  316. };
  317. #ifdef __cplusplus
  318. extern "C"
  319. #endif
  320. int luaopen_NSLComm (lua_State *L) {
  321. luaL_register(L, "NSLComm", NSLComm_lib);
  322. return 1;
  323. }