使用多台相机
切换驱动程序视图
如果您只想更改驱动程序的外观并正在使用SmartDashboard,则SmartDashboard CameraServer Stream Viewer具有一个选项(“选定的相机路径”),该选项读取给定的:term:`NetworkTables`键并更改“相机选择” ”设置为该值(显示该摄像机)。然后,机器人代码只需要将NetworkTables键设置为正确的摄像机名称即可。假设“选定的摄像机路径”设置为“ CameraSelection”,下面的代码使用操纵杆1触发按钮状态来显示camera1和camera2。
UsbCamera camera1;
UsbCamera camera2;
Joystick joy1 = new Joystick(0);
NetworkTableEntry cameraSelection;
public Robot() {
camera1 = CameraServer.startAutomaticCapture(0);
camera2 = CameraServer.startAutomaticCapture(1);
cameraSelection = NetworkTableInstance.getDefault().getTable("").getEntry("CameraSelection");
}
@Override
public void teleopPeriodic() {
if (joy1.getTriggerPressed()) {
System.out.println("Setting camera 2");
cameraSelection.setString(camera2.getName());
} else if (joy1.getTriggerReleased()) {
System.out.println("Setting camera 1");
cameraSelection.setString(camera1.getName());
}
}
cs::UsbCamera camera1;
cs::UsbCamera camera2;
frc::Joystick joy1{0};
nt::NetworkTableEntry cameraSelection;
Robot() {
camera1 = frc::CameraServer::StartAutomaticCapture(0);
camera2 = frc::CameraServer::StartAutomaticCapture(1);
cameraSelection = nt::NetworkTableInstance::GetDefault().GetTable("")->GetEntry("CameraSelection");
}
void TeleopPeriodic() override {
if (joy1.GetTriggerPressed()) {
std::cout << "Setting Camera 2" << std::endl;
cameraSelection.SetString(camera2.GetName());
} else if (joy1.GetTriggerReleased()) {
std::cout << "Setting Camera 1" << std::endl;
cameraSelection.SetString(camera1.GetName());
}
}
备注
Python requires you to place your image processing code in a separate file from your robot code. You can create robot.py and vision.py in the same directory.
robot.py contents:
import wpilib
from ntcore import NetworkTableInstance
class MyRobot(wpilib.TimedRobot):
def robotInit(self):
self.joy1 = wpilib.Joystick(0)
self.cameraSelection = NetworkTableInstance.getDefault().getTable("").getEntry("CameraSelection")
wpilib.CameraServer.launch("vision.py:main")
def teleopPeriodic(self):
if self.joy1.getTriggerPressed():
print("Setting camera 2")
self.cameraSelection.setString("USB Camera 1")
elif self.joy1.getTriggerReleased():
print("Setting camera 1")
self.cameraSelection.setString("USB Camera 0")
vision.py contents:
from cscore import CameraServer
def main():
CameraServer.enableLogging()
camera1 = CameraServer.startAutomaticCapture(0)
camera2 = CameraServer.startAutomaticCapture(1)
CameraServer.waitForever()
pyproject.toml contents (this only shows the portions you need to update):
[tool.robotpy]
...
# Add cscore to the components list
components = ["cscore"]
如果使用其他仪表板,则可以通过动态更改相机服务器来改变所使用的相机。如果你在名称上选择打开camera1的数据流查看器,则机器人代码将根据操纵杆触发器将流内容更改为camera1或camera2
UsbCamera camera1;
UsbCamera camera2;
VideoSink server;
Joystick joy1 = new Joystick(0);
public Robot() {
camera1 = CameraServer.startAutomaticCapture(0);
camera2 = CameraServer.startAutomaticCapture(1);
server = CameraServer.getServer();
}
@Override
public void teleopPeriodic() {
if (joy1.getTriggerPressed()) {
System.out.println("Setting camera 2");
server.setSource(camera2);
} else if (joy1.getTriggerReleased()) {
System.out.println("Setting camera 1");
server.setSource(camera1);
}
}
cs::UsbCamera camera1;
cs::UsbCamera camera2;
cs::VideoSink server;
frc::Joystick joy1{0};
bool prevTrigger = false;
Robot() {
camera1 = frc::CameraServer::StartAutomaticCapture(0);
camera2 = frc::CameraServer::StartAutomaticCapture(1);
server = frc::CameraServer::GetServer();
}
void TeleopPeriodic() override {
if (joy1.GetTrigger() && !prevTrigger) {
std::cout << "Setting Camera 2" << std::endl;
server.SetSource(camera2);
} else if (!joy1.GetTrigger() && prevTrigger) {
std::cout << "Setting Camera 1" << std::endl;
server.SetSource(camera1);
}
prevTrigger = joy1.GetTrigger();
}
# Setting the source directly via joystick isn't possible in Python, you
# should use NetworkTables as shown above instead
保持数据流开放
默认情况下,cscore库通常主动地关闭未使用的相机。这意味着当您切换相机时,它可能会与未使用的相机断开连接,因此,在重新连接到相机时,切换回会有一些延迟。即使在没有使用的情况下,也要保持两个相机的连接都打开,请使用“SetConnectionStrategy()”方法让库保持数据流开放
UsbCamera camera1;
UsbCamera camera2;
VideoSink server;
Joystick joy1 = new Joystick(0);
public Robot() {
camera1 = CameraServer.startAutomaticCapture(0);
camera2 = CameraServer.startAutomaticCapture(1);
server = CameraServer.getServer();
camera1.setConnectionStrategy(ConnectionStrategy.kKeepOpen);
camera2.setConnectionStrategy(ConnectionStrategy.kKeepOpen);
}
@Override
public void teleopPeriodic() {
if (joy1.getTriggerPressed()) {
System.out.println("Setting camera 2");
server.setSource(camera2);
} else if (joy1.getTriggerReleased()) {
System.out.println("Setting camera 1");
server.setSource(camera1);
}
}
cs::UsbCamera camera1;
cs::UsbCamera camera2;
cs::VideoSink server;
frc::Joystick joy1{0};
bool prevTrigger = false;
Robot() {
camera1 = frc::CameraServer::StartAutomaticCapture(0);
camera2 = frc::CameraServer::StartAutomaticCapture(1);
server = frc::CameraServer::GetServer();
camera1.SetConnectionStrategy(cs::VideoSource::ConnectionStrategy::kConnectionKeepOpen);
camera2.SetConnectionStrategy(cs::VideoSource::ConnectionStrategy::kConnectionKeepOpen);
}
void TeleopPeriodic() override {
if (joy1.GetTrigger() && !prevTrigger) {
std::cout << "Setting Camera 2" << std::endl;
server.SetSource(camera2);
} else if (!joy1.GetTrigger() && prevTrigger) {
std::cout << "Setting Camera 1" << std::endl;
server.SetSource(camera1);
}
prevTrigger = joy1.GetTrigger();
}
备注
Python requires you to place your image processing code in a separate file from your robot code. You can create robot.py and vision.py in the same directory.
robot.py contents:
import wpilib
from ntcore import NetworkTableInstance
class MyRobot(wpilib.TimedRobot):
def robotInit(self):
self.joy1 = wpilib.Joystick(0)
self.cameraSelection = NetworkTableInstance.getDefault().getTable("").getEntry("CameraSelection")
wpilib.CameraServer.launch("vision.py:main")
def teleopPeriodic(self):
if self.joy1.getTriggerPressed():
print("Setting camera 2")
self.cameraSelection.setString("USB Camera 1")
elif self.joy1.getTriggerReleased():
print("Setting camera 1")
self.cameraSelection.setString("USB Camera 0")
vision.py contents:
from cscore import CameraServer, VideoSource
def main():
CameraServer.enableLogging()
camera1 = CameraServer.startAutomaticCapture(0)
camera2 = CameraServer.startAutomaticCapture(1)
camera1.setConnectionStrategy(VideoSource.ConnectionStrategy.kConnectionKeepOpen)
camera2.setConnectionStrategy(VideoSource.ConnectionStrategy.kConnectionKeepOpen)
CameraServer.waitForever()
pyproject.toml contents (this only shows the portions you need to update):
[tool.robotpy]
...
# Add cscore to the components list
components = ["cscore"]
备注
如果两个相机都是USB端口,则可能会遇到分辨率更高的USB带宽限制,因为在所有这些情况下,roboRIO都将同时将数据从两个相机传输到roboRIO(在选项1和2的短时间内,以及在选项3中连续输入)。从理论上讲,库有可能(仅)在选项2的情况下避免这种同时发生,但目前尚未实现。
不同的相机会报告的带宽使用情况有所不同,如果已达到极限,库会通过提示错误消息来提醒你:
could not start streaming due to USB bandwidth limitations;
try a lower resolution or a different pixel format
(VIDIOC_STREAMON: No space left on device)
If you’re using Option 3 it will give you this error during the Robot constructor. Thus you should just try your desired resolution and adjusting as necessary until you both don’t get that error and don’t exceed the radio bandwidth limitations.