$search
00001 /********************************************************************* 00002 * Software License Agreement (BSD License) 00003 * 00004 * Copyright (c) 2009-2010, Willow Garage, Inc. 00005 * All rights reserved. 00006 * 00007 * Redistribution and use in source and binary forms, with or without 00008 * modification, are permitted provided that the following conditions 00009 * are met: 00010 * 00011 * * Redistributions of source code must retain the above copyright 00012 * notice, this list of conditions and the following disclaimer. 00013 * * Redistributions in binary form must reproduce the above 00014 * copyright notice, this list of conditions and the following 00015 * disclaimer in the documentation and/or other materials provided 00016 * with the distribution. 00017 * * Neither the name of the Willow Garage nor the names of its 00018 * contributors may be used to endorse or promote products derived 00019 * from this software without specific prior written permission. 00020 * 00021 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00022 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00023 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00024 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00025 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00026 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00027 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00028 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00029 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00030 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00031 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00032 * POSSIBILITY OF SUCH DAMAGE. 00033 *********************************************************************/ 00034 00035 // Author: Blaise Gassend 00036 00037 #include <sys/socket.h> 00038 #include <netinet/in.h> 00039 #include <sys/types.h> 00040 #include <arpa/inet.h> 00041 #include <string.h> 00042 #include <stdio.h> 00043 #include <stdlib.h> 00044 #include <unistd.h> 00045 #include <signal.h> 00046 #include <errno.h> 00047 #include <sched.h> 00048 00049 #include <ros/console.h> 00050 #include <ros/time.h> 00051 00052 #include <wge100_camera/ipcam_packet.h> 00053 #include <wge100_camera/host_netutil.h> 00054 #include <wge100_camera/wge100lib.h> 00055 #include <wge100_camera/mt9v.h> 00056 00057 class WGE100Simulator 00058 { 00059 public: 00060 WGE100Simulator(uint32_t serial) : serial_no_(serial) 00061 { 00062 in_addr in_addr; 00063 in_addr.s_addr = 0; 00064 socket_ = wge100SocketCreate(&in_addr, WG_CAMCMD_PORT); 00065 if (socket_ == -1) 00066 { 00067 ROS_ERROR("Error creating/binding socket: %s", strerror(errno)); 00068 return; 00069 } 00070 00071 signal(SIGTERM, WGE100Simulator::setExiting); 00072 reset(); 00073 } 00074 00075 int run() 00076 { 00077 if (socket_ == -1) 00078 return -1; 00079 00080 while (!exiting_) 00081 { 00082 ProcessCommands(); 00083 SendData(); 00084 } 00085 00086 return 0; 00087 } 00088 00089 ~WGE100Simulator() 00090 { 00091 if (socket_ != -1) 00092 close(socket_); 00093 } 00094 00095 private: 00096 uint32_t serial_no_; 00097 int socket_; 00098 int running_; 00099 int width_; 00100 int height_; 00101 int frame_; 00102 //ros::Duration period_; 00103 ros::Time next_frame_time_; 00104 sockaddr_in data_addr_; 00105 static const int NUM_IMAGER_REGISTERS = 256; 00106 static const int IMAGER_REGISTER_UNDEFINED = 1; 00107 static const int IMAGER_REGISTER_UNSUPPORTED = 2; 00108 uint16_t imager_registers_[NUM_IMAGER_REGISTERS]; 00109 uint8_t imager_register_flags_[NUM_IMAGER_REGISTERS]; 00110 00111 void reset() 00112 { 00113 running_ = 0; 00114 frame_ = 0; 00115 width_ = 640; 00116 height_ = 480; 00117 //period_ = ros::Duration(1/30.); 00118 next_frame_time_ = ros::Time(0); 00119 for (int i = 0; i < NUM_IMAGER_REGISTERS; i++) 00120 { 00121 imager_registers_[i] = 0; 00122 imager_register_flags_[i] |= IMAGER_REGISTER_UNDEFINED | IMAGER_REGISTER_UNSUPPORTED; 00123 } 00124 uint8_t supported_registers[] = { 0x7F, 0x06, 0x05, 0x04, 0x03, 0 }; 00125 uint16_t init_value[] = { 0 , 0x2D, 0x5E, 0x2F0, 0x1E0, 0x1311 }; 00126 for (unsigned int i = 0; i < sizeof(supported_registers) / sizeof(*supported_registers); i++) 00127 { 00128 imager_register_flags_[supported_registers[i]] &= ~(IMAGER_REGISTER_UNDEFINED | IMAGER_REGISTER_UNSUPPORTED); 00129 imager_registers_[supported_registers[i]] = init_value[i]; 00130 } 00131 00132 uint8_t tolerated_registers[] = { 0x18, 0x15, 0x20, 0x21, 0x01, 0x02, 0x0D, 0x70, 0x71, 0x1C, 0xAF, 0x0B, 0x47, 0x48, 0x4C, 0xA5, 0x35, 0xBD }; 00133 00134 for (unsigned int i = 0; i < sizeof(tolerated_registers) / sizeof(*tolerated_registers); i++) 00135 imager_register_flags_[tolerated_registers[i]] &= ~IMAGER_REGISTER_UNSUPPORTED; 00136 } 00137 00138 static inline uint8_t get_diag_test_pattern(int x, int y) 00139 { 00140 if ((x + 1) / 2 + y < 500) 00141 return 14 + x / 4; 00142 else 00143 return 0; 00144 } 00145 00146 void SendData() 00147 { 00148 if (!running_) 00149 { 00150 next_frame_time_ = ros::Time(0); 00151 ros::Duration(0.01).sleep(); 00152 return; 00153 } 00154 00155 if (width_ != imager_registers_[0x04]) 00156 { 00157 ROS_ERROR("Width mismatch %i reg: %i", width_, imager_registers_[0x04]); 00158 ros::Duration(0.01).sleep(); 00159 return; 00160 } 00161 00162 if (height_ != imager_registers_[0x03]) 00163 { 00164 ROS_ERROR("Height mismatch %i reg: %i", height_, imager_registers_[0x03]); 00165 ros::Duration(0.01).sleep(); 00166 return; 00167 } 00168 00169 ros::Duration sleeptime = (next_frame_time_ - ros::Time::now()); 00170 ros::Duration period = ros::Duration(((imager_registers_[0x03] + imager_registers_[0x06]) * (imager_registers_[0x04] + imager_registers_[0x05]) + 4) / 16e6); 00171 00172 if (sleeptime < -period) 00173 { 00174 if (next_frame_time_ != ros::Time(0)) 00175 ROS_WARN("Simulator lost lock on frame #%i", frame_); 00176 next_frame_time_ = ros::Time::now(); 00177 } 00178 else 00179 sleeptime.sleep(); 00180 next_frame_time_ += period; 00181 00182 PacketVideoLine pvl; 00183 PacketEOF peof; 00184 00185 peof.header.frame_number = pvl.header.frame_number = htonl(frame_); 00186 peof.header.horiz_resolution = pvl.header.horiz_resolution = htons(width_); 00187 peof.header.vert_resolution = pvl.header.vert_resolution = htons(height_); 00188 00189 for (int y = 0; y < height_; y++) 00190 { 00191 if ((imager_registers_[0x7F] & 0x3C00) == 0x3800) 00192 { 00193 if (width_ > 320) 00194 for (int x = 0; x < width_; x++) 00195 pvl.data[x] = get_diag_test_pattern(x, y); 00196 else 00197 for (int x = 0; x < width_; x++) 00198 pvl.data[x] = (get_diag_test_pattern(2 * x, 2 * y) + get_diag_test_pattern(2 * x, 2 * y + 1)) / 2; 00199 } 00200 else 00201 { 00202 for (int x = 0; x < width_; x++) 00203 pvl.data[x] = x + y + frame_; 00204 } 00205 00206 pvl.header.line_number = htons(y | (frame_ << 10)); 00207 sendto(socket_, &pvl, sizeof(pvl.header) + width_, 0, 00208 (struct sockaddr *) &data_addr_, sizeof(data_addr_)); 00209 if (y == 0) 00210 { 00211 sched_yield(); // Make sure that first packet arrives with low jitter 00212 ROS_INFO("Sending frame #%i", frame_); 00213 fflush(stdout); 00214 } 00215 } 00216 00217 peof.header.line_number = htons(IMAGER_LINENO_EOF); 00218 peof.i2c_valid = 0; 00219 peof.i2c[0] = 0; 00220 sendto(socket_, &peof, sizeof(peof), 0, 00221 (struct sockaddr *) &data_addr_, sizeof(data_addr_)); 00222 00223 frame_ = (frame_ + 1) & 0xFFFF; 00224 } 00225 00226 void ProcessCommands() 00227 { 00228 unsigned char buff[100]; 00229 00230 while (true) 00231 { 00232 ssize_t len = recv(socket_, buff, 100, MSG_DONTWAIT); 00233 if (len == -1) 00234 break; 00235 00236 PacketGeneric *hdr = (PacketGeneric *) buff; 00237 00238 if (len == 1 && buff[0] == 0xFF) 00239 continue; // This is the magic ping packet, just ignore it. 00240 00241 if (ntohl(hdr->magic_no) != WG_MAGIC_NO || 00242 ntohl(hdr->type) > PKT_MAX_ID) 00243 { 00244 ROS_INFO("Got a packet with a bad magic number or type."); \ 00245 continue; 00246 } 00247 00248 #define CAST_AND_CHK(type) \ 00249 if (len != sizeof(type)) \ 00250 { \ 00251 ROS_INFO("Got a "#type" with incorrect length"); \ 00252 continue;\ 00253 } \ 00254 if (false) ROS_INFO("Got a "#type""); \ 00255 type *pkt = (type *) buff; 00256 // End of this horrid macro that makes pkt appear by magic. 00257 00258 switch (ntohl(hdr->type)) 00259 { 00260 case PKTT_DISCOVER: 00261 { 00262 CAST_AND_CHK(PacketDiscover); 00263 sendAnnounce(&pkt->hdr); 00264 break; 00265 } 00266 00267 case PKTT_CONFIGURE: 00268 { 00269 CAST_AND_CHK(PacketConfigure); 00270 if (pkt->product_id != htonl(CONFIG_PRODUCT_ID) || 00271 pkt->ser_no != htonl(serial_no_)) 00272 break; 00273 running_ = false; 00274 sendAnnounce(&pkt->hdr); 00275 break; 00276 } 00277 00278 case PKTT_TRIGCTRL: 00279 { 00280 CAST_AND_CHK(PacketTrigControl); 00281 unsigned int new_mode = htons(pkt->trig_state); 00282 if (new_mode == 0 && !running_) 00283 sendStatus(&pkt->hdr, PKT_STATUST_OK, 0); 00284 else 00285 { 00286 ROS_ERROR("Tried to set to trigger mode %i.", new_mode); 00287 sendStatus(&pkt->hdr, PKT_STATUST_ERROR, PKT_ERROR_INVALID); 00288 } 00289 break; 00290 } 00291 00292 case PKTT_IMGRMODE: 00293 { 00294 CAST_AND_CHK(PacketImagerMode); 00295 uint32_t mode = htonl(pkt->mode); 00296 if (mode >= 10 || running_) 00297 { 00298 sendStatus(&pkt->hdr, PKT_STATUST_ERROR, PKT_ERROR_INVALID); 00299 break; 00300 } 00301 //double fps[10] = { 15,12.5, 30, 25, 15,12.5, 60, 50, 30, 25 }; 00302 //int widths[10] = { 752, 752, 640, 640, 640, 640, 320, 320, 320, 320 }; 00303 //int heights[10] ={ 480, 480, 480, 480, 480, 480, 240, 240, 240, 240 }; 00304 //period_ = ros::Duration(1/fps[mode]); 00305 width_ = MT9VModes[mode].width; 00306 height_ = MT9VModes[mode].height; 00307 imager_registers_[0x03] = height_; 00308 imager_registers_[0x04] = width_; 00309 imager_registers_[0x05] = MT9VModes[mode].hblank; 00310 imager_registers_[0x06] = MT9VModes[mode].vblank; 00311 sendStatus(&pkt->hdr, PKT_STATUST_OK, 0); 00312 } 00313 break; 00314 00315 case PKTT_IMGRSETRES: 00316 { 00317 CAST_AND_CHK(PacketImagerSetRes); 00318 unsigned int new_width = htons(pkt->horizontal); 00319 unsigned int new_height = htons(pkt->vertical); 00320 if (new_width > 752 || new_height > 640) 00321 { 00322 ROS_ERROR("Tried to set resolution to out of range %ix%i", new_width, new_height); 00323 sendStatus(&pkt->hdr, PKT_STATUST_ERROR, PKT_ERROR_INVALID); 00324 break; 00325 } 00326 //period_ = ros::Duration(1/10); // @todo fix this. 00327 width_ = new_width; 00328 height_ = new_height; 00329 sendStatus(&pkt->hdr, PKT_STATUST_OK, 0); 00330 } 00331 break; 00332 00333 case PKTT_VIDSTART: 00334 { 00335 CAST_AND_CHK(PacketVidStart); 00336 if (running_) 00337 sendStatus(&pkt->hdr, PKT_STATUST_ERROR, PKT_ERROR_INVALID); 00338 else 00339 { 00340 sendStatus(&pkt->hdr, PKT_STATUST_OK, 0); 00341 bzero(&data_addr_, sizeof(data_addr_)); 00342 data_addr_.sin_family = AF_INET; 00343 data_addr_.sin_addr.s_addr = pkt->receiver.addr; 00344 data_addr_.sin_port = pkt->receiver.port; 00345 } 00346 running_ = true; 00347 } 00348 break; 00349 00350 case PKTT_VIDSTOP: 00351 { 00352 CAST_AND_CHK(PacketVidStop); 00353 if (running_) 00354 sendStatus(&pkt->hdr, PKT_STATUST_OK, 0); 00355 else 00356 sendStatus(&pkt->hdr, PKT_STATUST_ERROR, PKT_ERROR_INVALID); 00357 running_ = false; 00358 } 00359 break; 00360 00361 case PKTT_RESET: 00362 { 00363 reset(); 00364 } 00365 break; 00366 00367 case PKTT_SENSORRD: 00368 { 00369 CAST_AND_CHK(PacketSensorRequest); 00370 if (imager_register_flags_[pkt->address] & IMAGER_REGISTER_UNDEFINED) 00371 ROS_WARN("Reading uninitialized imager register 0x%02X.", pkt->address); 00372 if (imager_register_flags_[pkt->address] & IMAGER_REGISTER_UNSUPPORTED) 00373 ROS_WARN("Reading unsupported imager register 0x%02X.", pkt->address); 00374 sendSensorData(&pkt->hdr, pkt->address, imager_registers_[pkt->address]); 00375 } 00376 break; 00377 00378 case PKTT_SENSORWR: 00379 { 00380 CAST_AND_CHK(PacketSensorData); 00381 if (imager_register_flags_[pkt->address] & IMAGER_REGISTER_UNSUPPORTED) 00382 ROS_ERROR("Writing unsupported imager register 0x%02X.", pkt->address); 00383 imager_register_flags_[pkt->address] &= ~IMAGER_REGISTER_UNDEFINED; 00384 imager_registers_[pkt->address] = ntohs(pkt->data); 00385 sendStatus(&pkt->hdr, PKT_STATUST_OK, 0); 00386 } 00387 break; 00388 00389 case PKTT_FLASHREAD: 00390 { 00391 CAST_AND_CHK(PacketFlashRequest); 00392 sendFlashData(&pkt->hdr, pkt->address); 00393 } 00394 break; 00395 00396 default: 00397 ROS_ERROR("Got an unknown message type: %i", ntohl(hdr->type)); 00398 break; 00399 } 00400 #undef CAST_AND_CHK 00401 } 00402 } 00403 00404 #define FILL_HDR(pkttype, pktid) \ 00405 if (false) ROS_INFO("Sending a "#pkttype" packet."); \ 00406 Packet##pkttype rsp; \ 00407 rsp.hdr.magic_no = htonl(WG_MAGIC_NO); \ 00408 strncpy(rsp.hdr.hrt, #pkttype, sizeof(rsp.hdr.hrt)); \ 00409 rsp.hdr.type = htonl(pktid); 00410 // End of this horrid macro that makes resp appear by magic. 00411 00412 #define SEND_RSP \ 00413 sockaddr_in rsp_addr; \ 00414 bzero(&rsp_addr, sizeof(rsp_addr)); \ 00415 rsp_addr.sin_family = AF_INET; \ 00416 rsp_addr.sin_addr.s_addr = hdr->reply_to.addr; \ 00417 rsp_addr.sin_port = hdr->reply_to.port; \ 00418 sendto(socket_, &rsp, sizeof(rsp), 0, \ 00419 (struct sockaddr *) &rsp_addr, sizeof(rsp_addr)); 00420 00421 void sendAnnounce(PacketGeneric *hdr) 00422 { 00423 FILL_HDR(Announce, PKTT_ANNOUNCE); 00424 bzero(rsp.mac, sizeof(rsp.mac)); 00425 rsp.product_id = htonl(CONFIG_PRODUCT_ID); 00426 rsp.ser_no = htonl(serial_no_); 00427 strncpy(rsp.product_name, "WGE100_camera_simulator.", sizeof(rsp.product_name)); 00428 rsp.hw_version = htonl(0x2041); 00429 rsp.fw_version = htonl(0x0112); 00430 strncpy(rsp.camera_name, "WGE100_camera_simulator.", sizeof(rsp.camera_name)); 00431 SEND_RSP; 00432 } 00433 00434 void sendStatus(PacketGeneric *hdr, uint32_t type, uint32_t code) 00435 { 00436 if (type != PKT_STATUST_OK) 00437 ROS_ERROR("Error Condition."); 00438 FILL_HDR(Status, PKTT_STATUS); 00439 rsp.status_type = htonl(type); 00440 rsp.status_code = htonl(code); 00441 SEND_RSP; 00442 } 00443 00444 void sendFlashData(PacketGeneric *hdr, uint32_t address) 00445 { 00446 FILL_HDR(FlashPayload, PKTT_FLASHDATA); 00447 rsp.address = address; 00448 bzero(rsp.data, sizeof(rsp.data)); 00449 SEND_RSP; 00450 } 00451 00452 void sendSensorData(PacketGeneric *hdr, uint8_t addr, uint16_t value) 00453 { 00454 FILL_HDR(SensorData, PKTT_SENSORDATA); 00455 rsp.address = addr; 00456 rsp.data = htons(value); 00457 SEND_RSP; 00458 } 00459 00460 #undef FILL_HDR 00461 #undef SEND_RSP 00462 volatile static bool exiting_; 00463 00464 static void setExiting(int i) 00465 { 00466 exiting_ = true; 00467 } 00468 }; 00469 00470 volatile bool WGE100Simulator::exiting_ = false; 00471 00472 int main(int argc, char **argv) 00473 { 00474 ros::Time::init(); 00475 WGE100Simulator wge100sim(12345); 00476 return wge100sim.run(); 00477 } 00478