Now you can download a copy of these docs so you can use them offline! Download now
AxisCameraParams.cpp
00001 /*----------------------------------------------------------------------------*/ 00002 /* Copyright (c) FIRST 2008. All Rights Reserved. */ 00003 /* Open Source Software - may be modified and shared by FRC teams. The code */ 00004 /* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */ 00005 /*----------------------------------------------------------------------------*/ 00006 00007 #include "Vision/AxisCameraParams.h" 00008 00009 #include "Vision/AxisCamera.h" 00010 #include <inetLib.h> 00011 #include "pcre.h" 00012 #include <sockLib.h> 00013 #include <string.h> 00014 #include "Synchronized.h" 00015 #include "Timer.h" 00016 #include "Utility.h" 00017 #include "WPIErrors.h" 00018 00019 #if JAVA_CAMERA_LIB != 1 00020 #include "DriverStation.h" 00021 #endif 00022 00023 static const char *const kRotationChoices[] = {"0", "180"}; 00024 static const char *const kResolutionChoices[] = {"640x480", "640x360", "320x240", "160x120"}; 00025 static const char *const kExposureControlChoices[] = { "automatic", "hold", "flickerfree50", "flickerfree60" }; 00026 static const char *const kWhiteBalanceChoices[] = { "auto", "holdwb", "fixed_outdoor1", 00027 "fixed_outdoor2", "fixed_indoor", "fixed_fluor1", "fixed_fluor2" }; 00028 00032 AxisCameraParams::AxisCameraParams(const char* ipAddress) 00033 : m_paramTask("paramTask", (FUNCPTR) s_ParamTaskFunction) 00034 , m_paramChangedSem (NULL) 00035 , m_socketPossessionSem (NULL) 00036 , m_brightnessParam (NULL) 00037 , m_compressionParam (NULL) 00038 , m_exposurePriorityParam (NULL) 00039 , m_colorLevelParam (NULL) 00040 , m_maxFPSParam (NULL) 00041 , m_rotationParam (NULL) 00042 , m_resolutionParam (NULL) 00043 , m_exposureControlParam (NULL) 00044 , m_whiteBalanceParam (NULL) 00045 { 00046 if (ipAddress == NULL || strlen(ipAddress) == 0) 00047 { 00048 #if JAVA_CAMERA_LIB == 1 00049 wpi_setWPIErrorWithContext(ParameterOutOfRange, "IP Address must be specified"); 00050 return; 00051 #else 00052 DriverStation *ds = DriverStation::GetInstance(); 00053 ds->WaitForData(); 00054 UINT16 teamNumber = ds->GetTeamNumber(); 00055 char cameraIP[16]; 00056 snprintf(cameraIP, 16, "10.%d.%d.11", teamNumber / 100, teamNumber % 100); 00057 m_ipAddress = inet_addr(cameraIP); 00058 #endif 00059 } 00060 else 00061 { 00062 m_ipAddress = inet_addr((char*)ipAddress); 00063 } 00064 00065 if (m_ipAddress == (u_long)ERROR) 00066 { 00067 wpi_setErrnoError(); 00068 return; 00069 } 00070 00071 m_brightnessParam = new IntCameraParameter("ImageSource.I0.Sensor.Brightness=%i", 00072 "root.ImageSource.I0.Sensor.Brightness=(.*)", false); 00073 m_parameters.push_back(m_brightnessParam); 00074 m_colorLevelParam = new IntCameraParameter("ImageSource.I0.Sensor.ColorLevel=%i", 00075 "root.ImageSource.I0.Sensor.ColorLevel=(.*)", false); 00076 m_parameters.push_back(m_colorLevelParam); 00077 m_exposurePriorityParam = new IntCameraParameter("ImageSource.I0.Sensor.exposurePriority=%i", 00078 "root.ImageSource.I0.Sensor.ExposurePriority=(.*)", false); 00079 m_parameters.push_back(m_exposurePriorityParam); 00080 m_compressionParam = new IntCameraParameter("Image.I0.Appearance.Compression=%i", 00081 "root.Image.I0.Appearance.Compression=(.*)", true); 00082 m_parameters.push_back(m_compressionParam); 00083 m_maxFPSParam = new IntCameraParameter("Image.I0.Stream.FPS=%i", 00084 "root.Image.I0.Stream.FPS=(.*)", false); 00085 m_parameters.push_back(m_maxFPSParam); 00086 m_rotationParam = new EnumCameraParameter("Image.I0.Appearance.Rotation=%s", 00087 "root.Image.I0.Appearance.Rotation=(.*)", true, kRotationChoices, sizeof(kRotationChoices)/sizeof(kRotationChoices[0])); 00088 m_parameters.push_back(m_rotationParam); 00089 m_resolutionParam = new EnumCameraParameter("Image.I0.Appearance.Resolution=%s", 00090 "root.Image.I0.Appearance.Resolution=(.*)", true, kResolutionChoices, sizeof(kResolutionChoices)/sizeof(kResolutionChoices[0])); 00091 m_parameters.push_back(m_resolutionParam); 00092 m_exposureControlParam = new EnumCameraParameter("ImageSource.I0.Sensor.Exposure=%s", 00093 "root.ImageSource.I0.Sensor.Exposure=(.*)", false, kExposureControlChoices, sizeof(kExposureControlChoices)/sizeof(kExposureControlChoices[0])); 00094 m_parameters.push_back(m_exposureControlParam); 00095 m_whiteBalanceParam = new EnumCameraParameter("ImageSource.IO.Sensor.WhiteBalance=%s", 00096 "root.ImageSource.I0.Sensor.WhiteBalance=(.*)", false, kWhiteBalanceChoices, sizeof(kWhiteBalanceChoices)/sizeof(kWhiteBalanceChoices[0])); 00097 m_parameters.push_back(m_whiteBalanceParam); 00098 00099 m_paramChangedSem = semBCreate (SEM_Q_PRIORITY, SEM_EMPTY); 00100 m_socketPossessionSem = semBCreate (SEM_Q_PRIORITY, SEM_FULL); 00101 00102 m_paramTask.Start((int)this); 00103 } 00104 00108 AxisCameraParams::~AxisCameraParams() 00109 { 00110 m_paramTask.Stop(); 00111 00112 semDelete(m_socketPossessionSem); 00113 semDelete(m_paramChangedSem); 00114 00115 delete m_whiteBalanceParam; 00116 delete m_exposureControlParam; 00117 delete m_resolutionParam; 00118 delete m_rotationParam; 00119 delete m_maxFPSParam; 00120 delete m_compressionParam; 00121 delete m_exposurePriorityParam; 00122 delete m_colorLevelParam; 00123 delete m_brightnessParam; 00124 } 00125 00129 int AxisCameraParams::s_ParamTaskFunction(AxisCameraParams* thisPtr) 00130 { 00131 return thisPtr->ParamTaskFunction(); 00132 } 00133 00139 // TODO: need to synchronize the actual setting of parameters (the assignment statement) 00140 int AxisCameraParams::ParamTaskFunction() 00141 { 00142 static bool firstTime = true; 00143 00144 while (true) 00145 { 00146 semTake(m_socketPossessionSem, WAIT_FOREVER); 00147 if (firstTime) 00148 { 00149 while (ReadCamParams() == 0); 00150 firstTime = false; 00151 } 00152 bool restartRequired = false; 00153 00154 ParameterVector_t::iterator it = m_parameters.begin(); 00155 ParameterVector_t::iterator end = m_parameters.end(); 00156 for(; it != end; it++) 00157 { 00158 bool changed = false; 00159 char param[150]; 00160 restartRequired |= (*it)->CheckChanged(changed, param); 00161 if (changed) 00162 { 00163 UpdateCamParam(param); 00164 } 00165 } 00166 if (restartRequired) 00167 { 00168 RestartCameraTask(); 00169 } 00170 semGive(m_socketPossessionSem); 00171 } 00172 return 0; 00173 } 00174 00179 void AxisCameraParams::WriteBrightness(int brightness) 00180 { 00181 m_brightnessParam->SetValue(brightness); 00182 semGive(m_paramChangedSem); 00183 } 00184 00189 int AxisCameraParams::GetBrightness() 00190 { 00191 return m_brightnessParam->GetValue(); 00192 } 00193 00198 void AxisCameraParams::WriteWhiteBalance(WhiteBalance_t whiteBalance) 00199 { 00200 m_whiteBalanceParam->SetValue(whiteBalance); 00201 semGive(m_paramChangedSem); 00202 } 00203 00208 AxisCameraParams::WhiteBalance_t AxisCameraParams::GetWhiteBalance() 00209 { 00210 return (WhiteBalance_t) m_whiteBalanceParam->GetValue(); 00211 } 00212 00217 void AxisCameraParams::WriteColorLevel(int colorLevel) 00218 { 00219 m_colorLevelParam->SetValue(colorLevel); 00220 semGive(m_paramChangedSem); 00221 } 00222 00227 int AxisCameraParams::GetColorLevel() 00228 { 00229 return m_colorLevelParam->GetValue(); 00230 } 00231 00236 void AxisCameraParams::WriteExposureControl(Exposure_t exposureControl) 00237 { 00238 m_exposureControlParam->SetValue(exposureControl); 00239 semGive(m_paramChangedSem); 00240 } 00241 00246 AxisCameraParams::Exposure_t AxisCameraParams::GetExposureControl() 00247 { 00248 return (Exposure_t) m_exposureControlParam->GetValue(); 00249 } 00250 00255 void AxisCameraParams::WriteResolution(Resolution_t resolution) 00256 { 00257 m_resolutionParam->SetValue(resolution); 00258 semGive(m_paramChangedSem); 00259 } 00260 00265 AxisCameraParams::Resolution_t AxisCameraParams::GetResolution() 00266 { 00267 return (Resolution_t) m_resolutionParam->GetValue(); 00268 } 00269 00277 void AxisCameraParams::WriteExposurePriority(int exposurePriority) 00278 { 00279 m_exposurePriorityParam->SetValue(exposurePriority); 00280 semGive(m_paramChangedSem); 00281 } 00282 00283 int AxisCameraParams::GetExposurePriority() 00284 { 00285 return m_exposurePriorityParam->GetValue(); 00286 } 00287 00293 void AxisCameraParams::WriteRotation(Rotation_t rotation) 00294 { 00295 m_rotationParam->SetValue(rotation); 00296 semGive(m_paramChangedSem); 00297 } 00298 00303 AxisCameraParams::Rotation_t AxisCameraParams::GetRotation() 00304 { 00305 return (Rotation_t) m_rotationParam->GetValue(); 00306 } 00307 00313 void AxisCameraParams::WriteCompression(int compression) 00314 { 00315 m_compressionParam->SetValue(compression); 00316 semGive(m_paramChangedSem); 00317 } 00318 00323 int AxisCameraParams::GetCompression() 00324 { 00325 return m_compressionParam->GetValue(); 00326 } 00327 00333 void AxisCameraParams::WriteMaxFPS(int maxFPS) 00334 { 00335 m_maxFPSParam->SetValue(maxFPS); 00336 semGive(m_paramChangedSem); 00337 } 00338 00343 int AxisCameraParams::GetMaxFPS() 00344 { 00345 return m_maxFPSParam->GetValue(); 00346 } 00347 00354 int AxisCameraParams::UpdateCamParam(const char* param) 00355 { 00356 char *requestString = 00357 "GET /axis-cgi/admin/param.cgi?action=update&%s HTTP/1.1\n\ 00358 User-Agent: HTTPStreamClient\n\ 00359 Connection: Keep-Alive\n\ 00360 Cache-Control: no-cache\n\ 00361 Authorization: Basic RlJDOkZSQw==\n\n"; 00362 char completedRequest[1024]; 00363 sprintf(completedRequest, requestString, param); 00364 // Send request 00365 int camSocket = CreateCameraSocket(completedRequest); 00366 if (camSocket == ERROR) 00367 { 00368 printf("UpdateCamParam failed: %s\n", param); 00369 return 0; 00370 } 00371 close(camSocket); 00372 return 1; 00373 } 00374 00379 int AxisCameraParams::ReadCamParams() 00380 { 00381 char * requestString = 00382 "GET /axis-cgi/admin/param.cgi?action=list HTTP/1.1\n\ 00383 User-Agent: HTTPStreamClient\n\ 00384 Connection: Keep-Alive\n\ 00385 Cache-Control: no-cache\n\ 00386 Authorization: Basic RlJDOkZSQw==\n\n"; 00387 00388 int camSocket = CreateCameraSocket(requestString); 00389 if (camSocket == ERROR) 00390 { 00391 return 0; 00392 } 00393 // Allocate on the heap since it is very large and only needed once 00394 char *readBuffer = new char[27000]; 00395 int totalRead = 0; 00396 while (1) 00397 { 00398 wpi_assert(totalRead < 26000); 00399 int bytesRead = recv(camSocket, &readBuffer[totalRead], 1000, 0); 00400 if (bytesRead == ERROR) 00401 { 00402 wpi_setErrnoErrorWithContext("Failed to read image header"); 00403 close(camSocket); 00404 return 0; 00405 } 00406 else if (bytesRead <= 0) 00407 { 00408 break; 00409 } 00410 totalRead += bytesRead; 00411 } 00412 readBuffer[totalRead] = '\0'; 00413 00414 ParameterVector_t::iterator it = m_parameters.begin(); 00415 ParameterVector_t::iterator end = m_parameters.end(); 00416 for(; it != end; it++) 00417 { 00418 (*it)->GetParamFromString(readBuffer, totalRead); 00419 } 00420 close(camSocket); 00421 delete [] readBuffer; 00422 return 1; 00423 } 00424 00425 /* 00426 * Create a socket connected to camera 00427 * Used to create a connection to the camera by both AxisCameraParams and AxisCamera. 00428 * @param requestString The initial request string to send upon successful connection. 00429 * @return ERROR if failed, socket handle if successful. 00430 */ 00431 int AxisCameraParams::CreateCameraSocket(const char *requestString) 00432 { 00433 int sockAddrSize; 00434 struct sockaddr_in serverAddr; 00435 int camSocket; 00436 /* create socket */ 00437 if ((camSocket = socket(AF_INET, SOCK_STREAM, 0)) == ERROR) 00438 { 00439 wpi_setErrnoErrorWithContext("Failed to create the camera socket"); 00440 return ERROR; 00441 } 00442 00443 sockAddrSize = sizeof(struct sockaddr_in); 00444 bzero((char *) &serverAddr, sockAddrSize); 00445 serverAddr.sin_family = AF_INET; 00446 serverAddr.sin_len = (u_char) sockAddrSize; 00447 serverAddr.sin_port = htons(80); 00448 00449 serverAddr.sin_addr.s_addr = m_ipAddress; 00450 00451 /* connect to server */ 00452 struct timeval connectTimeout; 00453 connectTimeout.tv_sec = 5; 00454 connectTimeout.tv_usec = 0; 00455 if (connectWithTimeout(camSocket, (struct sockaddr *) &serverAddr, sockAddrSize, &connectTimeout) == ERROR) 00456 { 00457 wpi_setErrnoErrorWithContext("Failed to connect to the camera"); 00458 close(camSocket); 00459 return ERROR; 00460 } 00461 int sent = send(camSocket, requestString, strlen(requestString), 0); 00462 if (sent == ERROR) 00463 { 00464 wpi_setErrnoErrorWithContext("Failed to send a request to the camera"); 00465 close(camSocket); 00466 return ERROR; 00467 } 00468 return camSocket; 00469 }
Generated on Thu Jan 12 2012 22:35:17 for WPILibC++ by
1.7.1