Switching Cameras with code


Our team is thinking of using two cameras on our robot, and would like to be able to switch which camera is being displayed to the smart dashboard with the press of a button.

As of this point in time, we are not using vision tracking or anything complicated like that.


Switching Between Cameras?

Take a look at Camera Server - we have used it before and it is super easy to display to the smart dashboard. The documentation is here. The methods you are probably looking for is the startAutomaticCapture() function which can take in a number or ID for the camera stream. On the dashboard, you can change which camera stream to listen to.
If you want to dynamically control the stream from the RIO, you can also use the putVideo() function where you can manually send camera data. Simply use the VideoCapture class from OpenCV for your two cameras and change which frame is being sent using putVideo(). Hope that helps!



It’s not necessary to use OpenCV for this (and the OpenCV VideoCapture class is a lot less reliable than CameraServer’s video capture). See the CameraServer documentation for switching the driver views for how to do it with CameraServer (I recommend the “keeping streams open” approach for the speediest switching).



Is there any equivalent to this for Java?



C++ and Java are very similar. Here’s a quick Java conversion.

UsbCamera camera1;
UsbCamera camera2;
VideoSink server;
Joystick joy1 = new Joystick(0);
boolean prevTrigger = false;
void robotInit() {
  camera1 = CameraServer.getInstance().startAutomaticCapture(0);
  camera2 = CameraServer.getInstance().startAutomaticCapture(1);
  server = CameraServer.getInstance().addServer("Switched camera");
void teleopPeriodic() {
  if (joy1.getTrigger() && !prevTrigger) {
    System.out.println("Setting camera 2");
  } else if (!joy1.getTrigger() && prevTrigger) {
    System.out.println("Setting camera 1");
  prevTrigger = joy1.getTrigger();
1 Like

Displaying 2 USB Cameras
Robot OpenCV allocation crash with camera code

Thank you so much! I’ve been looking for a simple way to do this for a while, and this looks like what I’ve been looking for.



Is it that the docs are hard to navigate/find, or that the language of the example was C++? We do want to improve the team experience.



I think It’s mostly that I’m just dumb

Also, one last question. How do you view the server on the smart dashboard?



Do View | Add | CameraServer Stream Viewer. Right click on that, select Properties, then change the Camera Choice to the name passed to addServer.

I realized the above code is incorrect if you want access to both the individual streams as well as the switched stream, as it should use “addServer(name)” rather than “getServer”. If you use “getServer()” the switched stream is the camera 0 stream (the unswitched camera 0 is no longer available).



I’m probably just really dumb, but I changed the getTrigger() to getRawButton() so I could specify which button to use to switch, and now whenever I press the button to switch cameras, it switches to camera 2 then immediately back to camera 1.



Did you replace all three occurrences of GetTrigger? Note the code above only displays camera2 while the trigger is being held down. If you want a “click button once to switch to camera2, click again to switch to camera1” type behavior, you will need to have a separate Boolean variable that’s inverted on the rising edge detection.

Also, have you switched getServer to the new (in 2019.3.2) addSwitchedCamera? That will let you view it on the dashboard rather than a webpage.



I don’t know where I should be putting getServer (or now addSwitchedCamera) in the code though. I can already see it on the dashboard by viewing the CameraStream.



Sorry, I meant addServer() should be replaced, not getServer(), in my code above.

1 Like


Is it possible to set the camera resolution on the output stream? We’ve added things like:
camera1 = CameraServer.getInstance().startAutomaticCapture(0);
camera1.setResolution(320, 240);
camera1.setFPS(20); //cannot go higher or it uses too much bandwidth!

camera2 = CameraServer.getInstance().startAutomaticCapture(1);
camera2.setResolution(320, 240);
camera2.setFPS(20); //cannot go higher or it uses too much bandwidth!

server = CameraServer.getInstance().addSwitchedCamera("Switched Camera");

but the switched camera stream that shows up in SmartDashBoard is running at 34 FPS and 12 Mbps.



You can force the FPS and compression via the server object returned from addSwitchedCamera. Most dashboards also let you set both of those as well as the resolution.



Hmmm… we tried that already and setFPS/setResolution isn’t available because “server” is a VideoSink not a USBCamera. We’re probably missing something simple.



addSwitchedCamera() returns a MjpegServer, which has additional methods to set the stream configuration. http://first.wpi.edu/FRC/roborio/release/docs/java/edu/wpi/cscore/MjpegServer.html



OK, that may have been tried before switching to “addSwitchedCamera” so we’ll check it again.

We were able to set the FPS and resolution in Shuffleboard for both cameras simultaneously, but when those were set to 20 FPS they only got 5 FPS at 640x480 (both < 1 Mbps). The switching worked for a while then randomly stopped working so we’re going to need to do more debugging.

Also, the streams seem to have a hard time coming up, but then start and work fine when the code is restarted. Thanks for the info.



I’m not sure why but the cameras don’t seem to be switching. The code is running fine based on logs using the getSource() method, but I’m not seeing a change in which camera is streaming on my SmartDashboard. addServer() was also changed to addSwitchedCamera(). Do I need to be running a command that refreshes the feed?

EDIT: I’m viewing the camera feed through CameraServer on the dashboard, and MjpegServer has no connection.