Package com.marswars.proxy_server
Class ProxyServerThread
java.lang.Object
java.lang.Thread
com.marswars.proxy_server.ProxyServerThread
- All Implemented Interfaces:
Runnable
Proxy server thread for handling UDP communication with external systems.
Receives and processes various packet types including odometry, module states,
AprilTag solutions, piece detections, and timesync requests.
Provides bidirectional communication capabilities on a single UDP port.
Multi-Client Support
The proxy server can handle multiple simultaneous clients (e.g., multiple vision coprocessors). Each client is tracked independently with its own connection monitoring and alerts. Data from all clients is merged into shared queues, accessible via the getter methods.
Use broadcastData(byte[]) to send data to all connected clients, or
sendDataToClient(byte[], SocketAddress) to send to a specific client.
The legacy sendData(byte[]) method sends to the most recent client for
backward compatibility.
Connection Monitoring
The proxy server automatically monitors the connection to each client and publishes individual WPILib Alerts when connections are lost. Connection is considered lost if no packets are received within the timeout period (1 second by default). A debouncer is used to prevent alert flapping during intermittent connectivity issues.
Use isConnected() to check if any client is connected,
getConnectedClientCount() to get the number of active clients, and
getTimeSinceLastPacket() to get time since last received packet from any client.
Camera Tracking
The proxy server tracks individual cameras by their serial number (extracted from vision packets). Each camera gets its own connection monitoring and alert that includes both the camera serial and the client it's connected to for easy debugging. Cameras are considered disconnected if no vision packets (tag solutions or piece detections) are received within 2 seconds.
Use getConnectedCameraCount() to get the number of active cameras,
getCameraSerials() to list all tracked cameras, and
isCameraConnected(String) to check if a specific camera is connected.
PhotonVision Simulation Support
In simulation mode, this class can use PhotonVision simulation to generate simulated vision data that populates the tagSolutions queue, allowing you to test vision-based robot code without a physical robot or vision coprocessor.Usage Example:
// In your robot initialization (Robot.java or subsystem)
ProxyServerThread proxyServer = ProxyServerThread.getInstance();
// Check connection status for multiple clients
int connectedClients = proxyServer.getConnectedClientCount();
System.out.println("Connected clients: " + connectedClients);
// Get all client addresses
List<SocketAddress> clients = proxyServer.getClientAddresses();
// Broadcast data to all connected clients
byte[] customData = new byte[]{1, 2, 3};
int sentCount = proxyServer.broadcastData(customData);
System.out.println("Sent to " + sentCount + " clients");
// Initialize vision simulation (only in simulation mode)
if (RobotBase.isSimulation()) {
// Load the field layout
AprilTagFieldLayout fieldLayout = AprilTagFieldLayout.loadField(
AprilTagFields.k2025Reefscape
);
MwVisionSimulation visionSim = proxyServer.initializeVisionSimulation(fieldLayout);
// Add default cameras (front, left, right, back)
visionSim.addDefaultCameras();
// Or add a custom camera
// Camera mounted 0.5m forward, 0.3m up, angled 15 degrees down
Transform3d robotToCamera = new Transform3d(
new Translation3d(0.5, 0, 0.3),
new Rotation3d(0, Math.toRadians(-15), 0)
);
visionSim.addCamera("simCamera", robotToCamera);
}
// In your periodic method, update with current robot pose
if (RobotBase.isSimulation()) {
Pose2d currentPose = drivetrain.getPose(); // Get from your drivetrain
proxyServer.updateVisionSimulation(currentPose);
}
// Vision data will now be available via getLatestTagSolutions()
List<TagSolutionData> solutions = proxyServer.getLatestTagSolutions();
- See Also:
-
Nested Class Summary
Nested classes/interfaces inherited from class java.lang.Thread
Thread.State, Thread.UncaughtExceptionHandler -
Field Summary
Fields inherited from class java.lang.Thread
MAX_PRIORITY, MIN_PRIORITY, NORM_PRIORITY -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionintbroadcastData(byte[] buffer) Broadcasts data to all currently connected clients.booleanBinds the server socket to the set port to begin communication.Gets a list of all tracked camera serial numbers (both connected and disconnected).Gets the last client address that sent data to the server.Gets a list of all tracked client addresses (both connected and disconnected).intGets the number of currently connected cameras.intGets the number of currently connected clients.static ProxyServerThreadGets the singleton instance of the ProxyServerThread.Gets the current robot module states as individual SwerveModuleState arrays.Gets the current robot module states information.Gets the current robot pose, velocity, and variance data from odometry readings.Gets the current detected game pieces information.Gets the current AprilTag solution information.doublegetTimeSinceLastCameraPacket(String cameraSerial) Gets the time elapsed since the last packet was received from a specific camera.doubleGets the time elapsed since the last packet was received from any client.booleanChecks if the server has any active client connections.initializeVisionSimulation(AprilTagFieldLayout field_layout) Initializes vision simulation for generating simulated vision data.booleanisCameraConnected(String cameraSerial) Checks if a specific camera is currently connected.booleanChecks if the proxy server currently has an active connection to any client.voidrun()booleansendCustomPacket(byte message_id, byte[] payload) Sends a custom packet with specified message ID and payload databooleansendData(byte[] buffer) Sends data back to the last connected client on the same port.booleansendDataToClient(byte[] buffer, SocketAddress client_address) Sends data to a specific client address.booleanSends snapshot trigger packet for log location flaggingvoidstart()booleanSends match data packet for log name syncingvoidupdateVisionSimulation(Pose2d robot_pose) Updates the vision simulation with the current robot pose and generates vision data.Methods inherited from class java.lang.Thread
activeCount, checkAccess, clone, countStackFrames, currentThread, dumpStack, enumerate, getAllStackTraces, getContextClassLoader, getDefaultUncaughtExceptionHandler, getId, getName, getPriority, getStackTrace, getState, getThreadGroup, getUncaughtExceptionHandler, holdsLock, interrupt, interrupted, isAlive, isDaemon, isInterrupted, join, join, join, onSpinWait, resume, setContextClassLoader, setDaemon, setDefaultUncaughtExceptionHandler, setName, setPriority, setUncaughtExceptionHandler, sleep, sleep, stop, suspend, toString, yield
-
Constructor Details
-
ProxyServerThread
public ProxyServerThread()
-
-
Method Details
-
getInstance
Gets the singleton instance of the ProxyServerThread.- Returns:
- the ProxyServerThread instance
-
start
public void start() -
run
public void run() -
configureServer
public boolean configureServer()Binds the server socket to the set port to begin communication. This must be called once before you can attempt toupdateData().- Returns:
- true: server configured successfully | false: configuration error occurred.
- Throws:
SocketException- if the socket could not be opened, or the socket could not bind to the specified local port.
-
isConnected
public boolean isConnected()Checks if the proxy server currently has an active connection to any client.- Returns:
- true if at least one client is connected, false if all connections lost
-
getConnectedClientCount
public int getConnectedClientCount()Gets the number of currently connected clients.- Returns:
- number of clients with active connections
-
getClientAddresses
Gets a list of all tracked client addresses (both connected and disconnected).- Returns:
- list of client socket addresses
-
getTimeSinceLastPacket
public double getTimeSinceLastPacket()Gets the time elapsed since the last packet was received from any client.- Returns:
- seconds since last packet from any client, or Double.MAX_VALUE if no clients
-
getConnectedCameraCount
public int getConnectedCameraCount()Gets the number of currently connected cameras.- Returns:
- number of cameras with active connections
-
getCameraSerials
Gets a list of all tracked camera serial numbers (both connected and disconnected).- Returns:
- list of camera serial numbers
-
isCameraConnected
Checks if a specific camera is currently connected.- Parameters:
cameraSerial- the camera serial number to check- Returns:
- true if the camera is connected, false otherwise
-
getTimeSinceLastCameraPacket
Gets the time elapsed since the last packet was received from a specific camera.- Parameters:
cameraSerial- the camera serial number- Returns:
- seconds since last packet from the camera, or Double.MAX_VALUE if camera not found
-
sendData
public boolean sendData(byte[] buffer) Sends data back to the last connected client on the same port. For multi-client support, usesendDataToClient(byte[], SocketAddress)instead.- Parameters:
buffer- the byte array to send- Returns:
- true if data was sent successfully, false if there was an error
-
sendDataToClient
Sends data to a specific client address.- Parameters:
buffer- the byte array to sendclientAddress- the destination client address- Returns:
- true if data was sent successfully, false if there was an error
-
broadcastData
public int broadcastData(byte[] buffer) Broadcasts data to all currently connected clients.- Parameters:
buffer- the byte array to send- Returns:
- number of clients successfully sent to
-
getLatestOdometryReadings
Gets the current robot pose, velocity, and variance data from odometry readings. Data is updated by callingupdateData()periodically.- Returns:
- list of recent
OdomPacket.OdometryDatafrom chassis proxy
-
getLatestModuleStatesReadings
Gets the current robot module states information. States are updated by callingupdateData()periodically.- Returns:
- list of recent
StatesPacket.ModuleStatesDatacontaining swerve module information
-
getLatestModuleStatesArrays
Gets the current robot module states as individual SwerveModuleState arrays. This is a convenience method that extracts the module states arrays from the data objects.- Returns:
- list of SwerveModuleState arrays (for backward compatibility)
-
getLatestTagSolutions
Gets the current AprilTag solution information. Solutions are updated by callingupdateData()periodically.- Returns:
- list of recent
TagSolutionPacket.TagSolutionDatawith pose estimates and detected tag IDs
-
getLatestPieceDetections
Gets the current detected game pieces information. Detections are updated by callingupdateData()periodically.- Returns:
- list of recent
PieceDetectionPacket.PieceDetectionDatawith piece detection information
-
snapshot
Sends snapshot trigger packet for log location flagging- Parameters:
tag_name- flag name to record in log- Returns:
- true if packet was sent successfully, false otherwise
-
syncMatchData
public boolean syncMatchData()Sends match data packet for log name syncing- Returns:
- true if packet was sent successfully, false otherwise
-
sendCustomPacket
public boolean sendCustomPacket(byte message_id, byte[] payload) Sends a custom packet with specified message ID and payload data- Parameters:
message_id- the message type identifierpayload- the data payload (can be null for header-only packets)- Returns:
- true if packet was sent successfully, false otherwise
-
getClientAddress
Gets the last client address that sent data to the server. For multi-client tracking, usegetClientAddresses()instead.- Returns:
- SocketAddress of the last client that sent data, null if no client has connected
-
hasClientConnection
public boolean hasClientConnection()Checks if the server has any active client connections.- Returns:
- true if at least one client is connected
-
initializeVisionSimulation
Initializes vision simulation for generating simulated vision data. This should be called in simulation mode to enable PhotonVision simulation. Only works in simulation mode - does nothing on real robot.- Parameters:
fieldLayout- the AprilTag field layout to use- Returns:
- the created MwVisionSimulation instance, or null if not in simulation
-
updateVisionSimulation
Updates the vision simulation with the current robot pose and generates vision data. This should be called periodically with the simulated robot pose. The generated vision data is automatically added to the tagSolutions queue. Only works in simulation mode - does nothing on real robot.- Parameters:
robotPose- the current simulated robot pose
-