Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/source/docs/quick-start/common-setups.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ PhotonVision requires dedicated hardware, above and beyond a roboRIO. This page
The Orange Pi 5 is the only currently supported device for object detection.
:::

## SystemCore Support

The SystemCore is not supported by PhotonVision. PhotonVision is designed to utilize the entirety of the coprocessor's resources, and this could prove to be dangerous if attempted on the main robot controller.
There are no current plans to support running on SystemCore alongside robot code, and any attempts to do so are entirely at your own risk and will require a separate fork of PhotonVision.

## SD Cards

- 8GB or larger micro SD card
Expand Down
86 changes: 86 additions & 0 deletions photon-server/src/main/java/org/photonvision/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,13 @@
package org.photonvision;

import edu.wpi.first.hal.HAL;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Path;
import java.security.CodeSource;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.cli.*;
Expand Down Expand Up @@ -173,6 +178,70 @@ public static void main(String[] args) {
+ Platform.getPlatformName()
+ (Platform.isRaspberryPi() ? (" (Pi " + PiVersion.getPiVersion() + ")") : ""));

if (Platform.isSystemCore()) {
String docsLink =
"https://docs.photonvision.org/en/latest/docs/quick-start/common-setups.html#systemcore-support";

logger.error(
"SystemCore is not a supported platform for PhotonVision!\n "
+ "Please visit "
+ docsLink
+ " for more information.");

try {
int port = 5800;
io.javalin.Javalin app = null;
try {
app = io.javalin.Javalin.create(cfg -> cfg.showJavalinBanner = false).start(port);
} catch (Exception e) {
logger.warn("Failed to bind to port 5800, exiting: " + e.getMessage());
port = DEFAULT_WEBPORT;
app = io.javalin.Javalin.create(cfg -> cfg.showJavalinBanner = false).start(port);
}

final int boundPort = port;
final String html =
"<!doctype html>"
+ "<html><head><meta charset=\"utf-8\"><title>Unsupported platform</title></head><body>"
+ "<p>Main Robot Controllers shouldn't run PhotonVision, but yours does! "
+ "Please <a href=\"https://github.com/PhotonVision/photonvision/blob/main/scripts/uninstall.sh\" "
+ "target=\"_blank\" rel=\"noopener noreferrer\">uninstall</a> PhotonVision. "
+ "If you choose to modify PhotonVision so that it functions on SystemCore, "
+ "you do so entirely at your own risk and without any support. "
+ "For more information, see <a href=\""
+ docsLink
+ "\" target=\"_blank\" rel=\"noopener noreferrer\">"
+ docsLink
+ "</a>.</p></body></html>";

app.get(
"/",
ctx -> {
ctx.contentType("text/html; charset=utf-8");
ctx.result(html);
});

logger.info(
"Served SystemCore warning page on port "
+ boundPort
+ " - process will remain running to serve the page.");

// Prevent main from exiting so the page remains available.
final Object lock = new Object();
synchronized (lock) {
try {
lock.wait();
} catch (InterruptedException ignored) {
}
}
} catch (Exception e) {
logger.error("Failed to start static warning page server", e);
}

// Exit
System.exit(1);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • you never call javelin.serve
  • you must let javalin live to be a web server. You can't exit...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you never call javelin.serve

app = io.javalin.Javalin.create(cfg -> cfg.showJavalinBanner = false).start(port);

This is functionally equivalent, it does the same thing and serves it.

you must let javalin live to be a web server. You can't exit...

We suspend the process, the exit is only there if something in the webserver fails.

}

if (OsImageVersion.IMAGE_VERSION.isPresent()) {
logger.info("PhotonVision image version: " + OsImageVersion.IMAGE_VERSION.get());
}
Expand Down Expand Up @@ -328,4 +397,21 @@ public static void main(String[] args) {
HardwareManager.getInstance().setRunning(true);
Server.initialize(DEFAULT_WEBPORT);
}

public static File getJarLocation() {
try {
ProtectionDomain protectionDomain = Main.class.getProtectionDomain();
CodeSource codeSource = protectionDomain.getCodeSource();
if (codeSource != null) {
URL location = codeSource.getLocation();
return new File(location.toURI());
} else {
logger.error("Could not determine JAR location: code source is null");
return null;
}
} catch (URISyntaxException e) {
logger.error("Error determining JAR location", e);
return null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ public enum Platform {
true,
OSType.LINUX,
true), // Raspberry Pi 3/4 with a 64-bit image
LINUX_SYSTEMCORE(
"Linux Systemcore 64-bit NOT SUPPORTED",
Platform::getUnknownModel,
"linuxarm64",
false,
OSType.LINUX,
false), // SystemCore 64-bit
LINUX_RK3588_64(
"Linux AARCH 64-bit with RK3588",
Platform::getLinuxDeviceTreeModel,
Expand Down Expand Up @@ -131,6 +138,11 @@ public static boolean isRK3588() {
return Platform.isOrangePi() || Platform.isCoolPi4b() || Platform.isRock5C();
}

public static boolean isSystemCore() {
File sysCore = new File("/home/systemcore");
return sysCore.exists() | fileHasText("/etc/os-release", "systemcore");
}

public static boolean isQCS6490() {
return isRubik();
}
Expand Down Expand Up @@ -205,7 +217,9 @@ public static Platform getCurrentPlatform() {
}

if (OS_NAME.startsWith("Linux")) {
if (isPiSBC()) {
if (isSystemCore()) {
return LINUX_SYSTEMCORE;
} else if (isPiSBC()) {
if (OS_ARCH.equals("arm") || OS_ARCH.equals("arm32")) {
return LINUX_RASPBIAN32;
} else if (OS_ARCH.equals("aarch64") || OS_ARCH.equals("arm64")) {
Expand Down
Loading