mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-21 01:01:43 +00:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
12f759860e | ||
|
|
1bdbb5ddcc | ||
|
|
b573fb6555 | ||
|
|
b50a7bdbee | ||
|
|
5a5f10dfc8 | ||
|
|
e375b4a9ff | ||
|
|
ff141ab1ff | ||
|
|
b8537be219 | ||
|
|
8f1b034b2f | ||
|
|
71d0a07e0a | ||
|
|
d322342494 |
@@ -78,7 +78,7 @@ void HAL_InitializeI2C(int32_t port, int32_t* status) {
|
||||
* @param sendSize Number of bytes to send as part of the transaction.
|
||||
* @param dataReceived Buffer to read data into.
|
||||
* @param receiveSize Number of bytes to read from the device.
|
||||
* @return The number of bytes read (>= 0) or -1 on transfer abort.
|
||||
* @return >= 0 on success or -1 on transfer abort.
|
||||
*/
|
||||
int32_t HAL_TransactionI2C(int32_t port, int32_t deviceAddress,
|
||||
uint8_t* dataToSend, int32_t sendSize,
|
||||
@@ -110,7 +110,7 @@ int32_t HAL_TransactionI2C(int32_t port, int32_t deviceAddress,
|
||||
* @param registerAddress The address of the register on the device to be
|
||||
* written.
|
||||
* @param data The byte to write to the register on the device.
|
||||
* @return The number of bytes written (>= 0) or -1 on transfer abort.
|
||||
* @return >= 0 on success or -1 on transfer abort.
|
||||
*/
|
||||
int32_t HAL_WriteI2C(int32_t port, int32_t deviceAddress, uint8_t* dataToSend,
|
||||
int32_t sendSize) {
|
||||
@@ -140,7 +140,7 @@ int32_t HAL_WriteI2C(int32_t port, int32_t deviceAddress, uint8_t* dataToSend,
|
||||
* @param count The number of bytes to read in the transaction.
|
||||
* @param buffer A pointer to the array of bytes to store the data read from the
|
||||
* device.
|
||||
* @return The number of bytes read (>= 0) or -1 on transfer abort.
|
||||
* @return >= 0 on success or -1 on transfer abort.
|
||||
*/
|
||||
int32_t HAL_ReadI2C(int32_t port, int32_t deviceAddress, uint8_t* buffer,
|
||||
int32_t count) {
|
||||
|
||||
@@ -55,8 +55,7 @@ HAL_SolenoidHandle HAL_InitializeSolenoidPort(HAL_PortHandle portHandle,
|
||||
|
||||
auto handle =
|
||||
solenoidHandles.Allocate(module * kNumSolenoidChannels + channel, status);
|
||||
if (handle == HAL_kInvalidHandle) { // out of resources
|
||||
*status = NO_AVAILABLE_RESOURCES;
|
||||
if (*status != 0) {
|
||||
return HAL_kInvalidHandle;
|
||||
}
|
||||
auto solenoidPort = solenoidHandles.Get(handle);
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
@@ -44,8 +45,10 @@ class CameraServer : public ErrorBase {
|
||||
* If you also want to perform vision processing on the roboRIO, use
|
||||
* getVideo() to get access to the camera images.
|
||||
*
|
||||
* This overload calls {@link #StartAutomaticCapture(int)} with device 0,
|
||||
* creating a camera named "USB Camera 0".
|
||||
* The first time this overload is called, it calls
|
||||
* {@link #StartAutomaticCapture(int)} with device 0, creating a camera
|
||||
* named "USB Camera 0". Subsequent calls increment the device number
|
||||
* (e.g. 1, 2, etc).
|
||||
*/
|
||||
cs::UsbCamera StartAutomaticCapture();
|
||||
|
||||
@@ -241,6 +244,21 @@ class CameraServer : public ErrorBase {
|
||||
*/
|
||||
void RemoveServer(llvm::StringRef name);
|
||||
|
||||
/**
|
||||
* Get server for the primary camera feed.
|
||||
*
|
||||
* <p>This is only valid to call after a camera feed has been added
|
||||
* with StartAutomaticCapture() or AddServer().
|
||||
*/
|
||||
cs::VideoSink GetServer();
|
||||
|
||||
/**
|
||||
* Gets a server by name.
|
||||
*
|
||||
* @param name Server name
|
||||
*/
|
||||
cs::VideoSink GetServer(llvm::StringRef name);
|
||||
|
||||
/**
|
||||
* Adds an already created camera.
|
||||
*
|
||||
@@ -277,6 +295,7 @@ class CameraServer : public ErrorBase {
|
||||
static constexpr char const* kPublishName = "/CameraPublisher";
|
||||
|
||||
std::mutex m_mutex;
|
||||
std::atomic<int> m_defaultUsbDevice;
|
||||
std::string m_primarySourceName;
|
||||
llvm::StringMap<cs::VideoSource> m_sources;
|
||||
llvm::StringMap<cs::VideoSink> m_sinks;
|
||||
|
||||
@@ -171,7 +171,7 @@ static std::string PixelFormatToString(int pixelFormat) {
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
static cs::VideoMode::PixelFormat PixelFormatFromString(llvm::StringRef str) {
|
||||
if (str == "MJPEG" || str == "mjpeg" || str == "JPEG" || str == "jpeg")
|
||||
return cs::VideoMode::PixelFormat::kMJPEG;
|
||||
@@ -228,7 +228,7 @@ static cs::VideoMode VideoModeFromString(llvm::StringRef modeStr) {
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
#endif
|
||||
static std::string VideoModeToString(const cs::VideoMode& mode) {
|
||||
std::string rv;
|
||||
llvm::raw_string_ostream oss{rv};
|
||||
@@ -261,9 +261,9 @@ static void PutSourcePropertyValue(ITable* table, const cs::VideoEvent& event,
|
||||
llvm::SmallString<64> infoName;
|
||||
if (llvm::StringRef{event.name}.startswith("raw_")) {
|
||||
name = "RawProperty/";
|
||||
name += llvm::StringRef{event.name}.substr(4);
|
||||
name += event.name;
|
||||
infoName = "RawPropertyInfo/";
|
||||
infoName += llvm::StringRef{event.name}.substr(4);
|
||||
infoName += event.name;
|
||||
} else {
|
||||
name = "Property/";
|
||||
name += event.name;
|
||||
@@ -427,6 +427,9 @@ CameraServer::CameraServer()
|
||||
0x4fff, true};
|
||||
|
||||
// Listener for NetworkTable events
|
||||
// We don't currently support changing settings via NT due to
|
||||
// synchronization issues, so just update to current setting if someone
|
||||
// else tries to change it.
|
||||
llvm::SmallString<64> buf;
|
||||
m_tableListener = nt::AddEntryListener(
|
||||
Concatenate(kPublishName, "/", buf),
|
||||
@@ -446,24 +449,16 @@ CameraServer::CameraServer()
|
||||
relativeKey = relativeKey.substr(subKeyIndex + 1);
|
||||
|
||||
// handle standard names
|
||||
llvm::SmallString<64> propNameBuf;
|
||||
llvm::StringRef propName;
|
||||
if (relativeKey == "mode") {
|
||||
if (!value->IsString()) return;
|
||||
auto mode = VideoModeFromString(value->GetString());
|
||||
if (mode.pixelFormat == cs::VideoMode::PixelFormat::kUnknown ||
|
||||
!sourceIt->second.SetVideoMode(mode)) {
|
||||
// reset to current mode
|
||||
nt::SetEntryValue(key, nt::Value::MakeString(VideoModeToString(
|
||||
sourceIt->second.GetVideoMode())));
|
||||
}
|
||||
// reset to current mode
|
||||
nt::SetEntryValue(key, nt::Value::MakeString(VideoModeToString(
|
||||
sourceIt->second.GetVideoMode())));
|
||||
return;
|
||||
} else if (relativeKey.startswith("Property/")) {
|
||||
propName = relativeKey.substr(9);
|
||||
} else if (relativeKey.startswith("RawProperty/")) {
|
||||
propNameBuf = "raw_";
|
||||
propNameBuf += relativeKey.substr(12);
|
||||
propName = propNameBuf.str();
|
||||
propName = relativeKey.substr(12);
|
||||
} else {
|
||||
return; // ignore
|
||||
}
|
||||
@@ -474,17 +469,14 @@ CameraServer::CameraServer()
|
||||
case cs::VideoProperty::kNone:
|
||||
return;
|
||||
case cs::VideoProperty::kBoolean:
|
||||
if (!value->IsBoolean()) return;
|
||||
property.Set(value->GetBoolean() ? 1 : 0);
|
||||
nt::SetEntryValue(key, nt::Value::MakeBoolean(property.Get() != 0));
|
||||
return;
|
||||
case cs::VideoProperty::kInteger:
|
||||
case cs::VideoProperty::kEnum:
|
||||
if (!value->IsDouble()) return;
|
||||
property.Set(static_cast<int>(value->GetDouble()));
|
||||
nt::SetEntryValue(key, nt::Value::MakeDouble(property.Get()));
|
||||
return;
|
||||
case cs::VideoProperty::kString:
|
||||
if (!value->IsString()) return;
|
||||
property.SetString(value->GetString());
|
||||
nt::SetEntryValue(key, nt::Value::MakeString(property.GetString()));
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
@@ -494,7 +486,7 @@ CameraServer::CameraServer()
|
||||
}
|
||||
|
||||
cs::UsbCamera CameraServer::StartAutomaticCapture() {
|
||||
return StartAutomaticCapture(0);
|
||||
return StartAutomaticCapture(m_defaultUsbDevice++);
|
||||
}
|
||||
|
||||
cs::UsbCamera CameraServer::StartAutomaticCapture(int dev) {
|
||||
@@ -667,6 +659,33 @@ void CameraServer::RemoveServer(llvm::StringRef name) {
|
||||
m_sinks.erase(name);
|
||||
}
|
||||
|
||||
cs::VideoSink CameraServer::GetServer() {
|
||||
llvm::SmallString<64> name;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
if (m_primarySourceName.empty()) {
|
||||
wpi_setWPIErrorWithContext(CameraServerError, "no camera available");
|
||||
return cs::VideoSink{};
|
||||
}
|
||||
name = "serve_";
|
||||
name += m_primarySourceName;
|
||||
}
|
||||
return GetServer(name);
|
||||
}
|
||||
|
||||
cs::VideoSink CameraServer::GetServer(llvm::StringRef name) {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
auto it = m_sinks.find(name);
|
||||
if (it == m_sinks.end()) {
|
||||
llvm::SmallString<64> buf;
|
||||
llvm::raw_svector_ostream err{buf};
|
||||
err << "could not find server " << name;
|
||||
wpi_setWPIErrorWithContext(CameraServerError, err.str());
|
||||
return cs::VideoSink{};
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
void CameraServer::AddCamera(const cs::VideoSource& camera) {
|
||||
std::string name = camera.GetName();
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
@@ -51,7 +51,7 @@ bool I2C::Transaction(uint8_t* dataToSend, int sendSize, uint8_t* dataReceived,
|
||||
status = HAL_TransactionI2C(m_port, m_deviceAddress, dataToSend, sendSize,
|
||||
dataReceived, receiveSize);
|
||||
// wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
|
||||
return status < receiveSize;
|
||||
return status < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,7 +81,7 @@ bool I2C::Write(int registerAddress, uint8_t data) {
|
||||
buffer[1] = data;
|
||||
int32_t status = 0;
|
||||
status = HAL_WriteI2C(m_port, m_deviceAddress, buffer, sizeof(buffer));
|
||||
return status < static_cast<int>(sizeof(buffer));
|
||||
return status < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,7 +97,7 @@ bool I2C::Write(int registerAddress, uint8_t data) {
|
||||
bool I2C::WriteBulk(uint8_t* data, int count) {
|
||||
int32_t status = 0;
|
||||
status = HAL_WriteI2C(m_port, m_deviceAddress, data, count);
|
||||
return status < count;
|
||||
return status < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -122,8 +122,8 @@ bool I2C::Read(int registerAddress, int count, uint8_t* buffer) {
|
||||
wpi_setWPIErrorWithContext(NullParameter, "buffer");
|
||||
return true;
|
||||
}
|
||||
return Transaction(reinterpret_cast<uint8_t*>(®isterAddress),
|
||||
sizeof(registerAddress), buffer, count);
|
||||
uint8_t regAddr = registerAddress;
|
||||
return Transaction(®Addr, sizeof(regAddr), buffer, count);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,9 +146,7 @@ bool I2C::ReadOnly(int count, uint8_t* buffer) {
|
||||
wpi_setWPIErrorWithContext(NullParameter, "buffer");
|
||||
return true;
|
||||
}
|
||||
int32_t status = 0;
|
||||
status = HAL_ReadI2C(m_port, m_deviceAddress, buffer, count);
|
||||
return status < count;
|
||||
return HAL_ReadI2C(m_port, m_deviceAddress, buffer, count) < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -140,14 +140,14 @@ RobotDrive::RobotDrive(std::shared_ptr<SpeedController> leftMotor,
|
||||
*
|
||||
* Speed controller input version of RobotDrive (see previous comments).
|
||||
*
|
||||
* @param rearLeftMotor The back left SpeedController object used to drive
|
||||
* the robot.
|
||||
* @param frontLeftMotor The front left SpeedController object used to drive
|
||||
* the robot.
|
||||
* @param rearRightMotor The back right SpeedController object used to drive
|
||||
* @param rearLeftMotor The back left SpeedController object used to drive
|
||||
* the robot.
|
||||
* @param frontRightMotor The front right SpeedController object used to drive
|
||||
* the robot.
|
||||
* @param rearRightMotor The back right SpeedController object used to drive
|
||||
* the robot.
|
||||
*/
|
||||
RobotDrive::RobotDrive(SpeedController* frontLeftMotor,
|
||||
SpeedController* rearLeftMotor,
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include "HAL/HAL.h"
|
||||
#include "WPIErrors.h"
|
||||
#include "llvm/SmallVector.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
@@ -147,9 +148,9 @@ int SPI::Write(uint8_t* data, int size) {
|
||||
int SPI::Read(bool initiate, uint8_t* dataReceived, int size) {
|
||||
int retVal = 0;
|
||||
if (initiate) {
|
||||
auto dataToSend = new uint8_t[size];
|
||||
std::memset(dataToSend, 0, size);
|
||||
retVal = HAL_TransactionSPI(m_port, dataToSend, dataReceived, size);
|
||||
llvm::SmallVector<uint8_t, 32> dataToSend;
|
||||
dataToSend.resize(size);
|
||||
retVal = HAL_TransactionSPI(m_port, dataToSend.data(), dataReceived, size);
|
||||
} else {
|
||||
retVal = HAL_ReadSPI(m_port, dataReceived, size);
|
||||
}
|
||||
|
||||
@@ -230,7 +230,6 @@ bool DriverStation::IsTest() const {
|
||||
|
||||
/**
|
||||
* Is the driver station attached to a Field Management System?
|
||||
* Note: This does not work with the Blue DS.
|
||||
* @return True if the robot is competing on a field being controlled by a Field
|
||||
* Management System
|
||||
*/
|
||||
|
||||
@@ -24,8 +24,9 @@ import edu.wpi.cscore.VideoSource;
|
||||
import edu.wpi.first.wpilibj.networktables.NetworkTable;
|
||||
import edu.wpi.first.wpilibj.networktables.NetworkTablesJNI;
|
||||
import edu.wpi.first.wpilibj.tables.ITable;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Hashtable;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -49,20 +50,21 @@ public class CameraServer {
|
||||
/**
|
||||
* Get the CameraServer instance.
|
||||
*/
|
||||
public static CameraServer getInstance() {
|
||||
public static synchronized CameraServer getInstance() {
|
||||
if (server == null) {
|
||||
server = new CameraServer();
|
||||
}
|
||||
return server;
|
||||
}
|
||||
|
||||
private AtomicInteger m_defaultUsbDevice;
|
||||
private String m_primarySourceName;
|
||||
private HashMap<String, VideoSource> m_sources;
|
||||
private HashMap<String, VideoSink> m_sinks;
|
||||
private HashMap<Integer, ITable> m_tables; // indexed by source handle
|
||||
private ITable m_publishTable;
|
||||
private VideoListener m_videoListener; //NOPMD
|
||||
private int m_tableListener; //NOPMD
|
||||
private final Hashtable<String, VideoSource> m_sources;
|
||||
private final Hashtable<String, VideoSink> m_sinks;
|
||||
private final Hashtable<Integer, ITable> m_tables; // indexed by source handle
|
||||
private final ITable m_publishTable;
|
||||
private final VideoListener m_videoListener; //NOPMD
|
||||
private final int m_tableListener; //NOPMD
|
||||
private int m_nextPort;
|
||||
private String[] m_addresses;
|
||||
|
||||
@@ -93,11 +95,6 @@ public class CameraServer {
|
||||
return "mjpg:http://" + address + ":" + port + "/?action=stream";
|
||||
}
|
||||
|
||||
@SuppressWarnings("JavadocMethod")
|
||||
private synchronized ITable getSourceTable(int source) {
|
||||
return m_tables.get(source);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"JavadocMethod", "PMD.AvoidUsingHardCodedIP"})
|
||||
private synchronized String[] getSinkStreamValues(int sink) {
|
||||
// Ignore all but MjpegServer
|
||||
@@ -290,8 +287,8 @@ public class CameraServer {
|
||||
String name;
|
||||
String infoName;
|
||||
if (event.name.startsWith("raw_")) {
|
||||
name = "RawProperty/" + event.name.substring(4);
|
||||
infoName = "RawPropertyInfo/" + event.name.substring(4);
|
||||
name = "RawProperty/" + event.name;
|
||||
infoName = "RawPropertyInfo/" + event.name;
|
||||
} else {
|
||||
name = "Property/" + event.name;
|
||||
infoName = "PropertyInfo/" + event.name;
|
||||
@@ -335,9 +332,10 @@ public class CameraServer {
|
||||
|
||||
@SuppressWarnings({"JavadocMethod", "PMD.UnusedLocalVariable"})
|
||||
private CameraServer() {
|
||||
m_sources = new HashMap<String, VideoSource>();
|
||||
m_sinks = new HashMap<String, VideoSink>();
|
||||
m_tables = new HashMap<Integer, ITable>();
|
||||
m_defaultUsbDevice = new AtomicInteger();
|
||||
m_sources = new Hashtable<String, VideoSource>();
|
||||
m_sinks = new Hashtable<String, VideoSink>();
|
||||
m_tables = new Hashtable<Integer, ITable>();
|
||||
m_publishTable = NetworkTable.getTable(kPublishName);
|
||||
m_nextPort = kBasePort;
|
||||
m_addresses = new String[0];
|
||||
@@ -359,21 +357,23 @@ public class CameraServer {
|
||||
case kSourceCreated: {
|
||||
// Create subtable for the camera
|
||||
ITable table = m_publishTable.getSubTable(event.name);
|
||||
synchronized (this) {
|
||||
m_tables.put(event.sourceHandle, table);
|
||||
}
|
||||
m_tables.put(event.sourceHandle, table);
|
||||
table.putString("source", makeSourceValue(event.sourceHandle));
|
||||
table.putString("description",
|
||||
CameraServerJNI.getSourceDescription(event.sourceHandle));
|
||||
table.putBoolean("connected", CameraServerJNI.isSourceConnected(event.sourceHandle));
|
||||
table.putStringArray("streams", getSourceStreamValues(event.sourceHandle));
|
||||
VideoMode mode = CameraServerJNI.getSourceVideoMode(event.sourceHandle);
|
||||
table.setDefaultString("mode", videoModeToString(mode));
|
||||
table.putStringArray("modes", getSourceModeValues(event.sourceHandle));
|
||||
try {
|
||||
VideoMode mode = CameraServerJNI.getSourceVideoMode(event.sourceHandle);
|
||||
table.setDefaultString("mode", videoModeToString(mode));
|
||||
table.putStringArray("modes", getSourceModeValues(event.sourceHandle));
|
||||
} catch (VideoException ex) {
|
||||
// Do nothing. Let the other event handlers update this if there is an error.
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kSourceDestroyed: {
|
||||
ITable table = getSourceTable(event.sourceHandle);
|
||||
ITable table = m_tables.get(event.sourceHandle);
|
||||
if (table != null) {
|
||||
table.putString("source", "");
|
||||
table.putStringArray("streams", new String[0]);
|
||||
@@ -382,7 +382,7 @@ public class CameraServer {
|
||||
break;
|
||||
}
|
||||
case kSourceConnected: {
|
||||
ITable table = getSourceTable(event.sourceHandle);
|
||||
ITable table = m_tables.get(event.sourceHandle);
|
||||
if (table != null) {
|
||||
// update the description too (as it may have changed)
|
||||
table.putString("description",
|
||||
@@ -392,42 +392,42 @@ public class CameraServer {
|
||||
break;
|
||||
}
|
||||
case kSourceDisconnected: {
|
||||
ITable table = getSourceTable(event.sourceHandle);
|
||||
ITable table = m_tables.get(event.sourceHandle);
|
||||
if (table != null) {
|
||||
table.putBoolean("connected", false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kSourceVideoModesUpdated: {
|
||||
ITable table = getSourceTable(event.sourceHandle);
|
||||
ITable table = m_tables.get(event.sourceHandle);
|
||||
if (table != null) {
|
||||
table.putStringArray("modes", getSourceModeValues(event.sourceHandle));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kSourceVideoModeChanged: {
|
||||
ITable table = getSourceTable(event.sourceHandle);
|
||||
ITable table = m_tables.get(event.sourceHandle);
|
||||
if (table != null) {
|
||||
table.putString("mode", videoModeToString(event.mode));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kSourcePropertyCreated: {
|
||||
ITable table = getSourceTable(event.sourceHandle);
|
||||
ITable table = m_tables.get(event.sourceHandle);
|
||||
if (table != null) {
|
||||
putSourcePropertyValue(table, event, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kSourcePropertyValueUpdated: {
|
||||
ITable table = getSourceTable(event.sourceHandle);
|
||||
ITable table = m_tables.get(event.sourceHandle);
|
||||
if (table != null) {
|
||||
putSourcePropertyValue(table, event, false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kSourcePropertyChoicesUpdated: {
|
||||
ITable table = getSourceTable(event.sourceHandle);
|
||||
ITable table = m_tables.get(event.sourceHandle);
|
||||
if (table != null) {
|
||||
String[] choices = CameraServerJNI.getEnumPropertyChoices(event.propertyHandle);
|
||||
table.putStringArray("PropertyInfo/" + event.name + "/choices", choices);
|
||||
@@ -450,8 +450,11 @@ public class CameraServer {
|
||||
}, 0x4fff, true);
|
||||
|
||||
// Listener for NetworkTable events
|
||||
// We don't currently support changing settings via NT due to
|
||||
// synchronization issues, so just update to current setting if someone
|
||||
// else tries to change it.
|
||||
m_tableListener = NetworkTablesJNI.addEntryListener(kPublishName + "/",
|
||||
(uid, key, value, flags) -> {
|
||||
(uid, key, eventValue, flags) -> {
|
||||
String relativeKey = key.substring(kPublishName.length() + 1);
|
||||
|
||||
// get source (sourceName/...)
|
||||
@@ -471,16 +474,13 @@ public class CameraServer {
|
||||
// handle standard names
|
||||
String propName;
|
||||
if (relativeKey.equals("mode")) {
|
||||
VideoMode mode = videoModeFromString((String) value);
|
||||
if (mode.pixelFormat == PixelFormat.kUnknown || !source.setVideoMode(mode)) {
|
||||
// reset to current mode
|
||||
NetworkTablesJNI.putString(key, videoModeToString(source.getVideoMode()));
|
||||
}
|
||||
// reset to current mode
|
||||
NetworkTablesJNI.putString(key, videoModeToString(source.getVideoMode()));
|
||||
return;
|
||||
} else if (relativeKey.startsWith("Property/")) {
|
||||
propName = relativeKey.substring(9);
|
||||
} else if (relativeKey.startsWith("RawProperty/")) {
|
||||
propName = "raw_" + relativeKey.substring(12);
|
||||
propName = relativeKey.substring(12);
|
||||
} else {
|
||||
return; // ignore
|
||||
}
|
||||
@@ -491,14 +491,17 @@ public class CameraServer {
|
||||
case kNone:
|
||||
return;
|
||||
case kBoolean:
|
||||
property.set(((Boolean) value).booleanValue() ? 1 : 0);
|
||||
// reset to current setting
|
||||
NetworkTablesJNI.putBoolean(key, property.get() != 0);
|
||||
return;
|
||||
case kInteger:
|
||||
case kEnum:
|
||||
property.set(((Double) value).intValue());
|
||||
// reset to current setting
|
||||
NetworkTablesJNI.putDouble(key, property.get());
|
||||
return;
|
||||
case kString:
|
||||
property.setString((String) value);
|
||||
// reset to current setting
|
||||
NetworkTablesJNI.putString(key, property.getString());
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
@@ -513,11 +516,13 @@ public class CameraServer {
|
||||
* If you also want to perform vision processing on the roboRIO, use
|
||||
* getVideo() to get access to the camera images.
|
||||
*
|
||||
* <p>This overload calls {@link #startAutomaticCapture(int)} with device 0,
|
||||
* creating a camera named "USB Camera 0".
|
||||
* <p>The first time this overload is called, it calls
|
||||
* {@link #startAutomaticCapture(int)} with device 0, creating a camera
|
||||
* named "USB Camera 0". Subsequent calls increment the device number
|
||||
* (e.g. 1, 2, etc).
|
||||
*/
|
||||
public UsbCamera startAutomaticCapture() {
|
||||
return startAutomaticCapture(0);
|
||||
return startAutomaticCapture(m_defaultUsbDevice.getAndIncrement());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -745,6 +750,32 @@ public class CameraServer {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get server for the primary camera feed.
|
||||
*
|
||||
* <p>This is only valid to call after a camera feed has been added
|
||||
* with startAutomaticCapture() or addServer().
|
||||
*/
|
||||
public VideoSink getServer() {
|
||||
synchronized (this) {
|
||||
if (m_primarySourceName == null) {
|
||||
throw new VideoException("no camera available");
|
||||
}
|
||||
return getServer("serve_" + m_primarySourceName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a server by name.
|
||||
*
|
||||
* @param name Server name
|
||||
*/
|
||||
public VideoSink getServer(String name) {
|
||||
synchronized (this) {
|
||||
return m_sinks.get(name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an already created camera.
|
||||
*
|
||||
|
||||
@@ -546,9 +546,9 @@ public class DriverStation implements RobotState.Interface {
|
||||
return m_newControlData.getAndSet(false);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"SummaryJavadoc", "JavadocMethod"})
|
||||
/**
|
||||
* Is the driver station attached to a Field Management System? Note: This does not work with the
|
||||
* Blue DS.
|
||||
* Is the driver station attached to a Field Management System?
|
||||
*
|
||||
* @return True if the robot is competing on a field being controlled by a Field Management System
|
||||
*/
|
||||
|
||||
@@ -83,7 +83,7 @@ public class I2C extends SensorBase {
|
||||
if (receiveSize > 0 && dataReceived != null) {
|
||||
dataReceivedBuffer.get(dataReceived);
|
||||
}
|
||||
return status < receiveSize;
|
||||
return status < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,7 +117,7 @@ public class I2C extends SensorBase {
|
||||
}
|
||||
|
||||
return I2CJNI.i2CTransaction((byte) m_port.value, (byte) m_deviceAddress, dataToSend,
|
||||
(byte) sendSize, dataReceived, (byte) receiveSize) < receiveSize;
|
||||
(byte) sendSize, dataReceived, (byte) receiveSize) < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -139,6 +139,7 @@ public class I2C extends SensorBase {
|
||||
*
|
||||
* @param registerAddress The address of the register on the device to be written.
|
||||
* @param data The byte to write to the register on the device.
|
||||
* @return Transfer Aborted... false for success, true for aborted.
|
||||
*/
|
||||
public synchronized boolean write(int registerAddress, int data) {
|
||||
byte[] buffer = new byte[2];
|
||||
@@ -149,7 +150,7 @@ public class I2C extends SensorBase {
|
||||
dataToSendBuffer.put(buffer);
|
||||
|
||||
return I2CJNI.i2CWrite((byte) m_port.value, (byte) m_deviceAddress, dataToSendBuffer,
|
||||
(byte) buffer.length) < buffer.length;
|
||||
(byte) buffer.length) < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -158,13 +159,14 @@ public class I2C extends SensorBase {
|
||||
* <p>Write multiple bytes to a register on a device and wait until the transaction is complete.
|
||||
*
|
||||
* @param data The data to write to the device.
|
||||
* @return Transfer Aborted... false for success, true for aborted.
|
||||
*/
|
||||
public synchronized boolean writeBulk(byte[] data) {
|
||||
ByteBuffer dataToSendBuffer = ByteBuffer.allocateDirect(data.length);
|
||||
dataToSendBuffer.put(data);
|
||||
|
||||
return I2CJNI.i2CWrite((byte) m_port.value, (byte) m_deviceAddress, dataToSendBuffer,
|
||||
(byte) data.length) < data.length;
|
||||
(byte) data.length) < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -173,6 +175,7 @@ public class I2C extends SensorBase {
|
||||
* <p>Write multiple bytes to a register on a device and wait until the transaction is complete.
|
||||
*
|
||||
* @param data The data to write to the device. Must be created using ByteBuffer.allocateDirect().
|
||||
* @return Transfer Aborted... false for success, true for aborted.
|
||||
*/
|
||||
public synchronized boolean writeBulk(ByteBuffer data, int size) {
|
||||
if (!data.isDirect()) {
|
||||
@@ -183,7 +186,7 @@ public class I2C extends SensorBase {
|
||||
"buffer is too small, must be at least " + size);
|
||||
}
|
||||
|
||||
return I2CJNI.i2CWrite((byte) m_port.value, (byte) m_deviceAddress, data, (byte) size) < size;
|
||||
return I2CJNI.i2CWrite((byte) m_port.value, (byte) m_deviceAddress, data, (byte) size) < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -264,7 +267,7 @@ public class I2C extends SensorBase {
|
||||
int retVal = I2CJNI.i2CRead((byte) m_port.value, (byte) m_deviceAddress, dataReceivedBuffer,
|
||||
(byte) count);
|
||||
dataReceivedBuffer.get(buffer);
|
||||
return retVal < count;
|
||||
return retVal < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -291,7 +294,7 @@ public class I2C extends SensorBase {
|
||||
}
|
||||
|
||||
return I2CJNI.i2CRead((byte) m_port.value, (byte) m_deviceAddress, buffer, (byte) count)
|
||||
< count;
|
||||
< 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -128,10 +128,10 @@ public class RobotDrive implements MotorSafety {
|
||||
* Constructor for RobotDrive with 4 motors specified as SpeedController objects. Speed controller
|
||||
* input version of RobotDrive (see previous comments).
|
||||
*
|
||||
* @param rearLeftMotor The back left SpeedController object used to drive the robot.
|
||||
* @param frontLeftMotor The front left SpeedController object used to drive the robot
|
||||
* @param rearRightMotor The back right SpeedController object used to drive the robot.
|
||||
* @param rearLeftMotor The back left SpeedController object used to drive the robot.
|
||||
* @param frontRightMotor The front right SpeedController object used to drive the robot.
|
||||
* @param rearRightMotor The back right SpeedController object used to drive the robot.
|
||||
*/
|
||||
public RobotDrive(SpeedController frontLeftMotor, SpeedController rearLeftMotor,
|
||||
SpeedController frontRightMotor, SpeedController rearRightMotor) {
|
||||
|
||||
@@ -74,7 +74,7 @@ public class SafePWM extends PWM implements MotorSafety {
|
||||
|
||||
/**
|
||||
* Feed the MotorSafety timer. This method is called by the subclass motor whenever it updates its
|
||||
* speed, thereby reseting the timeout value.
|
||||
* speed, thereby resetting the timeout value.
|
||||
*/
|
||||
@SuppressWarnings("MethodName")
|
||||
public void Feed() {
|
||||
|
||||
@@ -727,7 +727,7 @@ public class PIDController implements PIDInterface, LiveWindowSendable, Controll
|
||||
setSetpoint((Double) value);
|
||||
}
|
||||
} else if (key.equals("enabled")) {
|
||||
if (isEnable() != (Boolean) value) {
|
||||
if (isEnabled() != (Boolean) value) {
|
||||
if ((Boolean) value) {
|
||||
enable();
|
||||
} else {
|
||||
@@ -750,7 +750,7 @@ public class PIDController implements PIDInterface, LiveWindowSendable, Controll
|
||||
table.putNumber("d", getD());
|
||||
table.putNumber("f", getF());
|
||||
table.putNumber("setpoint", getSetpoint());
|
||||
table.putBoolean("enabled", isEnable());
|
||||
table.putBoolean("enabled", isEnabled());
|
||||
table.addTableListener(m_listener, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,8 +335,7 @@ public class DriverStation implements RobotState.Interface {
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the driver station attached to a Field Management System? Note: This does not work with the
|
||||
* Blue DS.
|
||||
* Is the driver station attached to a Field Management System?
|
||||
*
|
||||
* @return True if the robot is competing on a field being controlled by a Field Management System
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user