We are having an interesting problem with our camera code and we were wondering if anyone has seen anything like these.
We have an auto targeting routine that works great but we are only able to call it about 6 times andd then the camera stops returning images. We still get the live feed on the dashboard though. Afterwards we have to reboot to get the camera code to work again.
Any idea what might be wrong?
Does anyone do anything special in sequential camera calls?
Are you deleting the old images you are creating as part of your loop. I read somewhere that the old images will build up fast if you aren’t removing them constantly.
Im having the same problem right now. I have one version where it doesn’t occur and a more recent one where it does. The changes should* all be okay though…
The newer version organizes particles. That is the only change. My image is deleted also.
As for the console, i have been using the ds lcd recently because after i connect target server when trying to open the console the target tools option is not available in the drop down menu.
There are many things that could go wrong with that statement. Are you sure reports is not a NULL pointer? Are you sure highParticle contains a valid index etc?
It works for a few iterations before failing.
I had the 2 other team programmers look to check that everything was alright when this issue started (after I added code using those lines).
The CPU usage in the DS climbs when it starts using the camera and plateaus for a while while it works before stopping.
I could post before and after code if it would help. (this is reasonably short because it’s simplified and camera-specific)
I delete everything I use in any loops which I make it in.
Wait, which line is the culprit now? There is no line “reports->at(highParticle).center_mass_y;” in your alteredCode.cpp. I assume the workingCode.cpp is the working one and alteredCode.cpp is the one with problems, although I see more bugs in workingCode than alteredCode.
for (unsigned int i = 0; i < reports->size(); i++)
{
if(reports->at(i).center_mass_y > reports->at(highParticle).center_mass_y)
{
highParticle = i;
}
}
for (unsigned int i = 0; i < reports->size(); i++)
{
if(reports->at(i).center_mass_y < reports->at(lowParticle).center_mass_y)
{
lowParticle = i;
}
}
Also, your assumption is correct. The working one does not stop while the other, (with the above changes), does after working briefly.
I commented out these lines and the code began to work again.
I also tried to make particle analysis report pointers like in the other file to compare results but that works in a similar fashion with the exception that when the code stops working instead of the CPU usage flat-lining it spikes and does not come down and the code stops as with the other way.
I apologize for any distracting extraneous code or any bugs in the ‘working’ version. It is a save from when I got the camera to work as I intended (my lesson learned- this being the second time)
Okay, then the most logical explanation is that your reports->size() sometimes gives you zero, meaning that it can’t find any target. In that case, your reference to particle 0 “reports->at(highParticle).center_mass_x_normalized;” will fault. To prove this, add something like this to your code. By switching this code, you will print out size() before you execute that centerX line that will fault. I’d bet, size() is zero.
[FONT=Consolas][size=2]numTargets = reports->size();
[FONT=Consolas][size=2][FONT=Consolas][size=2]dsLCD->Clear();
dsLCD->Printf(DriverStationLCD::kUser_Line1, 1, [/size][/size][/FONT][FONT=Consolas][size=2][FONT=Consolas][size=2]"report width %d"[/size][/size][/FONT][/FONT][FONT=Consolas][size=2], convexHullImage->GetWidth());
[/size][/FONT][FONT=Consolas][size=2][FONT=Consolas][size=2]//fix so is based on score
[/size][/size][/FONT][/FONT][FONT=Consolas][size=2]dsLCD->Printf(DriverStationLCD::kUser_Line2, 1, [/size][/FONT][FONT=Consolas][size=2][FONT=Consolas][size=2]"size %d"[/size][/size][/FONT][/FONT][FONT=Consolas][size=2], reports->size());
[/size][/FONT][FONT=Consolas][size=2]dsLCD->UpdateLCD();
[/size][/FONT]centerX = reports->at(highParticle).center_mass_x_normalized;
[/FONT][/size][/FONT]dsLCD->Printf(DriverStationLCD::kUser_Line3, 1, [FONT=Consolas][size=2][FONT=Consolas][size=2]"center x %f"[/size][/FONT][/size][/FONT][FONT=Consolas][size=2], centerX);
dsLCD->UpdateLCD();
[/size][/FONT]
I am glad that’s fixed. In general, you need to add more “error checking” code and always assume the WPI library calls could fail. For example, all the calls that generate images such as ThresholdRGB, FilterImages etc could fail and return NULL pointers. If you don’t check and use them, you will fault. It may be unlikely but it could happen under unusual circumstances. For example, here is an excerpt of our vision processing code. Note that it checked for errors after each WPI library call and at the end when deleting the objects, we called SAFE_DELETE which is a macro that basically check for NULL pointer before it deleted the object.
int err = ERR_SUCCESS;
BinaryImage *image = NULL;
BinaryImage *thresholdImage = NULL;
BinaryImage *bigObjImage = NULL;
BinaryImage *convexHullImage = NULL;
BinaryImage *filteredImage = NULL;
m_camera->GetImage(&m_cameraImage);
//
// Filter the image by color.
//
thresholdImage = m_cameraImage.ThresholdRGB(*m_colorThresholds);
image = thresholdImage;
if (thresholdImage == NULL)
{
err = imaqGetLastError();
TErr(("Failed to filter image with thresholds (err=%d).", err));
}
else if (m_sizeThreshold > 0)
{
//
// Remove small objects
//
bigObjImage = image->RemoveSmallObjects(false, m_sizeThreshold);
image = bigObjImage;
if (bigObjImage == NULL)
{
err = imaqGetLastError();
TErr(("Failed to filter image with size (err=%d).", err));
}
}
if (err == ERR_SUCCESS)
{
convexHullImage = image->ConvexHull(false);
image = convexHullImage;
if (convexHullImage == NULL)
{
err = imaqGetLastError();
TErr(("Failed to generate Convex Hull image (err=%d).", err));
}
}
if ((err == ERR_SUCCESS) && (m_filterCriteria != NULL))
{
filteredImage = image->ParticleFilter(m_filterCriteria, m_numCriteria);
image = filteredImage;
if (filteredImage == NULL)
{
err = imaqGetLastError();
TErr(("Failed to filter image based on criteria (err=%d).", err));
}
}
if (err == ERR_SUCCESS)
{
vector<ParticleAnalysisReport> *reports =
image->GetOrderedParticleAnalysisReports();
if (reports == NULL)
{
err = imaqGetLastError();
TErr(("Failed to get particle analysis reports (err=%d).", err));
}
else
{
CRITICAL_REGION(m_semaphore)
{
SAFE_DELETE(m_targets);
m_targets = reports;
reports = NULL;
}
END_REGION;
}
}
SAFE_DELETE(filteredImage);
SAFE_DELETE(convexHullImage);
SAFE_DELETE(bigObjImage);
SAFE_DELETE(thresholdImage);