Now you can download a copy of these docs so you can use them offline! Download now
009/AxisCamera.cpp
1 
2 /********************************************************************************
3 * Project : FIRST Motor Controller
4 * File Name : AxisCamera.cpp
5 * Contributors : TD, ELF, JDG, SVK
6 * Creation Date : July 29, 2008
7 * Revision History : Source code & revision history maintained at sourceforge.WPI.edu
8 * File Description : Axis camera access for the FIRST Vision API
9 * The camera task runs as an independent thread
10 */
11 /*----------------------------------------------------------------------------*/
12 /* Copyright (c) FIRST 2008. All Rights Reserved. */
13 /* Open Source Software - may be modified and shared by FRC teams. The code */
14 /* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */
15 /*----------------------------------------------------------------------------*/
16 
17 
18 #include "sockLib.h"
19 #include "vxWorks.h"
20 
21 #include "errno.h"
22 #include "fioLib.h"
23 #include "hostLib.h"
24 #include "inetLib.h"
25 #include "signal.h"
26 #include "sigLib.h" // for signal
27 #include <string>
28 #include "time.h"
29 #include "usrLib.h"
30 
31 #include "AxisCamera.h"
32 #include "BaeUtilities.h"
33 #include "FrcError.h"
34 #include "Task.h"
35 #include "Timer.h"
36 #include "VisionAPI.h"
37 
38 #include <cstring>
39 #include <cstdio>
40 
42 #define DEFAULT_PACKET_SIZE 512
43 
45 IMAQ_FUNC int Priv_ReadJPEGString_C(Image* _image, const unsigned char* _string, uint32_t _stringLength);
46 
47 // To locally enable debug printing: set AxisCamera_debugFlag to a 1, to disable set to 0
48 int AxisCamera_debugFlag = 0;
49 #define DPRINTF if(AxisCamera_debugFlag)dprintf
50 
52 struct {
53  int readerPID; // Set to taskID for signaling
54  int index; /* -1,0,1 */
55  int acquire; /* 0:STOP CAMERA; 1:START CAMERA */
56  int cameraReady; /* 0: CAMERA NOT INITIALIZED; 1: CAMERA INITIALIZED */
57  int decode; /* 0:disable decoding; 1:enable decoding to HSL Image */
58  struct {
59  //
60  // To find the latest image timestamp, access:
61  // globalCamera.data[globalCamera.index].timestamp
62  //
63  double timestamp; // when image was taken
64  char* cameraImage; // jpeg image string
65  int cameraImageSize; // image size
66  Image* decodedImage; // image decoded to NI Image object
67  int decodedImageSize; // size of decoded image
68  }data[2];
69  int cameraMetrics[CAM_NUM_METRICS];
70 }globalCamera;
71 
72 /* run flag */
73 static short cont = 0;
74 
85 int GetImageBlocking(Image* image, double *timestamp, double lastImageTimestamp)
86 {
87  char funcName[]="GetImageBlocking";
88  int success;
89  double startTime = GetTime();
90 
91  while (1)
92  {
93  success = GetImage(image, timestamp);
94  if (!success) return (success);
95 
96  if (*timestamp > lastImageTimestamp)
97  return (1); // GOOD IMAGE RETURNED
98 
99  if (GetTime() > (startTime + MAX_BLOCKING_TIME_SEC))
100  {
101  imaqSetError(ERR_CAMERA_BLOCKING_TIMEOUT, funcName);
102  globalCamera.cameraMetrics[CAM_BLOCKING_TIMEOUT]++;
103  return (0); // NO IMAGE AVAILABLE WITHIN specified time
104  }
105  globalCamera.cameraMetrics[CAM_BLOCKING_COUNT]++;
106  taskDelay (1);
107  }
108 }
109 
114 int CameraInitialized()
115 {
116  char funcName[]="CameraInitialized";
117  int success = 0;
118  /* check to see if camera is initialized */
119  if (!globalCamera.cameraReady) {
120  imaqSetError(ERR_CAMERA_NOT_INITIALIZED, funcName);
121  DPRINTF (LOG_DEBUG, "Camera request before camera is initialized");
122  globalCamera.cameraMetrics[CAM_GETIMAGE_BEFORE_INIT]++;
123  globalCamera.cameraMetrics[CAM_GETIMAGE_FAILURE]++;
124  return success;
125  }
126 
127  if (globalCamera.index == -1){
128  imaqSetError(ERR_CAMERA_NO_BUFFER_AVAILABLE, funcName);
129  DPRINTF (LOG_DEBUG, "No camera image available");
130  globalCamera.cameraMetrics[CAM_GETIMAGE_BEFORE_AVAILABLE]++;
131  globalCamera.cameraMetrics[CAM_GETIMAGE_FAILURE]++;
132  return success;
133  }
134  return 1;
135 }
136 
145 int GetImage(Image* image, double *timestamp)
146 {
147  char funcName[]="GetImage";
148  int success = 0;
149  int readIndex;
150  int readCount = 10;
151  double currentTime = time(NULL);
152  double currentImageTimestamp;
153 
154  /* check to see if camera is initialized */
155 
156  if (!CameraInitialized()) {return success;}
157 
158  /* try readCount times to get an image */
159  while (readCount) {
160  readIndex = globalCamera.index;
161  if (!imaqDuplicate(image, globalCamera.data[readIndex].decodedImage)) {
162  int errorCode = GetLastVisionError();
163  DPRINTF (LOG_DEBUG,"Error duplicating image= %i %s ", errorCode, GetVisionErrorText(errorCode));
164  }
165  // save the timestamp to check before returning
166  currentImageTimestamp = globalCamera.data[readIndex].timestamp;
167 
168  // make sure this buffer is not being written to now
169  if (readIndex == globalCamera.index) break;
170  readCount--;
171  }
172 
173  /* were we successful ? */
174  if (readCount){
175  success = 1;
176  if (timestamp != NULL)
177  *timestamp = currentImageTimestamp; // Return image timestamp
178  } else{
179  globalCamera.cameraMetrics[CAM_GETIMAGE_FAILURE]++;
180  }
181 
182  /* Ensure the buffered image is not too old - set this "stale time" above */
183  if (currentTime > globalCamera.data[globalCamera.index].timestamp + CAMERA_IMAGE_STALE_TIME_SEC){
184  DPRINTF (LOG_CRITICAL, "STALE camera image (THIS COULD BE A BAD IMAGE)");
185  imaqSetError(ERR_CAMERA_STALE_IMAGE, funcName);
186  globalCamera.cameraMetrics[CAM_STALE_IMAGE]++;
187  globalCamera.cameraMetrics[CAM_GETIMAGE_FAILURE]++;
188  success = 0;
189  }
190  globalCamera.cameraMetrics[CAM_GETIMAGE_SUCCESS]++;
191  return success;
192 }
193 
201 int GetImageData(char** imageData, int* numBytes, double* currentImageTimestamp)
202 {
203  int success = 0;
204  int readIndex;
205  int readCount = 10;
206  int cameraImageSize;
207  char *cameraImageString;
208 
209  /* check to see if camera is initialized */
210 
211  if (!CameraInitialized()) {return success;}
212 
213  /* try readCount times to get an image */
214  while (readCount) {
215  readIndex = globalCamera.index;
216  cameraImageSize = globalCamera.data[readIndex].cameraImageSize;
217  //cameraImageString = (Image *) malloc(cameraImageSize);
218  cameraImageString = new char[cameraImageSize];
219  if (NULL == cameraImageString) {
220  DPRINTF (LOG_DEBUG, "Unable to allocate cameraImage");
221  globalCamera.cameraMetrics[CAM_GETIMAGE_FAILURE]++;
222  return success;
223  }
224  memcpy (cameraImageString, globalCamera.data[readIndex].cameraImage, cameraImageSize);
225  *currentImageTimestamp = globalCamera.data[readIndex].timestamp;
226  // make sure this buffer is not being written to now
227  if (readIndex == globalCamera.index) break;
228  free (cameraImageString);
229  readCount--;
230  }
231  if (readCount){
232  *imageData = cameraImageString;
233  *numBytes = cameraImageSize;
234  return 1;
235  }
236  return (OK);
237 }
238 
249 int GetImageDataBlocking(char** imageData, int* numBytes, double* timestamp, double lastImageTimestamp)
250 {
251 
252  char funcName[]="GetImageDataBlocking";
253  int success;
254  double startTime = GetTime();
255 
256  *imageData = NULL;
257  while (1)
258  {
259  success = GetImageData(imageData, numBytes, timestamp);
260  if (!success) return (success);
261 
262  if (*timestamp > lastImageTimestamp)
263  return (1); // GOOD IMAGE DATA RETURNED
264 
265  delete *imageData;
266  *imageData = NULL;
267 
268  if (GetTime() > (startTime + MAX_BLOCKING_TIME_SEC))
269  {
270  imaqSetError(ERR_CAMERA_BLOCKING_TIMEOUT, funcName);
271  return (0); // NO IMAGE AVAILABLE WITHIN specified time
272  }
273  globalCamera.cameraMetrics[CAM_BLOCKING_COUNT]++;
274  taskDelay (1);
275  }
276 }
277 
283 int GetCameraMetric(FrcvCameraMetric metric)
284 { return globalCamera.cameraMetrics[metric]; }
285 
292 int CameraCloseSocket(const char *errstring, int socket)
293 {
294  DPRINTF (LOG_CRITICAL, "Closing socket - CAMERA ERROR: %s", errstring );
295  close (socket);
296  return (ERROR);
297 }
298 
299 
310 static int CameraReadLine(int camSock, char* buffer, int bufSize, bool stripLineEnding) {
311  char funcName[]="CameraReadLine";
312  // Need at least 3 bytes in the buffer to pull this off.
313  if (bufSize < 3) {
314  imaqSetError(ERR_CAMERA_FAILURE, funcName);
315  return 0;
316  }
317  // Reduce size by 1 to allow for null terminator.
318  --bufSize;
319  // Read upto bufSize characters.
320  for (int i=0;i < bufSize;++i, ++buffer) {
321  // Read one character.
322  if (read (camSock, buffer, 1) <= 0) {
323  imaqSetError(ERR_CAMERA_FAILURE, funcName);
324  return 0;
325  }
326  // Line endings can be "\r\n" or just "\n". So always
327  // look for a "\n". If you got just a "\n" and
328  // stripLineEnding is false, then convert it into a \r\n
329  // because callers expect a \r\n.
330  // If the combination of the previous character and the current character
331  // is "\r\n", the line ending
332  if (*buffer=='\n') {
333  // If asked to strip the line ending, then set the buffer to the previous
334  // character.
335  if (stripLineEnding) {
336  if (i > 0 && *(buffer-1)=='\r') {
337  --buffer;
338  }
339  }
340  else {
341  // If the previous character was not a '\r',
342  if (i == 0 || *(buffer-1)!='\r') {
343  // Make the current character a '\r'.
344  *buffer = '\r';
345  // If space permits, add back the '\n'.
346  if (i < bufSize-1) {
347  ++buffer;
348  *buffer = '\n';
349  }
350  }
351  // Set the buffer past the current character ('\n')
352  ++buffer;
353  }
354  break;
355  }
356  }
357  // Null terminate.
358  *buffer = '\0';
359  return 1;
360 }
361 
368 static int CameraSkipUntilEmptyLine(int camSock) {
369  char buffer[1024];
370  int success = 0;
371  while(1) {
372  success = CameraReadLine(camSock, buffer, sizeof(buffer), true);
373  if (*buffer == '\0') {
374  return success;
375  }
376  }
377  return success;
378 }
379 
395 static int CameraOpenSocketAndIssueAuthorizedRequest(const char* serverName, const char* request)
396 {
397  char funcName[]="cameraOpenSocketAndIssueAuthorizedRequest";
398 
399  struct sockaddr_in cameraAddr;
400  int sockAddrSize;
401  int camSock = ERROR;
402 
403  // The camera is expected to have one of the following username, password combinations.
404  // This routine will return an error if it does not find one of these.
405  static const char* authenticationStrings[] = {
406  "RlJDOkZSQw==", /* FRC, FRC */
407  "cm9vdDpwYXNz", /* root, admin*/
408  "cm9vdDphZG1pbg==" /* root, pass*/
409  };
410 
411  static const int numAuthenticationStrings = sizeof(authenticationStrings)/sizeof(authenticationStrings[0]);
412 
413  static const char *requestTemplate = "%s " \
414  "HTTP/1.1\n" \
415  "User-Agent: HTTPStreamClient\n" \
416  "Connection: Keep-Alive\n" \
417  "Cache-Control: no-cache\n" \
418  "Authorization: Basic %s\n\n";
419 
420  int i = 0;
421  for (;i < numAuthenticationStrings;++i) {
422  char buffer[1024];
423 
424  sprintf(buffer, requestTemplate, request, authenticationStrings[i]);
425 
426  /* create camera socket */
427  //DPRINTF (LOG_DEBUG, "creating camSock" );
428  if ((camSock = socket (AF_INET, SOCK_STREAM, 0)) == ERROR) {
429  imaqSetError(ERR_CAMERA_SOCKET_CREATE_FAILED, funcName);
430  perror("Failed to create socket");
431  return (ERROR);
432  }
433 
434  sockAddrSize = sizeof (struct sockaddr_in);
435  bzero ((char *) &cameraAddr, sockAddrSize);
436  cameraAddr.sin_family = AF_INET;
437  cameraAddr.sin_len = (u_char) sockAddrSize;
438  cameraAddr.sin_port = htons (CAMERA_PORT);
439 
440  if (( (int)(cameraAddr.sin_addr.s_addr = inet_addr (const_cast<char*>(serverName)) ) == ERROR) &&
441  ( (int)(cameraAddr.sin_addr.s_addr = hostGetByName (const_cast<char*>(serverName)) ) == ERROR))
442  {
443  imaqSetError(ERR_CAMERA_CONNECT_FAILED, funcName);
444  return CameraCloseSocket("Failed to get IP, check hostname or IP", camSock);
445  }
446 
447  //DPRINTF (LOG_INFO, "connecting camSock" );
448  if (connect (camSock, (struct sockaddr *) &cameraAddr, sockAddrSize) == ERROR) {
449  imaqSetError(ERR_CAMERA_CONNECT_FAILED, funcName);
450  return CameraCloseSocket("Failed to connect to camera - check networ", camSock);
451  }
452 
453  //DPRINTF (LOG_DEBUG, "writing GET request to camSock" );
454  if (write (camSock, buffer, strlen(buffer) ) == ERROR) {
455  imaqSetError(ERR_CAMERA_CONNECT_FAILED, funcName);
456  return CameraCloseSocket("Failed to send GET request", camSock);
457  }
458 
459  // Read one line with the line ending removed.
460  if (!CameraReadLine(camSock, buffer, 1024, true)) {
461  return CameraCloseSocket("Bad response to GET request", camSock);
462  }
463 
464  // Check if the response is of the format HTTP/<version> 200 OK.
465  float discard;
466  if (sscanf(buffer, "HTTP/%f 200 OK", &discard) == 1) {
467  break;
468  }
469 
470  // We have to close the connection because in the case of failure
471  // the server closes the connection.
472  close(camSock);
473  }
474  // If none of the attempts were successful, then let the caller know.
475  if (numAuthenticationStrings == i) {
476  imaqSetError(ERR_CAMERA_AUTHORIZATION_FAILED, funcName);
477  fprintf(stderr, "Expected username/password combination not found on camera");
478  return ERROR;
479  }
480  return camSock;
481 }
482 
483 
489 int ConfigureCamera(char *configString){
490  char funcName[]="ConfigureCamera";
491  const char *serverName = "192.168.0.90"; /* camera @ */
492  int success = 0;
493  int camSock = 0;
494 
495  /* Generate camera configuration string */
496  const char * getStr1 =
497  "GET /axis-cgi/admin/param.cgi?action=update&ImageSource.I0.Sensor.";
498 
499  char cameraRequest[strlen(getStr1) + strlen(configString)];
500  sprintf (cameraRequest, "%s%s", getStr1, configString);
501  DPRINTF(LOG_DEBUG, "camera configuration string: \n%s", cameraRequest);
502  camSock = CameraOpenSocketAndIssueAuthorizedRequest(serverName, cameraRequest);
503  DPRINTF(LOG_DEBUG, "camera socket# = %i", camSock);
504 
505  //read response
506  success = CameraSkipUntilEmptyLine(camSock);
507  //DPRINTF(LOG_DEBUG, "succcess from CameraSkipUntilEmptyLine: %i", success);
508  char buffer[3]; // set property - 3
509  success = CameraReadLine(camSock, buffer, 3, true);
510  //DPRINTF(LOG_DEBUG, "succcess from CameraReadLine: %i", success);
511  DPRINTF(LOG_DEBUG, "line read from camera \n%s", buffer);
512  if (strcmp(buffer, "OK") != 0) {
513  imaqSetError(ERR_CAMERA_COMMAND_FAILURE, funcName);
514  DPRINTF(LOG_DEBUG, "setting ERR_CAMERA_COMMAND_FAILURE - OK not found");
515  }
516  DPRINTF (LOG_INFO, "\nConfigureCamera ENDING success = %i\n", success );
517 
518  /* clean up */
519  close (camSock);
520  return (1);
521 }
522 
523 
530 int GetCameraSetting(char *configString, char *cameraResponse){
531  const char *serverName = "192.168.0.90"; /* camera @ */
532  int success = 0;
533  int camSock = 0;
534 
535  /* Generate camera request string */
536  const char * getStr1 =
537  "GET /axis-cgi/admin/param.cgi?action=list&group=ImageSource.I0.Sensor.";
538  char cameraRequest[strlen(getStr1) + strlen(configString)];
539  sprintf (cameraRequest, "%s%s", getStr1, configString);
540  DPRINTF(LOG_DEBUG, "camera configuration string: \n%s", cameraRequest);
541  camSock = CameraOpenSocketAndIssueAuthorizedRequest(serverName, cameraRequest);
542  DPRINTF(LOG_DEBUG, "return from CameraOpenSocketAndIssueAuthorizedRequest %i", camSock);
543 
544  //read response
545  success = CameraSkipUntilEmptyLine(camSock);
546  success = CameraReadLine(camSock, cameraResponse, 1024, true);
547  DPRINTF(LOG_DEBUG, "succcess from CameraReadLine: %i", success);
548  DPRINTF(LOG_DEBUG, "line read from camera \n%s", cameraResponse);
549  DPRINTF (LOG_INFO, "\nGetCameraSetting ENDING success = %i\n", success );
550 
551  /* clean up */
552  close (camSock);
553  return (1);
554 }
555 
563 int GetImageSetting(char *configString, char *cameraResponse){
564  const char *serverName = "192.168.0.90"; /* camera @ */
565  int success = 0;
566  int camSock = 0;
567 
568  /* Generate camera request string */
569  const char *getStr1 = "GET /axis-cgi/admin/param.cgi?action=list&group=Image.I0.Appearance.";
570  char cameraRequest[strlen(getStr1) + strlen(configString)];
571  sprintf (cameraRequest, "%s%s", getStr1, configString);
572  DPRINTF(LOG_DEBUG, "camera configuration string: \n%s", cameraRequest);
573  camSock = CameraOpenSocketAndIssueAuthorizedRequest(serverName, cameraRequest);
574  DPRINTF(LOG_DEBUG, "return from CameraOpenSocketAndIssueAuthorizedRequest %i", camSock);
575 
576  //read response
577  success = CameraSkipUntilEmptyLine(camSock);
578  success = CameraReadLine(camSock, cameraResponse, 1024, true);
579  DPRINTF(LOG_DEBUG, "succcess from CameraReadLine: %i", success);
580  DPRINTF(LOG_DEBUG, "line read from camera \n%s", cameraResponse);
581  DPRINTF (LOG_INFO, "\nGetCameraSetting ENDING success = %i\n", success );
582 
583  /* clean up */
584  close (camSock);
585  return (1);
586 }
587 
588 
589 #define MEASURE_SOCKET_TIME 1
590 
599 int cameraJPEGServer(int frames, int compression, ImageResolution resolution, ImageRotation rotation)
600 {
601  char funcName[]="cameraJPEGServer";
602  char serverName[] = "192.168.0.90"; /* camera @ */
603  cont = 1;
604  int errorCode = 0;
605  int printCounter = 0;
606  int writeIndex;
607  int authorizeCount = 0;
608  int authorizeConfirmed = 0;
609  static const int authenticationStringsCount = 3;
610  static const char* authenticationStrings[] = {
611  "cm9vdDphZG1pbg==", /* root, admin*/
612  "RlJDOkZSQw==", /* FRC, FRC */
613  "cm9vdDpwYXNz==" /* root, pass*/
614  };
615 
616  DPRINTF (LOG_DEBUG, "cameraJPEGServer" );
617 
618  struct sockaddr_in cameraAddr;
619  int sockAddrSize;
620  int camSock = 0;
621 
622  char resStr[10];
623  switch (resolution) {
624  case k640x480: { sprintf(resStr,"640x480"); break; }
625  case k320x240: { sprintf(resStr,"320x240"); break; }
626  case k160x120: { sprintf(resStr,"160x120"); break; }
627  default: {DPRINTF (LOG_DEBUG, "code error - resolution input" ); break; }
628  }
629 
630  /* Generate camera initialization string */
631  /* changed resolution to 160x120 from 320x240 */
632  /* supported resolutions are: 640x480, 640x360, 320x240, 160x120 */
633  const char * getStr1 =
634  "GET /axis-cgi/mjpg/video.cgi?showlength=1&camera=1&";
635 
636  char insertStr[100];
637  sprintf (insertStr, "des_fps=%i&compression=%i&resolution=%s&rotation=%i",
638  frames, compression, resStr, (int)rotation);
639 
640  const char * getStr2 = " HTTP/1.1\n\
641 User-Agent: HTTPStreamClient\n\
642 Host: 192.150.1.100\n\
643 Connection: Keep-Alive\n\
644 Cache-Control: no-cache\n\
645 Authorization: Basic %s;\n\n";
646 
647  char getStr[strlen(getStr1) + strlen(insertStr) + strlen(getStr2)];
648  sprintf (getStr, "%s:%s%s", getStr1, insertStr, getStr2);
649 
650  DPRINTF(LOG_DEBUG, "revised camera string: \n%s", getStr);
651  /* Allocation */
652  char tempBuffer[1024];
653 
654  RETRY:
655  Wait(0.1); //bug fix - don't pester camera if it's booting
656  while (globalCamera.acquire == 0) Wait(0.1);
657 
658  if (!authorizeConfirmed){
659  if (authorizeCount < authenticationStringsCount){
660  sprintf (tempBuffer, getStr, authenticationStrings[authorizeCount]);
661  } else {
662  imaqSetError(ERR_CAMERA_AUTHORIZATION_FAILED, funcName);
663  fprintf(stderr, "Camera authorization failed ... Incorrect password on camera!!");
664  return (ERROR);
665  }
666  }
667 
668  while (1)
669  {
670  globalCamera.cameraMetrics[CAM_SOCKET_INIT_ATTEMPTS]++;
671 
672  /* create camera socket */
673  DPRINTF (LOG_DEBUG, "creating camSock" );
674  if ((camSock = socket (AF_INET, SOCK_STREAM, 0)) == ERROR) {
675  imaqSetError(ERR_CAMERA_SOCKET_CREATE_FAILED, funcName);
676  perror("Failed to create socket");
677  cont = 0;
678  return (ERROR);
679  }
680 
681  sockAddrSize = sizeof (struct sockaddr_in);
682  bzero ((char *) &cameraAddr, sockAddrSize);
683  cameraAddr.sin_family = AF_INET;
684  cameraAddr.sin_len = (u_char) sockAddrSize;
685  cameraAddr.sin_port = htons (CAMERA_PORT);
686 
687  DPRINTF (LOG_DEBUG, "getting IP" );
688  if (( (int)(cameraAddr.sin_addr.s_addr = inet_addr (serverName) ) == ERROR) &&
689  ( (int)(cameraAddr.sin_addr.s_addr = hostGetByName (serverName) ) == ERROR))
690  {
691  CameraCloseSocket("Failed to get IP, check hostname or IP", camSock);
692  continue;
693  }
694 
695  DPRINTF (LOG_INFO, "Attempting to connect to camSock" );
696  if (connect (camSock, (struct sockaddr *) &cameraAddr, sockAddrSize) == ERROR) {
697  imaqSetError(ERR_CAMERA_CONNECT_FAILED, funcName);
698  CameraCloseSocket("Failed to connect to camera - check network", camSock);
699  continue;
700  }
701 
702 #if MEASURE_SOCKET_SETUP
703  socketEndTime = GetTime();
704  setupTime = socketEndTime - socketStartTime;
705  printf("\n***socket setup time = %g\n", setupTime );
706 #endif
707 
708  globalCamera.cameraMetrics[CAM_SOCKET_OPEN]++;
709  break;
710  } // end while (trying to connect to camera)
711 
712  DPRINTF (LOG_DEBUG, "writing GET request to camSock" );
713  if (write (camSock, tempBuffer , strlen(tempBuffer) ) == ERROR) {
714  return CameraCloseSocket("Failed to send GET request", camSock);
715  }
716 
717  //DPRINTF (LOG_DEBUG, "reading header" );
718  /* Find content-length, then read that many bytes */
719  int counter = 2;
720  const char* contentString = "Content-Length: ";
721  const char* authorizeString = "200 OK";
722 
723 #define MEASURE_TIME 0
724 #if MEASURE_TIME
725  //timing parameters - only measure one at the time
726  double loopStartTime = 0.0; // measuring speed of execution loop
727  double loopEndTime = 0.0;
728  double cameraStartTime = 0.0;
729  double cameraEndTime = 0.0;
730  double previousStartTime = 0.0;
731  int performanceLoopCounter = 0;
732  int maxCount = 30;
733 #endif
734 
735  while (cont) {
736 #if MEASURE_TIME
737  previousStartTime = loopStartTime; // first time is bogus
738  loopStartTime = GetTime();
739 #endif
740  // If camera has been turned OFF, jump to RETRY
741  //if (globalCamera.acquire == 0) goto RETRY;
742 
743  /* Determine writer index */
744  if (globalCamera.index == 0)
745  writeIndex = 1;
746  else
747  writeIndex = 0;
748 
749  /* read header */
750  //TODO: check for error in header, increment ERR_CAMERA_HEADER_ERROR
751  char initialReadBuffer[DEFAULT_PACKET_SIZE] = "";
752  char intermediateBuffer[1];
753  char *trailingPtr = initialReadBuffer;
754  int trailingCounter = 0;
755 
756 
757 #if MEASURE_TIME
758  cameraStartTime = GetTime();
759 #endif
760 
761  while (counter) {
762  if (read (camSock, intermediateBuffer, 1) <= 0) {
763  CameraCloseSocket("Failed to read image header", camSock);
764  globalCamera.cameraMetrics[ERR_CAMERA_HEADER_ERROR]++;
765  goto RETRY;
766  }
767 
768  strncat(initialReadBuffer, intermediateBuffer, 1);
769  if (NULL != strstr(trailingPtr, "\r\n\r\n")) {
770 
771  if (!authorizeConfirmed){
772 
773  if (strstr(initialReadBuffer, authorizeString))
774  {
775  authorizeConfirmed = 1;
776  /* set camera to initialized */
777  globalCamera.cameraReady = 1;
778  }
779  else
780  {
781  CameraCloseSocket("Not authorized to connect to camera", camSock);
782  authorizeCount++;
783  goto RETRY;
784  }
785  }
786  --counter;
787  }
788  if (++trailingCounter >= 4) {
789  trailingPtr++;
790  }
791  }
792 
793  counter = 1;
794  char *contentLength = strstr(initialReadBuffer, contentString);
795  if (contentLength == NULL) {
796  globalCamera.cameraMetrics[ERR_CAMERA_HEADER_ERROR]++;
797  CameraCloseSocket("No content-length token found in packet", camSock);
798  goto RETRY;
799  }
800  /* get length of image content */
801  contentLength = contentLength + strlen(contentString);
802  globalCamera.data[writeIndex].cameraImageSize = atol (contentLength);
803 
804  if(globalCamera.data[writeIndex].cameraImage)
805  free(globalCamera.data[writeIndex].cameraImage);
806  //globalCamera.data[writeIndex].cameraImage = (Image *) malloc(globalCamera.data[writeIndex].cameraImageSize);
807  globalCamera.data[writeIndex].cameraImage = (char*)malloc(globalCamera.data[writeIndex].cameraImageSize);
808  if (NULL == globalCamera.data[writeIndex].cameraImage) {
809  return CameraCloseSocket("Failed to allocate space for imageString", camSock);
810  }
811  globalCamera.cameraMetrics[CAM_BUFFERS_WRITTEN]++;
812 
813  //
814  // This is a blocking camera read function, and will block if the camera
815  // has been disconnected from the cRIO. If however the camera is
816  // POWERED OFF while connected to the cRIO, this function NEVER RETURNS
817  //
818  int bytesRead = fioRead (camSock, (char *)globalCamera.data[writeIndex].cameraImage,
819  globalCamera.data[writeIndex].cameraImageSize);
820 
821 #if MEASURE_TIME
822  cameraEndTime = GetTime();
823 #endif
824 
825  //DPRINTF (LOG_DEBUG, "Completed fioRead function - bytes read:%d", bytesRead);
826  if (bytesRead <= 0) {
827  CameraCloseSocket("Failed to read image data", camSock);
828  goto RETRY;
829  } else if (bytesRead != globalCamera.data[writeIndex].cameraImageSize){
830  fprintf(stderr, "ERROR: Failed to read entire image: readLength does not match bytes read");
831  globalCamera.cameraMetrics[CAM_BAD_IMAGE_SIZE]++;
832  }
833  // if decoding the JPEG to an HSL Image, do it here
834  if (globalCamera.decode) {
835  if(globalCamera.data[writeIndex].decodedImage)
836  frcDispose(globalCamera.data[writeIndex].decodedImage);
837  globalCamera.data[writeIndex].decodedImage = frcCreateImage(IMAQ_IMAGE_HSL);
838  if (! Priv_ReadJPEGString_C(globalCamera.data[writeIndex].decodedImage,
839  (const unsigned char *)globalCamera.data[writeIndex].cameraImage,
840  globalCamera.data[writeIndex].cameraImageSize) ) {
841  DPRINTF (LOG_DEBUG, "failure creating Image");
842  }
843  }
844 
845  // TODO: React to partial image
846  globalCamera.data[writeIndex].timestamp = GetTime();
847  globalCamera.index = writeIndex;
848 
849  /* signal a listening task */
850  if (globalCamera.readerPID) {
851  if (taskKill (globalCamera.readerPID,SIGUSR1) == OK)
852  {
853  DPRINTF (LOG_DEBUG, "SIGNALING PID= %i", globalCamera.readerPID);
854  }
855  else
856  {
857  globalCamera.cameraMetrics[CAM_PID_SIGNAL_ERR]++;
858  DPRINTF (LOG_DEBUG, "ERROR SIGNALING PID= %i", globalCamera.readerPID);
859  }
860  }
861 
862  globalCamera.cameraMetrics[CAM_NUM_IMAGE]++;
863  printCounter ++;
864  if (printCounter == 1000) {
865  DPRINTF (LOG_DEBUG, "imageCounter = %i", globalCamera.cameraMetrics[CAM_NUM_IMAGE]);
866  printCounter=0;
867  }
868 
869  taskDelay(1);
870 
871 #if MEASURE_TIME
872  loopEndTime = GetTime();
873  performanceLoopCounter++;
874  if (performanceLoopCounter <= maxCount) {
875  DPRINTF (LOG_DEBUG, "%i DONE!!!: loop = ,%g, camera = ,%g, difference = ,%g, loopRate= ,%g,",
876  performanceLoopCounter, loopEndTime-loopStartTime, cameraEndTime-cameraStartTime,
877  (loopEndTime-loopStartTime) - (cameraEndTime-cameraStartTime),
878  loopStartTime-previousStartTime);
879  }
880 #endif
881  } /* end while (cont) */
882 
883  /* clean up */
884  close (camSock);
885  cont = 0;
886  DPRINTF (LOG_INFO, "\nJPEG SERVER ENDING errorCode = %i\n", errorCode );
887 
888  return (OK);
889 }
890 
895 void StartImageSignal(int taskId) // Start issuing a SIGUSR1 signal to the specified taskId
896 { globalCamera.readerPID = taskId; }
897 
901 void StartImageAcquisition()
902 {
903  globalCamera.cameraMetrics[CAM_STARTS]++;
904  globalCamera.acquire = 1;
905  DPRINTF(LOG_DEBUG, "starting acquisition");
906 }
907 
908 
912 void StopImageAcquisition()
913 { globalCamera.cameraMetrics[CAM_STOPS]++; globalCamera.acquire = 0; }
914 
915 
925 static int initCamera(int frames, int compression, ImageResolution resolution, ImageRotation rotation)
926 {
927  //SetDebugFlag ( DEBUG_SCREEN_AND_FILE ) ;
928 
929  DPRINTF(LOG_DEBUG, "\n+++++ camera task starting: rotation = %i", (int)rotation);
930  int errorCode;
931 
932  /* Initialize globalCamera area
933  * Set decode to 1 - always want to decode images for processing
934  * If ONLY sending images to the dashboard, you could set it to 0 */
935  bzero ((char *)&globalCamera, sizeof(globalCamera));
936  globalCamera.index = -1;
937  globalCamera.decode = 1;
938 
939  /* allow writing to vxWorks target */
940  Priv_SetWriteFileAllowed(1);
941 
942  /* start acquisition immediately */
943  StartImageAcquisition();
944 
945  /* cameraJPEGServer runs until camera is stopped */
946  DPRINTF (LOG_DEBUG, "calling cameraJPEGServer" );
947  errorCode = cameraJPEGServer(frames, compression, resolution, rotation);
948  DPRINTF (LOG_INFO, "errorCode from cameraJPEGServer = %i\n", errorCode );
949  return (OK);
950 }
951 
952 Task g_axisCameraTask("Camera", (FUNCPTR)initCamera);
953 
962 int StartCameraTask()
963 {
964  return StartCameraTask(10, 0, k160x120, ROT_0);
965 }
966 int StartCameraTask(int frames, int compression, ImageResolution resolution, ImageRotation rotation)
967 {
968  char funcName[]="startCameraTask";
969  DPRINTF(LOG_DEBUG, "starting camera");
970 
971  int cameraTaskID = 0;
972 
973  //range check
974  if (frames < 1) frames = 1;
975  else if (frames > 30) frames = 30;
976  if (compression < 0) compression = 0;
977  else if (compression > 100) compression = 100;
978 
979  // stop any prior copy of running task
980  StopCameraTask();
981 
982  // spawn camera task
983  bool started = g_axisCameraTask.Start(frames, compression, resolution, rotation);
984  cameraTaskID = g_axisCameraTask.GetID();
985  DPRINTF(LOG_DEBUG, "spawned task id %i", cameraTaskID);
986 
987  if (!started) {
988  DPRINTF(LOG_DEBUG, "camera task failed to start");
989  imaqSetError(ERR_CAMERA_TASK_SPAWN_FAILED, funcName);
990  return -1;
991  }
992  return cameraTaskID;
993 }
994 
999 int StopCameraTask()
1000 {
1001  std::string taskName("FRC_Camera");
1002  // check for prior copy of running task
1003  int oldTaskID = taskNameToId(const_cast<char*>(taskName.c_str()));
1004  if(oldTaskID != ERROR) { taskDelete(oldTaskID); }
1005  return oldTaskID;
1006 }
1007 
1008 #if 0
1009 /* if you want to run this task by itself to debug
1010  * enable this code and make RunProgram the entry point
1011  */
1012 extern "C"
1013 {
1014 void RunProgram();
1015 int AxisCamera_StartupLibraryInit();
1016 }
1018 void RunProgram()
1019 { StartCameraTask();}
1020 
1022 int AxisCamera_StartupLibraryInit()
1023  { RunProgram(); return 0; }
1024 
1025 #endif
1026 
1027 
1028 
bool Start(uint32_t arg0=0, uint32_t arg1=0, uint32_t arg2=0, uint32_t arg3=0, uint32_t arg4=0, uint32_t arg5=0, uint32_t arg6=0, uint32_t arg7=0, uint32_t arg8=0, uint32_t arg9=0)
Definition: Task.cpp:52
int32_t GetID()
Definition: Task.cpp:175
Definition: Task.h:17

Generated on Sat Apr 26 2014 12:26:45 for WPILibC++ by doxygen 1.8.6