使用多台相机
切换驱动程序视图
如果您只想更改驱动程序的外观并正在使用SmartDashboard,则SmartDashboard CameraServer Stream Viewer具有一个选项(“选定的相机路径”),该选项读取给定的:term:`NetworkTables`键并更改“相机选择” ”设置为该值(显示该摄像机)。然后,机器人代码只需要将NetworkTables键设置为正确的摄像机名称即可。假设“选定的摄像机路径”设置为“ CameraSelection”,下面的代码使用操纵杆1触发按钮状态来显示camera1和camera2。
UsbCamera camera1;
UsbCamera camera2;
Joystick joy1 = new Joystick(0);
NetworkTableEntry cameraSelection;
@Override
public void robotInit() {
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;
void RobotInit() override {
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());
}
}
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()
如果使用其他仪表板,则可以通过动态更改相机服务器来改变所使用的相机。如果你在名称上选择打开camera1的数据流查看器,则机器人代码将根据操纵杆触发器将流内容更改为camera1或camera2
UsbCamera camera1;
UsbCamera camera2;
VideoSink server;
Joystick joy1 = new Joystick(0);
@Override
public void robotInit() {
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;
void RobotInit() override {
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);
@Override
public void robotInit() {
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;
void RobotInit() override {
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();
}
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()
备注
如果两个相机都是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)
如果您使用的是选项3,则会在“ RobotInit()”期间出现此错误。因此,你应该只尝试所需的分辨率并根据需要进行调整,直到两边都没有收到该错误提醒并且未超过带宽限制。