> nodes)
+ {
+ rclcpp::executors::MultiThreadedExecutor executor;
+ for (auto node : nodes)
+ {
+ executor.add_node(node);
+ }
+
+ executor.spin();
+
+ for (auto node : nodes)
+ {
+ executor.remove_node(node);
+ }
+
+ rclcpp::shutdown();
}
+
}
\ No newline at end of file
diff --git a/autonav_ws/src/scr_controller/src/core.cpp b/autonav_ws/src/scr_controller/src/core.cpp
index e96fb6ab..dbc343d7 100644
--- a/autonav_ws/src/scr_controller/src/core.cpp
+++ b/autonav_ws/src/scr_controller/src/core.cpp
@@ -95,8 +95,6 @@ class CoreNode : public rclcpp::Node
}
// Update the device state
- //RCLCPP_INFO(this->get_logger(), "Device %s state changed to %s", request->device.c_str(), SCR::toString((SCR::DeviceState)request->state).c_str());
- RCLCPP_INFO(this->get_logger(), "Device %s state changed to DISABLED DEVICE STATE TOSTRING");
if (device_states.find(request->device) == device_states.end())
{
// This is the first time we've seen this device, so we need to publish the system state, device state, and all known configs
@@ -157,7 +155,6 @@ class CoreNode : public rclcpp::Node
response->success = true;
// Publish the new config
- RCLCPP_INFO(this->get_logger(), "Config updated for device %s -> %s", request->device.c_str(), request->json.c_str());
scr_msgs::msg::ConfigUpdated config_updated_message;
config_updated_message.device = request->device;
config_updated_message.json = request->json;
diff --git a/display/index.html b/display/index.html
index eb296dc7..dc9a5ceb 100644
--- a/display/index.html
+++ b/display/index.html
@@ -5,7 +5,7 @@
- SCR Weeb Wagon
+ SCR Danger Zone
@@ -41,7 +41,7 @@
- Weeb Wagon
+ Danger Zone
@@ -122,8 +122,11 @@ Device States
Camera / Filtered
@@ -230,7 +233,7 @@ System
Loading...
- Waiting for the Weeb Wagon
+ Waiting for the Danger Zone
diff --git a/display/scripts/globals.js b/display/scripts/globals.js
index d5742eba..1052e765 100644
--- a/display/scripts/globals.js
+++ b/display/scripts/globals.js
@@ -16,6 +16,7 @@ var deviceStates = {};
var logs = [];
var iterator = 0;
var iterators = [];
+var debug = false;
var addressKeys = {
"autonav_serial_imu": {
@@ -34,14 +35,24 @@ var addressKeys = {
"autonav_vision_transformer": {
"internal_title": "[Vision] Transformer",
"lower_hue": "int",
- "lower_saturation": "int",
- "lower_value": "int",
+ "lower_sat": "int",
+ "lower_val": "int",
"upper_hue": "int",
- "upper_saturation": "int",
- "upper_value": "int",
- "blur": "int",
+ "upper_sat": "int",
+ "upper_val": "int",
+ "blur_weight": "int",
"blur_iterations": "int",
- "region_of_disinterest_offset": "int"
+ "rod_offset": "int",
+ "map_res": "int",
+ "image_warp_tl": "float",
+ "image_warp_tr": "float"
+ },
+
+ "autonav_vision_expandifier": {
+ "internal_title": "[Vision] Expandifier",
+ "horizontal_fov": "int",
+ "map_res": "int",
+ "vertical_fov": "float"
},
"autonav_filters": {
@@ -66,8 +77,8 @@ var addressKeys = {
"autonav_nav_astar": {
"internal_title": "[Navigation] A*",
- "pop_distance": "float",
- "direction": {
+ "waypointPopDistance": "float",
+ "waypointDirection": {
0: "North",
1: "South",
2: "Misc 1",
@@ -76,8 +87,8 @@ var addressKeys = {
5: "Misc 4",
6: "Misc 5",
},
- "use_only_waypoints": "bool",
- "waypoint_delay": "float",
+ "useOnlyWaypoints": "bool",
+ "waypointDelay": "float",
},
"autonav_nav_resolver": {
@@ -91,17 +102,10 @@ var addressKeys = {
"max_angular_speed": "float"
},
- "autonav_playback": {
- "internal_title": "[Playback]",
- "record_imu": "bool",
- "record_gps": "bool",
- "record_position": "bool",
- "record_feedback": "bool",
- "record_objectdetection": "bool",
- "record_manual": "bool",
- "record_autonomous": "bool",
- "record_input": "bool",
- "record_debugfeedback": "bool",
+ "autonav_image_combiner": {
+ "internal_title": "[Image Combiner]",
+ "overlap": "int",
+ "map_res": "int"
}
}
diff --git a/display/scripts/main.js b/display/scripts/main.js
index a0ed897d..d16495e7 100644
--- a/display/scripts/main.js
+++ b/display/scripts/main.js
@@ -62,6 +62,7 @@ $(document).ready(function () {
}
if (op == "get_nodes_callback") {
+ console.log(obj);
for (let i = 0; i < obj.nodes.length; i++) {
const node = obj.nodes[i];
send({
@@ -70,13 +71,35 @@ $(document).ready(function () {
opcode: 4,
iterator: iterate()
});
+
+ const statemap = obj.states;
+ if (node in statemap) {
+ if (node == "rosbridge_websocket" || node == "rosapi" || node == "scr_core" || node == "rosapi_params")
+ {
+ continue;
+ }
+
+ deviceStates[node] = statemap[node];
+ unorderedListElement = $("#element_device_states");
+ unorderedListElement.empty();
+ for (const id in deviceStates) {
+ const state = deviceStates[id];
+ unorderedListElement.append(`${id}: ${deviceStateToName(state)}
`);
+ }
+ }
}
+
+ for (const key in obj.configs)
+ {
+ config[key] = obj.configs[key];
+ }
+ regenerateConfig();
}
}
};
websocket.onclose = function (event) {
- $("#connecting-state").text("Waiting for the Weeb Wagon");
+ $("#connecting-state").text("Waiting for the Danger Zone");
$(".connecting").show();
$(".connecting-input").show();
$("#main").hide();
@@ -97,10 +120,6 @@ $(document).ready(function () {
var sendQueue = [];
- function send(obj) {
- sendQueue.push(obj);
- }
-
function setSystemState() {
send({
op: "set_system_state",
@@ -110,148 +129,6 @@ $(document).ready(function () {
});
}
- function generateElementForConfiguration(data, type, device, text) {
- if (type == "bool") {
- const checked = fromBytesToBool(data);
-
- // Create a dropdown
- const div = document.createElement("div");
- div.classList.add("input-group");
- div.classList.add("mb-3");
-
- const select = document.createElement("select");
- select.classList.add("form-select");
- select.onchange = function () {
- send({
- op: "configuration",
- opcode: 1,
- device: device,
- address: text,
- data: Array.from(fromBoolToBytes(select.value == 1)),
- iterator: iterate()
- });
- }
-
- const optionTrue = document.createElement("option");
- optionTrue.value = 1;
- optionTrue.innerText = "True";
- optionTrue.selected = checked;
-
- const optionFalse = document.createElement("option");
- optionFalse.value = 0;
- optionFalse.innerText = "False";
- optionFalse.selected = !checked;
-
- select.appendChild(optionTrue);
- select.appendChild(optionFalse);
-
- const span = document.createElement("span");
- span.classList.add("input-group-text");
- span.innerText = text;
-
- div.appendChild(span);
- div.appendChild(select);
- return div;
- }
- else if (type == "float") {
- const div = document.createElement("div");
- div.classList.add("input-group");
- div.classList.add("mb-3");
-
- const input = document.createElement("input");
- input.type = "number";
- input.classList.add("form-control");
- input.value = fromBytesToFloat(data).toFixed(6);
- input.onchange = function () {
- send({
- op: "configuration",
- opcode: 1,
- device: device,
- address: text,
- data: Array.from(fromFloatToBytes(input.value)),
- iterator: iterate()
- });
- }
-
- const span = document.createElement("span");
- span.classList.add("input-group-text");
- span.innerText = text;
-
- div.appendChild(span);
- div.appendChild(input);
- return div;
- }
- else if (type == "int") {
- const div = document.createElement("div");
- div.classList.add("input-group");
- div.classList.add("mb-3");
-
- const input = document.createElement("input");
- input.type = "number";
- input.classList.add("form-control");
- input.value = fromBytesToInt(data);
- input.onchange = function () {
- send({
- op: "configuration",
- opcode: 1,
- device: device,
- address: text,
- data: Array.from(fromIntToBytes(input.value)),
- iterator: iterate()
- });
- }
-
- const span = document.createElement("span");
- span.classList.add("input-group-text");
- span.innerText = text;
-
- div.appendChild(span);
- div.appendChild(input);
- return div;
- }
- else {
- const options = addressKeys[device][text];
-
- if (typeof options == "object") {
- const index = fromBytesToInt(data);
-
- // Create a dropdown
- const div = document.createElement("div");
- div.classList.add("input-group");
- div.classList.add("mb-3");
-
- const select = document.createElement("select");
- select.classList.add("form-select");
- select.onchange = function () {
- send({
- op: "configuration",
- opcode: 1,
- device: device,
- address: text,
- data: Array.from(fromIntToBytes(select.value)),
- iterator: iterate()
- });
- }
-
- for (let i = 0; i < Object.keys(options).length; i++) {
- const option = document.createElement("option");
- option.value = i;
- option.selected = i == index;
- option.innerText = options[i];
- select.appendChild(option);
- }
-
- const span = document.createElement("span");
- span.classList.add("input-group-text");
- span.innerText = text;
-
- div.appendChild(span);
- div.appendChild(select);
- return div;
- }
- }
- }
-
function generateElementForConbus(data, type, text, deviceId, address, readonly = false) {
if (type == "bool") {
const checked = fromBytesToBool(data);
@@ -441,54 +318,7 @@ $(document).ready(function () {
}
if (topic == "/scr/configuration") {
- const { device, opcode, data, address } = msg;
- if (opcode == 4) {
- return;
- }
-
- if (opcode == 2 || opcode == 3) {
- if (!(device in config)) {
- config[device] = {};
- }
-
- config[device][address] = data;
-
- const configElement = $("#configuration");
- configElement.empty();
-
- for (const deviceId in config) {
- const deviceConfig = config[deviceId];
- const title = addressKeys[deviceId]["internal_title"];
- const deviceElement = $(``);
- deviceElement.append(``);
- const deviceBody = $(``);
- deviceElement.append(deviceBody);
-
- for (const address of Object.keys(deviceConfig).sort()) {
- const data = deviceConfig[address];
- const type = addressKeys[deviceId][address];
- if (type == undefined) {
- const alert = $(`Unknown Address: ${address}
`);
- deviceBody.append(alert);
- continue;
- }
-
- const inputElement = generateElementForConfiguration(data, type, deviceId, address);
- deviceBody.append(inputElement);
- }
-
- for (const address in addressKeys[deviceId]) {
- if (address in deviceConfig || address == "internal_title") {
- continue;
- }
-
- const alert = $(`Unknown Address: ${address}
`);
- deviceBody.append(alert);
- }
-
- configElement.append(deviceElement);
- }
- }
+ console.log(msg);
return;
}
@@ -560,15 +390,34 @@ $(document).ready(function () {
return;
}
- if (topic == "/autonav/camera/compressed") {
+ if (topic == "/autonav/camera/compressed/left") {
// Set to
- const imgElement = document.getElementById("target_raw_camera");
+ const imgElement = document.getElementById("target_raw_camera_left");
imgElement.src = `data:image/jpeg;base64,${msg.data}`;
return;
}
- if (topic == "/autonav/cfg_space/raw/image") {
- const imgElement = document.getElementById("target_filtered_camera");
+ if (topic == "/autonav/camera/compressed/right") {
+ // Set to
+ const imgElement = document.getElementById("target_raw_camera_right");
+ imgElement.src = `data:image/jpeg;base64,${msg.data}`;
+ return;
+ }
+
+ if (topic == "/autonav/cfg_space/raw/image/left") {
+ const imgElement = document.getElementById("target_filtered_camera_left");
+ imgElement.src = `data:image/jpeg;base64,${msg.data}`;
+ return;
+ }
+
+ if (topic == "/autonav/cfg_space/raw/image/right") {
+ const imgElement = document.getElementById("target_filtered_camera_right");
+ imgElement.src = `data:image/jpeg;base64,${msg.data}`;
+ return;
+ }
+
+ if (topic == "/autonav/cfg_space/raw/debug") {
+ const imgElement = document.getElementById("target_camera_raw");
imgElement.src = `data:image/jpeg;base64,${msg.data}`;
return;
}
@@ -701,4 +550,187 @@ $(document).ready(function () {
logs = [];
$("#log_body").empty();
});
+
+ function generateElementForConfiguration(data, type, device, text) {
+ if (type == "bool") {
+ const checked = data == 1;
+
+ // Create a dropdown
+ const div = document.createElement("div");
+ div.classList.add("input-group");
+ div.classList.add("mb-3");
+
+ const select = document.createElement("select");
+ select.classList.add("form-select");
+ select.onchange = function () {
+ config[device][text] = select.value;
+ send({
+ op: "configuration",
+ device: device,
+ json: config[device],
+ });
+ }
+
+ const optionTrue = document.createElement("option");
+ optionTrue.value = 1;
+ optionTrue.innerText = "True";
+ optionTrue.selected = checked;
+
+ const optionFalse = document.createElement("option");
+ optionFalse.value = 0;
+ optionFalse.innerText = "False";
+ optionFalse.selected = !checked;
+
+ select.appendChild(optionTrue);
+ select.appendChild(optionFalse);
+
+ const span = document.createElement("span");
+ span.classList.add("input-group-text");
+ span.innerText = text;
+
+ div.appendChild(span);
+ div.appendChild(select);
+ return div;
+ }
+ else if (type == "float") {
+ const div = document.createElement("div");
+ div.classList.add("input-group");
+ div.classList.add("mb-3");
+
+ const input = document.createElement("input");
+ input.type = "number";
+ input.classList.add("form-control");
+ input.value = data;
+ input.onchange = function () {
+ config[device][text] = parseFloat(input.value);
+ send({
+ op: "configuration",
+ device: device,
+ json: config[device],
+ });
+ }
+
+ const span = document.createElement("span");
+ span.classList.add("input-group-text");
+ span.innerText = text;
+
+ div.appendChild(span);
+ div.appendChild(input);
+ return div;
+ }
+ else if (type == "int") {
+ const div = document.createElement("div");
+ div.classList.add("input-group");
+ div.classList.add("mb-3");
+
+ const input = document.createElement("input");
+ input.type = "number";
+ input.classList.add("form-control");
+ input.value = data;
+ input.onchange = function () {
+ config[device][text] = parseInt(input.value);
+ send({
+ op: "configuration",
+ device: device,
+ json: config[device],
+ });
+ }
+
+ const span = document.createElement("span");
+ span.classList.add("input-group-text");
+ span.innerText = text;
+
+ div.appendChild(span);
+ div.appendChild(input);
+ return div;
+ }
+ else {
+ const options = addressKeys[device][text];
+
+ if (typeof options == "object") {
+ const index = data;
+
+ // Create a dropdown
+ const div = document.createElement("div");
+ div.classList.add("input-group");
+ div.classList.add("mb-3");
+
+ const select = document.createElement("select");
+ select.classList.add("form-select");
+ select.onchange = function () {
+ config[device][text] = select.value;
+ send({
+ op: "configuration",
+ device: device,
+ json: config[device],
+ });
+ }
+
+ for (let i = 0; i < Object.keys(options).length; i++) {
+ const option = document.createElement("option");
+ option.value = i;
+ option.selected = i == index;
+ option.innerText = options[i];
+ select.appendChild(option);
+ }
+
+ const span = document.createElement("span");
+ span.classList.add("input-group-text");
+ span.innerText = text;
+
+ div.appendChild(span);
+ div.appendChild(select);
+ return div;
+ }
+ }
+ }
+
+ const regenerateConfig = () => {
+ const configElement = $("#configuration");
+ configElement.empty();
+
+ for (const deviceId in config) {
+ const deviceConfig = config[deviceId];
+ if (addressKeys[deviceId] == undefined) {
+ console.log(`Unknown Device Config: ${deviceId}`);
+ // const alert = $(`Unknown Device Config: ${deviceId}
`);
+ // configElement.append(alert);
+ continue;
+ }
+
+ const title = addressKeys[deviceId]["internal_title"];
+ const deviceElement = $(``);
+ deviceElement.append(``);
+ const deviceBody = $(``);
+ deviceElement.append(deviceBody);
+
+ for (const address of Object.keys(deviceConfig).sort()) {
+ const data = deviceConfig[address];
+ const type = addressKeys[deviceId][address];
+ if (type == undefined) {
+ const alert = $(`Unknown Type: ${address}
`);
+ deviceBody.append(alert);
+ continue;
+ }
+
+ const inputElement = generateElementForConfiguration(data, type, deviceId, address);
+ deviceBody.append(inputElement);
+ }
+
+ for (const address in addressKeys[deviceId]) {
+ if (address in deviceConfig || address == "internal_title") {
+ continue;
+ }
+
+ const alert = $(`Unknown Configuration Entry: ${address}
`);
+ deviceBody.append(alert);
+ }
+
+ configElement.append(deviceElement);
+ }
+ }
+
+ function send(obj) {
+ sendQueue.push(obj);
+ }
})
\ No newline at end of file
diff --git a/display/scripts/utilities.js b/display/scripts/utilities.js
index 0bc62169..c529122d 100644
--- a/display/scripts/utilities.js
+++ b/display/scripts/utilities.js
@@ -121,7 +121,7 @@ const radiansToDegrees = (radians) => {
}
const deviceStateToName = (state) => {
- return state == 0 ? "Off" : state == 1 ? "Standby" : state == 2 ? "Ready" : "Operating";
+ return ["Off", "Booting", "Standby", "Ready", "Operating", "Errored"][state];
}
const clearGlobals = () => {
diff --git a/display/styles/index.css b/display/styles/index.css
index 0b6edefb..2db3d8cd 100644
--- a/display/styles/index.css
+++ b/display/styles/index.css
@@ -76,20 +76,34 @@ h5 > span {
flex-direction: column;
}
+/* Off */
span[data-state="0"] {
color: --var(-text-color);
}
+/* Booting */
span[data-state="1"] {
- color: #C21858;
+ color: #FF9800;
}
+/* Standby */
span[data-state="2"] {
- color: #57ACDC;
+ color: #FFC107;
}
+/* Ready */
span[data-state="3"] {
- color: #60C689;
+ color: #4CAF50;
+}
+
+/* Operating */
+span[data-state="4"] {
+ color: #57ACDC;
+}
+
+/* Errored */
+span[data-state="5"] {
+ color: #C21858;
}
#element_device_states > h5 > span {