2 Cameras in Java

Hello World,
As my team has been working this off season we were wondering if we would be able to use two USB cameras on our robot. We know that it is legal but we were wondering on the coding side what it would take. We are not able to test the code on the actual robot so, we only have theory to go on. Anyway, in theory this is all that should be needed to run two usb cameras at the same time on the Java SmartDashboard.

public class Robot extends IterativeRobot {

    CameraServer server;
    CameraServer server2;

    public void robotInit() {
    	RobotMap.init();
    	        //This is for the USB Camera
    	server = CameraServer.getInstance();
    	server.setQuality(50);
    	       //Replace cam0 with acutal name
    	server.startAutomaticCapture("cam0");

        server2 = CameraServer.getInstance();
        server2.setQuality(50);
               //Replace cam1 with actual name
        server2.startAutomaticCapture("cam1");
        }

CameraServer.getInstance(), as the name implies, returns a singleton instance of CameraServer. That means server1 and server2 are the same in your code.

Here’s how you might get both camera feeds into a single frame


// init
USBCamera cam0 = new USBCamera("cam0");
USBCamera cam1 = new USBCamera("cam1");
Image cam0Image = NIVision.imaqCreateImage(ImageType.IMAGE_RGB, 0);
Image cam1Image = NIVision.imaqCreateImage(ImageType.IMAGE_RGB, 0);
Image combinedImage = NIVision.imaqCreateImage(ImageType.IMAGE_RGB, 0);

cam0.openCamera();
cam1.openCamera();
cam0.startCapture();
cam1.startCapture();

// on each iteration
cam0.getImage(cam0Image);
cam1.getImage(cam1Image);
GetImageSizeResult cam0Size = NIVision.imaqGetImageSize(cam0Image);
GetImageSizeResult cam1Size = NIVision.imaqGetImageSize(cam1Image);
NIVision.imaqCopyRect(combinedImage, cam0Image, new Rect(0, 0, cam0Size.width, cam0Size.height), new Point(0, 0));
NIVision.imaqCopyRect(combinedImage, cam1Image, new Rect(0, 0, cam1Size.width, cam1Size.height), new Point(cam0Size.width, 0));

CameraServer.getInstance().setImage(combinedImage);

Disclaimer: untested, but you get the idea

I was not involved with programming this year, but from my conversations with the programming mentors and students, I understand that we had difficulty using two cameras on the same USB bus. This problem appeared not to be java-specific, but a USB camera issue. It seems that most USB cameras (and all of the ones we had on hand at that time, including some KoP cameras) grab something like 60% of the USB bandwidth when they start up. Running two cameras without taking pains to limit these allocations, you are certain to have trouble. If you can’t find any detail on how to do this online, PM me and I’ll contact the mentors to find out how we resolved/mitigated the issue.

We ran with 3 cameras on our robot this year (front high view, front ball intake, and the reverse-cam). What we did was to extend the CameraServer class to allow us to switch feeds from one cam to another. We found that getting 2 simultaneous feeds put us a bit too close to the bandwidth cap, even at low-ish resolution (mjpeg isn’t that efficient).

On our DS we had two buttons that would set the direction of travel forward and pick one of the two forward cams, and a third button that would invert the direction of travel of the robot and bring up the “reverse” cam. It was fairly efficient, and good for intaking a boulder against the rail or in the corners.

Our USB problem wasn’t bandwidth (we stopped image capture as we switched cams), but that we had 3 identical cams on the USB bus – which cam was “usb0” tended to change with each cold start of the RoboRIO. Part of our pre-match on-field setup was defining which “usbX” camera was which.

We has trouble with one camera on one port and two via a hub – only one camera from the hub would be recognized. How did you guys get 3 cameras working?

To be honest, we used a small cheap unpowered hub and some older cameras, plugged in and they all just showed up – they just didn’t always appear in the same order.

Is there a chance the cameras and hub are drawing too much voltage?

(And I presume the trouble you are talking about means not all the cameras were being listed on the RoboRio web interface.)

Thanks for that info. What we will most likely end up doing is having two cameras but only streaming one at a time to the dashboard. This is the latest version of code that we have for it.(FYI this was in a command format but was changed for simplicity of this site)


Cameras cameras;
public void robotInit() {
    	//This is for the USB Camera
    	server = CameraServer.getInstance();
    	server.setQuality(50);
    	Cameras.cam = "";
    	server.startAutomaticCapture(Cameras.cam);
    	while(isEnabled()){
    		server.startAutomaticCapture(Cameras.cam);
    	}

//There is a joystick button once pressed it will activate this command SwitchCams
public void SwitchCams() {
        if(Cameras.cam == "cam0"){
    		Cameras.cam = "cam1";
    	}else if(Cameras.cam == "cam1"){
    		Cameras.cam = "0";
    		//Leave following if statement equal to blank
    	}else if(Cameras.cam == "")
    		Cameras.cam = "cam0";
}

Yep, it wouldn’t show up on the web interface. We checked with a hub that measures current draw and it looked ok. I guess we should try with a powered hub though.

The problem is that the native WPILib CameraServer class doesn’t have a way to stop, or switch, or restart the server instance. You’ll need to extend/replace that CameraServer class to make it work. Here’s what we ended up doing, albeit a bit quick and dirty:

Keep in mind that USB is designed to not overdraw current… If you have 500ma of power available and plug in (2) 400ma devices, your hub will only draw a bit over 400ma (a little for itself) and leave the other device unpowered.

You should also be able to plug those cameras into a PC and check the USB device info (lsusb on linux, for example) to see what the current required for each is. After that, some simple math would tell you if you’re over committing.

One other question – are both of these cameras identical?

No, we have a USB hub with a small LCD screen that displays current draw on it, and it looked ok. IIRC the power light was lit for all 3 cameras.

Two of the cameras were identical, one was a different model with a wider field of view. They were all Logitech webcams

I’m going to presume it was not the odd camera out that is the problem – and that if you plug them in one at a time to the Rio they do show up on the Web Interface.

If each camera works independant of the other two, then it’s not compatibility. That leaves the hub (or it’s cable), and power as the likely culprits. Aside from testing with another hub (powered and/or unpowered) I’m not sure what else to suggest…

You guys can look at our code we had 2 cameras working but you have to manually switch over the stream as it is impossible to stream both cameras at the same time here is our code: https://github.com/Team2895/Team2895-code-2016/blob/master/src/org/usfirst/frc/team2895/robot/Robot.java

Sent from my iPhone using Tapatalk

USB bandwidth? There is no problem with running two cameras at a time, in regards to the roborio.