Switching between two webcams on the dashboard

I know I know! There are already a LOT of these type of threads! Just hear me out :slight_smile:

We are working on trying to have a front and rear webcam for our robot. We want the view on the dashboard (the default LabVIEW dashboard) to switch cameras by either a press of a button or autonomously.

We have tried the various methods here on CD, but nothing worked yet.

One thing we noticed was that the RoboRIO is showing both webcams in the Configuration page (roborio-2990-frc.local/) as “cam0” and “cam1”, but they’re both enumerated as “USB0” (see attachment)

We’re wondering if this might be our problem. Is this supposed to happen? If so, does anyone have a WORKING LabVIEW example of switching webcams?

Thanks!

(Again, sorry for ANOTHER post about dual webcams, but I feel like this is a bit of a different issue then the rest)





The USB0::0x… are the fully-qualified addresses that VISA and some other drivers will call the camera when they enumerate. The OS HID drivers use the same or a similar technique. This includes which USB controller, which hub, and which port on the hub the device is plugged into. It is unrelated to the USB 0 and USB 1 addresses that the WPILib camera stuff uses.

One way to get what you are asking for is for me to describe a bit more about the camera server that is inside of Send2PC. It is written to use only one port and one camera. But with a few small tweaks, you can make ones that will serve two cameras. Then you can decide which is paused and which is streaming.

If you start with the Vision Processing block diagram, there is a string of initialization functions to ensure the camera is in a predictable state, then this refnum forks and goes into the loop and goes to the Background Loop subVI. Open the Background subVI.

As the comment states, this subVI does one thing for IP cameras and another for USB cams. They were combined into one abstract background subVI, but have little interaction. The left-most camera function determines whether this is a USB camera or not. If it is USB, the only thing that executes is the Send2PC Loop. So lets open that one next.

Send2PC listens for a connection on port 1180. That is not a parameter, but a constant. So if you want two cameras, you probably want two ports. Once it has a dashboard connection, it sets up the camera, starts it, and loops acquiring and sending them to the port. This implements both the SW compression and HW compression options and has code for a two-port cRIO that requires the data be forwarded. But the important thing to notice is that this code uses an image named WPILib_SendtoPCImage to get the image from the camera. It wouldn’t be good to use the same image name for different cameras.

So. If you clone the Send2PC VI and make the image name and port be unique, you now have two camera servers. If you are using USB for both, don’t bother with the background loop, you can just drop your Send2PCA and B versions and wire up the parameters.

Some teams want two small simultaneous streams, and the customizations I’ve described should work for them. You wanted a switch. So I’d recommend you then add some pause/run code to the loops to leave both cameras open and on a unique port and control which is working and which is paused.

On the dashboard, you have a few edits to make as well. The vision loop listens on one port, stores to one AVI file, displays to one image display, etc. If you dig down inside the code, the important work happens in Get on PC. It opens and communicates on port 1180 and decodes transmitted data into your image. If you have two of these connected to the appropriate port, hint, make the port be a parameter, then you can leave both running and display the one the driver is interested in.

So, with a few edits, you can make variations of the Send and Get PC camera servers to do what you want. I believe some teams have made these changes in years past, so you may not need to make them yourself, but they aren’t that hard or risky.

I’m happy to answer questions.
Greg McKaskle

Greg sir, you are amazing! VERY detailed instructions! Thanks! We will be testing out this code today at the shop and I’ll post back with our findings.

So I followed the instructions and didn’t have success although its most probably because I didn’t follow the instructions correctly. I’m posting the changes I made below and maybe you could point out where I went wrong.

Starting with the robot code, If I understand this correctly, the Camera Background VI just houses the Send 2 PC VI and you can ignore everything else if the camera is run over USB. So the first thing I did was make a modified version of the Send 2PC VI or as its called WPI_CameraSend Images to PC VI.
https://drive.google.com/open?id=0Bwq4tU8Mbh1oQngwNDJrd1pHM2M
In it, I the changed the port number constant wired into the TCP Listen VI to a control named “port”. This was originally just set to 1180. Then I changed the Image Name Constant going into IMAQ create VI into a string control as well whereas it was originally the WPILib_SendtoPCImage you were referring to.

I named this VI as “Sketchy Send 2 PC” just to keep track of changes but you can see that I placed this directly onto the vision processing VI.
https://drive.google.com/open?id=0Bwq4tU8Mbh1oSG1VUVZNWFJVODg
Originally the set of set up VIs associated with “USB 1” was not there as shown below. I just branched the single original camera reference into to two separate “Sketchy Send 2 PC” VIs while maintaining the same parameters that you see in this image being 2 different port numbers 1180 and 1179 (I’m not very familiar with so I just used 1 number less thinking it to be legitimate) and then “WPILib_SendtoPCImage A” and “WPILib_SendtoPCImage B” for the two VIs Respectively. When this, along with the other changes didn’t work, I made the change that you see in the image where I’m opening two separate Camera References.

Next in the Dashboard, I made the following changes:

Starting from the Camera Loop (Loop #2) and going further in

Essentially, Just modifying each concentric VI to change the 1180 TCP port constant at the bottom most level, to something that I can change on the dashboard while its running.

https://drive.google.com/open?id=0Bwq4tU8Mbh1oQlctRkJ4QVF0R2s
https://drive.google.com/open?id=0Bwq4tU8Mbh1oanRrd2hhRTg2aG8
https://drive.google.com/open?id=0Bwq4tU8Mbh1oQjhMNE5fSTkxdVE

At the end of this, I the code is still able to recognize and display one USB camera but cannot change the display to the second one whenever I bump the port number on the dashboard (while its running) between 1180 and 1179. It just stays on the same original camera. I cannot tell which camera I have assigned port 1180 or 1179.

Hey Teku14,

We successfully (after 5 hours!) managed to switch webcams. I will post the relevant VI snapshots and try to explain them the best I can. Here is a link to the code we tried and some annotated screenshots.
https://drive.google.com/folderview?id=0B1zoCPzvBFCzR2dnQUU0ekxyVGM&usp=sharing

Vision Processing:
We created two cameras (notice the different RefNum names :slight_smile: ) and wired them into our new Background Loop VI.

CameraBackground Loop:
We had to create a second RefNum input for the second webcam and run two (2) Send2PC loops (one for each camera).

Send2PC:
It looks like you did the Send2PC perfectly. Just create controls for the port and the image name, and set them as inputs for the VI.

DASHBOARD:
DashboardMain:
We had to do a bit of trial and error to get this to work correctly. We have a bit of code (highlighted in the orange box) that would “refresh” the feed and the port. Without that code, we would flip the camera switcher, but the image wouldn’t update with the new camera unless we switch from Camera HW to Camera SW (or vice versa). So, this little block of code automatically switches from HW to SW (or vice versa) if the port changes.

CameraRead_MJPG:
This was a tricky VI because it was a clone and you can’t edit a clone. The trick I found to edit a VI is:

  • In the DashboardMain VI, do a CTRL+F (find)
  • Next, under “Select Object”, click the “Add” button and go to: Objects in vi.lib and if you scroll all the way down, you will see the Camera VIs
  • Find the Dashbd MJPG VI and left-click on it
  • Next, in the “search Scope”, choose the “<All VIs in Application Instance>” and make sure the “Hierarchy Window” checkbox is checked
  • Flick Find
  • Double-click on “VI Hierarchy”
  • You should be able to click and drag the VI (Dashbg MJPG) into the Dashboard Main VI so you can edit it

Now that you have that VI, you can open it up and continue on. Yay!

Inside that VI, there is a “Get On PC” VI inside the “1, 2” case in the middle case-structure. We had to edit that too :slight_smile:

Get on PC:
Since this VI is also a clone, do the same steps as above with the MJPG VI, (but, obviously, look for the Get On PC instead :slight_smile: )

Moving on…

All we had to add was a control for the camera port and make it an input for the VI.

That’s what we did. Let me know if you have any further questions at all.

Thanks again Greg for getting us on the right foot :slight_smile:

You are welcome. Glad you got it working and are willing to share the results.

Also, if you have a reentrant clone VI and need to edit it, press ctl-m, which is a shortcut for Operate >> Change to … Mode. This lets you go between run and edit mode for any VI. Clones default to Run Mode.

Greg McKaskle

Glad to help out other FRC’ers :slight_smile:

And thanks for that tip. That’s MUCH easier than what we had to do

Thank you all for the response! Extremely helpful. I will try this out and post how it turns out.

I’m sorry but even after following your instructions and pictures to the dot it doesn’t seem to be working. Also the code you attached is trying to access the default WPI VIs that are on my computer. Can you save the modifications you made to the WPI Camera VIs into the project as new VIs and repost it?

Glad you guys got it all working! Just a piece of advice from a former driver, though – you will probably not be looking at your driver station laptop nearly as much as you think you will. Driving is stressful and dangerous and it’s hard to tear your eyes away from the field and down to your computer.

That’s my experience anyway. Just something to keep in mind!

Thanks for the advice! I was the driver for our team for 2 years, and I can concur, however :slight_smile: , with how little visibility there is on the field this year, it will be difficult to see what’s in front of your robot at times (e.g. a boulder behind the drawbridge).

We have tested the latency on the camera over wifi from the robot (not through the FMS, so it might vary), and it isn’t that bad. We calculated it to be only about 90-100ms lag. We had our driver drive it a bit ONLY looking at the webcam image, and he said he could drive it just fine.

I will post the VIs. I will try to get them out before the end of the week (school, work, robotics, etc :stuck_out_tongue: )

Also, I double-checked the rules, and we’re not allowed to use port 1181. We have to use a port somewhere in between 5800 and 5810 (per R60)

The link is returning a 404 error. Do you mind re-posting the code and screenshots?

Thanks

Dang it! Looks like it got deleted! (That’s what I get for not uploading them to a more permanent spot).

Basically, we just copy/pasted the camera stuff in the “Vision Processing” VI to create the second camera object. The tricky part is, then you have to go into some of the VI’s (digging deep, sometimes), and make sure a second camera is being sent to the dashboard.

THEN, from the dashboard program, there’s a control somewhere below the “Do not edit stuff below this” line that takes in the MJPG stream and sends it to the video item. We just created a switch that would switch back and forth between two TCP Ports (1180 and 1181 I believe).

But, all of this was basically a re-hash of what I said in the quoted post. Let me know if you need more details (I feel like that post is fairly detailed?)

Again, very sorry I can’t get you the VI’s directly :frowning:

The camera stuff was updated for 2017. It shouldn’t need the same edits.

Each camera you open and register by name such as “front” and “rear” will show up on the dashboard ring selector and in the Network Tables camera section.

Selecting the name should create a connection. The default dashboard has two viewers built in.

I’m sometimes seeing issues with the name resolution when wifi, or another network interface is up. Solution is to turn off the wifi.

Greg McKaskle

Can you clarify how that is done? Is there a string constant somewhere that I’m not finding?

Edit: I figured out that folks are referring to the camera initialization process in Vision Processing.VI and not anything within Send2PC. Basically the open/registration of the second camera is done with just a second WPI_CameraOpen.vi and then feeding the resultant refnum into WPI_CameraRefNum Registry Set.vi. The “ports” being referred to are the USB ports, not the HTTP ports (1180, 1181, etc.).

In Vision Processing.vi duplicate the first camera setup, but give the new code a different USB, e.g., USB 1, and a different *Camera name *of your choice.
e.g.,

But for two simultaneous streams, an additional HTTP port is required, right? With nothing else changed, both cameras will fight to use 1181.

I’ve been using the same port for two camera streams and haven’t had a problem.

Hmmm. My mileage is definitely varying on that then. We’ve tried both on 1181 as well as one on 1181 and the other on 1182 with the same result: as long as the same camera is selected in both display windows either feed is good, but as soon as we select a different second camera (in either window) we error out on the newly-selected camera.

Looking at the Dashboard code, I don’t see anything port-specific so it sounds like I’m barking up the wrong tree in assigning blame to the port. The Dashboard Variables indicate that we’ve got two streams connected as expected.