From b34039251ad500fb198a5f00a7729684f2d14614 Mon Sep 17 00:00:00 2001 From: Azalea Colburn Date: Wed, 24 Jul 2024 14:20:04 -0700 Subject: [PATCH 01/47] begin working on talonfx --- fission/src/Synthesis.tsx | 4 ++-- .../java/com/autodesk/synthesis/CANMotor.java | 8 +++++++ .../com/autodesk/synthesis/ctre/TalonFX.java | 22 ++++++++++++++++--- .../synthesis/revrobotics/CANSparkMax.java | 1 - .../src/main/java/frc/robot/Robot.java | 1 + 5 files changed, 30 insertions(+), 6 deletions(-) diff --git a/fission/src/Synthesis.tsx b/fission/src/Synthesis.tsx index a01e129834..c0256b82b1 100644 --- a/fission/src/Synthesis.tsx +++ b/fission/src/Synthesis.tsx @@ -34,7 +34,6 @@ import PracticeSettingsModal from "@/modals/configuring/PracticeSettingsModal" import RoboRIOModal from "@/modals/configuring/RoboRIOModal" import SettingsModal from "@/modals/configuring/SettingsModal" import RCConfigEncoderModal from "@/modals/configuring/rio-config/RCConfigEncoderModal" -import RCConfigPWMGroupModal from "@/modals/configuring/rio-config/RCConfigPWMGroupModal" import RCCreateDeviceModal from "@/modals/configuring/rio-config/RCCreateDeviceModal" import DeleteAllThemesModal from "@/modals/configuring/theme-editor/DeleteAllThemesModal" import DeleteThemeModal from "@/modals/configuring/theme-editor/DeleteThemeModal" @@ -66,7 +65,8 @@ import SceneOverlay from "./ui/components/SceneOverlay.tsx" import WPILibWSWorker from "@/systems/simulation/wpilib_brain/WPILibWSWorker.ts?worker" import WSViewPanel from "./ui/panels/WSViewPanel.tsx" import Lazy from "./util/Lazy.ts" -import RCConfigCANGroupModal from "./ui/modals/configuring/rio-config/RCConfigCANGroupModal.tsx" +import RCConfigCANGroupModal from "@/modals/configuring/rio-config/RCConfigCANGroupModal.tsx" +import RCConfigPWMGroupModal from "@/modals/configuring/rio-config/RCConfigPwmGroupModal.tsx" const DEFAULT_MIRA_PATH = "/api/mira/Robots/Team 2471 (2018)_v7.mira" diff --git a/simulation/SyntheSimJava/src/main/java/com/autodesk/synthesis/CANMotor.java b/simulation/SyntheSimJava/src/main/java/com/autodesk/synthesis/CANMotor.java index eeca38ed7b..1793aabddc 100644 --- a/simulation/SyntheSimJava/src/main/java/com/autodesk/synthesis/CANMotor.java +++ b/simulation/SyntheSimJava/src/main/java/com/autodesk/synthesis/CANMotor.java @@ -79,6 +79,14 @@ public void setNeutralDeadband(double deadband) { m_neutralDeadband.set(Math.min(1.0, Math.max(0.0, deadband))); } + /** + * Sets the supply current, simulated. + * + */ + public void setSupplyCurrent(int current) { + m_supplyCurrent.set(current); + } + /** * Get the supply current, simulated. * diff --git a/simulation/SyntheSimJava/src/main/java/com/autodesk/synthesis/ctre/TalonFX.java b/simulation/SyntheSimJava/src/main/java/com/autodesk/synthesis/ctre/TalonFX.java index 63ed5b1e9c..e2e4016e9a 100644 --- a/simulation/SyntheSimJava/src/main/java/com/autodesk/synthesis/ctre/TalonFX.java +++ b/simulation/SyntheSimJava/src/main/java/com/autodesk/synthesis/ctre/TalonFX.java @@ -1,13 +1,29 @@ package com.autodesk.synthesis.ctre; import com.autodesk.synthesis.CANMotor; +import com.ctre.phoenix.motorcontrol.NeutralMode; public class TalonFX extends com.ctre.phoenix6.hardware.TalonFX { private CANMotor m_motor; - public TalonFX(int deviceId) { - super(deviceId); + public TalonFX(int deviceNumber) { + super(deviceNumber); - m_motor = new CANMotor("SYN TalonFX", deviceId, 0.0, false, 0.3); + m_motor = new CANMotor("SYN TalonFX", deviceNumber, 0.0, false, 0.3); + } + + public void set(double speed) { + super.set(speed); + this.m_motor.setPercentOutput(speed); + } + + public void setNeutralMode(NeutralMode mode) { + super.setNeutralMode(mode); + + this.m_motor.setBrakeMode(mode == NeutralMode.Brake); + } + + public void configureNeutralDeadaband(double deadband) { + this.m_motor.setNeutralDeadband(deadband); } } diff --git a/simulation/SyntheSimJava/src/main/java/com/autodesk/synthesis/revrobotics/CANSparkMax.java b/simulation/SyntheSimJava/src/main/java/com/autodesk/synthesis/revrobotics/CANSparkMax.java index da2087e7ab..105161b114 100644 --- a/simulation/SyntheSimJava/src/main/java/com/autodesk/synthesis/revrobotics/CANSparkMax.java +++ b/simulation/SyntheSimJava/src/main/java/com/autodesk/synthesis/revrobotics/CANSparkMax.java @@ -39,5 +39,4 @@ public REVLibError setIdleMode(com.revrobotics.CANSparkBase.IdleMode mode) { return super.setIdleMode(mode); } - } diff --git a/simulation/samples/JavaSample/src/main/java/frc/robot/Robot.java b/simulation/samples/JavaSample/src/main/java/frc/robot/Robot.java index 8a9aa5024b..2d2bea7a07 100644 --- a/simulation/samples/JavaSample/src/main/java/frc/robot/Robot.java +++ b/simulation/samples/JavaSample/src/main/java/frc/robot/Robot.java @@ -15,6 +15,7 @@ import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; import com.autodesk.synthesis.revrobotics.CANSparkMax; +import com.autodesk.synthesis.ctre.TalonFX; /** * The VM is configured to automatically run this class, and to call the functions corresponding to From 698658fb477d5bf318329982fe9fae7517c5f4db Mon Sep 17 00:00:00 2001 From: Azalea Colburn Date: Thu, 25 Jul 2024 11:25:46 -0700 Subject: [PATCH 02/47] fix behavior inputs --- .../simulation/synthesis_brain/SynthesisBrain.ts | 6 +++--- .../java/com/autodesk/synthesis/ctre/TalonFX.java | 14 +++++++++----- .../JavaSample/src/main/java/frc/robot/Robot.java | 4 ++-- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/fission/src/systems/simulation/synthesis_brain/SynthesisBrain.ts b/fission/src/systems/simulation/synthesis_brain/SynthesisBrain.ts index feb87d70bf..d6565d56a3 100644 --- a/fission/src/systems/simulation/synthesis_brain/SynthesisBrain.ts +++ b/fission/src/systems/simulation/synthesis_brain/SynthesisBrain.ts @@ -4,16 +4,16 @@ import Behavior from "../behavior/Behavior" import World from "@/systems/World" import WheelDriver from "../driver/WheelDriver" import WheelRotationStimulus from "../stimulus/WheelStimulus" -import ArcadeDriveBehavior from "../behavior/ArcadeDriveBehavior" +import ArcadeDriveBehavior from "../behavior/synthesis/ArcadeDriveBehavior" import { SimulationLayer } from "../SimulationSystem" import Jolt from "@barclah/jolt-physics" import JOLT from "@/util/loading/JoltSyncLoader" import HingeDriver from "../driver/HingeDriver" import HingeStimulus from "../stimulus/HingeStimulus" -import GenericArmBehavior from "../behavior/GenericArmBehavior" +import GenericArmBehavior from "../behavior/synthesis/GenericArmBehavior" import SliderDriver from "../driver/SliderDriver" import SliderStimulus from "../stimulus/SliderStimulus" -import GenericElevatorBehavior from "../behavior/GenericElevatorBehavior" +import GenericElevatorBehavior from "../behavior/synthesis/GenericElevatorBehavior" import PreferencesSystem from "@/systems/preferences/PreferencesSystem" import InputSystem from "@/systems/input/InputSystem" diff --git a/simulation/SyntheSimJava/src/main/java/com/autodesk/synthesis/ctre/TalonFX.java b/simulation/SyntheSimJava/src/main/java/com/autodesk/synthesis/ctre/TalonFX.java index e2e4016e9a..6b54db84b9 100644 --- a/simulation/SyntheSimJava/src/main/java/com/autodesk/synthesis/ctre/TalonFX.java +++ b/simulation/SyntheSimJava/src/main/java/com/autodesk/synthesis/ctre/TalonFX.java @@ -1,7 +1,9 @@ package com.autodesk.synthesis.ctre; import com.autodesk.synthesis.CANMotor; -import com.ctre.phoenix.motorcontrol.NeutralMode; +// import com.ctre.phoenix6.configs.TalonFXConfigurator; +// import com.ctre.phoenix6.configs.TalonFXConfiguration; +import com.ctre.phoenix6.signals.NeutralModeValue; public class TalonFX extends com.ctre.phoenix6.hardware.TalonFX { private CANMotor m_motor; @@ -11,19 +13,21 @@ public TalonFX(int deviceNumber) { m_motor = new CANMotor("SYN TalonFX", deviceNumber, 0.0, false, 0.3); } - + public void set(double speed) { super.set(speed); this.m_motor.setPercentOutput(speed); } - public void setNeutralMode(NeutralMode mode) { + public void setNeutralMode(NeutralModeValue mode) { super.setNeutralMode(mode); - this.m_motor.setBrakeMode(mode == NeutralMode.Brake); + this.m_motor.setBrakeMode(mode == NeutralModeValue.Brake); } - public void configureNeutralDeadaband(double deadband) { + public void configureNeutralDeadband(double deadband) { + //super.configureNeutralDeadband(deadband); + // TODO: Find actual deadband config method this.m_motor.setNeutralDeadband(deadband); } } diff --git a/simulation/samples/JavaSample/src/main/java/frc/robot/Robot.java b/simulation/samples/JavaSample/src/main/java/frc/robot/Robot.java index 2d2bea7a07..f2f913bb8c 100644 --- a/simulation/samples/JavaSample/src/main/java/frc/robot/Robot.java +++ b/simulation/samples/JavaSample/src/main/java/frc/robot/Robot.java @@ -4,8 +4,8 @@ package frc.robot; -import com.ctre.phoenix6.hardware.TalonFX; -import com.revrobotics.CANSparkBase.IdleMode; +// import com.ctre.phoenix6.hardware.TalonFX; +// import com.revrobotics.CANSparkBase.IdleMode; // import com.revrobotics.CANSparkMax; import com.revrobotics.CANSparkLowLevel.MotorType; From 34a7933a5cd93e49eb0cd83b62353466f7a28262 Mon Sep 17 00:00:00 2001 From: Azalea Colburn Date: Thu, 25 Jul 2024 20:04:32 -0700 Subject: [PATCH 03/47] Send all data through CANMotor to the websocket --- .../synthesis/revrobotics/CANSparkMax.java | 13 +- .../src/main/java/frc/robot/Robot.java | 240 ++++++++++-------- 2 files changed, 141 insertions(+), 112 deletions(-) diff --git a/simulation/SyntheSimJava/src/main/java/com/autodesk/synthesis/revrobotics/CANSparkMax.java b/simulation/SyntheSimJava/src/main/java/com/autodesk/synthesis/revrobotics/CANSparkMax.java index 105161b114..e60f82cc4d 100644 --- a/simulation/SyntheSimJava/src/main/java/com/autodesk/synthesis/revrobotics/CANSparkMax.java +++ b/simulation/SyntheSimJava/src/main/java/com/autodesk/synthesis/revrobotics/CANSparkMax.java @@ -15,8 +15,9 @@ public class CANSparkMax extends com.revrobotics.CANSparkMax { /** * Creates a new CANSparkMax, wrapped with simulation support. * - * @param deviceId CAN Device ID. - * @param motorType Motortype. For Simulation purposes, this is discarded at the moment. + * @param deviceId CAN Device ID. + * @param motorType Motortype. For Simulation purposes, this is discarded at the + * moment. */ public CANSparkMax(int deviceId, MotorType motorType) { super(deviceId, motorType); @@ -31,6 +32,14 @@ public void set(double percent) { m_motor.setPercentOutput(percent); } + public void test() { + System.out.println("test"); + } + + public void setNeutralDeadband(double n) { + m_motor.setNeutralDeadband(n); + } + @Override public REVLibError setIdleMode(com.revrobotics.CANSparkBase.IdleMode mode) { if (mode != null) { diff --git a/simulation/samples/JavaSample/src/main/java/frc/robot/Robot.java b/simulation/samples/JavaSample/src/main/java/frc/robot/Robot.java index f2f913bb8c..6f78dca9c9 100644 --- a/simulation/samples/JavaSample/src/main/java/frc/robot/Robot.java +++ b/simulation/samples/JavaSample/src/main/java/frc/robot/Robot.java @@ -4,9 +4,6 @@ package frc.robot; -// import com.ctre.phoenix6.hardware.TalonFX; -// import com.revrobotics.CANSparkBase.IdleMode; -// import com.revrobotics.CANSparkMax; import com.revrobotics.CANSparkLowLevel.MotorType; import edu.wpi.first.wpilibj.TimedRobot; @@ -18,115 +15,138 @@ import com.autodesk.synthesis.ctre.TalonFX; /** - * The VM is configured to automatically run this class, and to call the functions corresponding to - * each mode, as described in the TimedRobot documentation. If you change the name of this class or - * the package after creating this project, you must also update the build.gradle file in the + * The VM is configured to automatically run this class, and to call the + * functions corresponding to + * each mode, as described in the TimedRobot documentation. If you change the + * name of this class or + * the package after creating this project, you must also update the + * build.gradle file in the * project. */ public class Robot extends TimedRobot { - private static final String kDefaultAuto = "Default"; - private static final String kCustomAuto = "My Auto"; - private String m_autoSelected; - private final SendableChooser m_chooser = new SendableChooser<>(); - - private Spark m_Spark = new Spark(0); - private CANSparkMax m_SparkMax = new CANSparkMax(1, MotorType.kBrushless); - private TalonFX m_Talon = new TalonFX(2); - - /** - * This function is run when the robot is first started up and should be used for any - * initialization code. - */ - @Override - public void robotInit() { - m_chooser.setDefaultOption("Default Auto", kDefaultAuto); - m_chooser.addOption("My Auto", kCustomAuto); - SmartDashboard.putData("Auto choices", m_chooser); - } - - /** - * This function is called every 20 ms, no matter the mode. Use this for items like diagnostics - * that you want ran during disabled, autonomous, teleoperated and test. - * - *

This runs after the mode specific periodic functions, but before LiveWindow and - * SmartDashboard integrated updating. - */ - @Override - public void robotPeriodic() {} - - /** - * This autonomous (along with the chooser code above) shows how to select between different - * autonomous modes using the dashboard. The sendable chooser code works with the Java - * SmartDashboard. If you prefer the LabVIEW Dashboard, remove all of the chooser code and - * uncomment the getString line to get the auto name from the text box below the Gyro - * - *

You can add additional auto modes by adding additional comparisons to the switch structure - * below with additional strings. If using the SendableChooser make sure to add them to the - * chooser code above as well. - */ - @Override - public void autonomousInit() { - m_autoSelected = m_chooser.getSelected(); - // m_autoSelected = SmartDashboard.getString("Auto Selector", kDefaultAuto); - System.out.println("Auto selected: " + m_autoSelected); - } - - /** This function is called periodically during autonomous. */ - @Override - public void autonomousPeriodic() { - - m_Spark.set(0.5); - m_SparkMax.set(1.0); - m_Talon.set(-1.0); - - switch (m_autoSelected) { - case kCustomAuto: - // Put custom auto code here - break; - case kDefaultAuto: - default: - // Put default auto code here - break; + private static final String kDefaultAuto = "Default"; + private static final String kCustomAuto = "My Auto"; + private String m_autoSelected; + private final SendableChooser m_chooser = new SendableChooser<>(); + + // private Spark m_Spark = new Spark(0); + private CANSparkMax m_SparkMax = new CANSparkMax(1, MotorType.kBrushless); + private TalonFX m_Talon = new TalonFX(2); + + /** + * This function is run when the robot is first started up and should be used + * for any + * initialization code. + */ + @Override + public void robotInit() { + m_chooser.setDefaultOption("Default Auto", kDefaultAuto); + m_chooser.addOption("My Auto", kCustomAuto); + SmartDashboard.putData("Auto choices", m_chooser); + } + + /** + * This function is called every 20 ms, no matter the mode. Use this for items + * like diagnostics + * that you want ran during disabled, autonomous, teleoperated and test. + * + *

+ * This runs after the mode specific periodic functions, but before LiveWindow + * and + * SmartDashboard integrated updating. + */ + @Override + public void robotPeriodic() { + } + + /** + * This autonomous (along with the chooser code above) shows how to select + * between different + * autonomous modes using the dashboard. The sendable chooser code works with + * the Java + * SmartDashboard. If you prefer the LabVIEW Dashboard, remove all of the + * chooser code and + * uncomment the getString line to get the auto name from the text box below the + * Gyro + * + *

+ * You can add additional auto modes by adding additional comparisons to the + * switch structure + * below with additional strings. If using the SendableChooser make sure to add + * them to the + * chooser code above as well. + */ + @Override + public void autonomousInit() { + m_autoSelected = m_chooser.getSelected(); + // m_autoSelected = SmartDashboard.getString("Auto Selector", kDefaultAuto); + System.out.println("Auto selected: " + m_autoSelected); + } + + /** This function is called periodically during autonomous. */ + @Override + public void autonomousPeriodic() { + + // m_Spark.set(0.5); + m_SparkMax.set(1.0); + // m_SparkMax.setNeutralDeadband(0.01); // FIXME: for some reason I can't set + // the deadband even after defining the function in the child + m_Talon.set(-1.0); + + switch (m_autoSelected) { + case kCustomAuto: + // Put custom auto code here + break; + case kDefaultAuto: + default: + // Put default auto code here + break; + } + } + + /** This function is called once when teleop is enabled. */ + @Override + public void teleopInit() { + } + + /** This function is called periodically during operator control. */ + @Override + public void teleopPeriodic() { + // m_Spark.set(0.25); + m_SparkMax.set(0.75); + m_Talon.set(-0.5); + } + + /** This function is called once when the robot is disabled. */ + @Override + public void disabledInit() { + // m_Spark.set(0.0); + m_SparkMax.set(0.0); + m_Talon.set(0.0); + } + + /** This function is called periodically when disabled. */ + @Override + public void disabledPeriodic() { + } + + /** This function is called once when test mode is enabled. */ + @Override + public void testInit() { + } + + /** This function is called periodically during test mode. */ + @Override + public void testPeriodic() { + } + + /** This function is called once when the robot is first started up. */ + @Override + public void simulationInit() { + } + + /** This function is called periodically whilst in simulation. */ + @Override + public void simulationPeriodic() { } - } - - /** This function is called once when teleop is enabled. */ - @Override - public void teleopInit() {} - - /** This function is called periodically during operator control. */ - @Override - public void teleopPeriodic() { - m_Spark.set(0.25); - m_SparkMax.set(0.75); - m_Talon.set(-0.5); - } - - /** This function is called once when the robot is disabled. */ - @Override - public void disabledInit() { - m_Spark.set(0.0); - m_SparkMax.set(0.0); - m_Talon.set(0.0); - } - - /** This function is called periodically when disabled. */ - @Override - public void disabledPeriodic() {} - - /** This function is called once when test mode is enabled. */ - @Override - public void testInit() {} - - /** This function is called periodically during test mode. */ - @Override - public void testPeriodic() {} - - /** This function is called once when the robot is first started up. */ - @Override - public void simulationInit() {} - - /** This function is called periodically whilst in simulation. */ - @Override - public void simulationPeriodic() {} } From f5dedc5e64cb074c50abd042eba5fb7b5bdf0aa7 Mon Sep 17 00:00:00 2001 From: Azalea Colburn Date: Fri, 26 Jul 2024 14:10:41 -0700 Subject: [PATCH 04/47] removed awful switch statement in brain --- .../systems/simulation/SimulationSystem.ts | 12 +- .../simulation/wpilib_brain/WPILibBrain.ts | 166 ++++++++++-------- 2 files changed, 99 insertions(+), 79 deletions(-) diff --git a/fission/src/systems/simulation/SimulationSystem.ts b/fission/src/systems/simulation/SimulationSystem.ts index 331739f8a7..9afffe0cbf 100644 --- a/fission/src/systems/simulation/SimulationSystem.ts +++ b/fission/src/systems/simulation/SimulationSystem.ts @@ -75,25 +75,27 @@ class SimulationLayer { this._drivers = [] this._stimuli = [] this._mechanism.constraints.forEach(x => { + let stim: Stimulus if (x.constraint.GetSubType() == JOLT.EConstraintSubType_Hinge) { const hinge = JOLT.castObject(x.constraint, JOLT.HingeConstraint) const driver = new HingeDriver(hinge) this._drivers.push(driver) - const stim = new HingeStimulus(hinge) + stim = new HingeStimulus(hinge) this._stimuli.push(stim) } else if (x.constraint.GetSubType() == JOLT.EConstraintSubType_Vehicle) { const vehicle = JOLT.castObject(x.constraint, JOLT.VehicleConstraint) const driver = new WheelDriver(vehicle) this._drivers.push(driver) - const stim = new WheelRotationStimulus(vehicle.GetWheel(0)) + stim = new WheelRotationStimulus(vehicle.GetWheel(0)) this._stimuli.push(stim) } else if (x.constraint.GetSubType() == JOLT.EConstraintSubType_Slider) { const slider = JOLT.castObject(x.constraint, JOLT.SliderConstraint) const driver = new SliderDriver(slider) this._drivers.push(driver) - const stim = new SliderStimulus(slider) + stim = new SliderStimulus(slider) this._stimuli.push(stim) } + this._stimuli.push(stim) }) this._stimuli.push(new ChassisStimulus(mechanism.nodeToBody.get(mechanism.rootBody)!)) } @@ -109,9 +111,7 @@ class SimulationLayer { this._brain = brain - if (this._brain) { - this._brain.Enable() - } + if (this._brain) this._brain.Enable() } } diff --git a/fission/src/systems/simulation/wpilib_brain/WPILibBrain.ts b/fission/src/systems/simulation/wpilib_brain/WPILibBrain.ts index c4839662b5..45a4a09267 100644 --- a/fission/src/systems/simulation/wpilib_brain/WPILibBrain.ts +++ b/fission/src/systems/simulation/wpilib_brain/WPILibBrain.ts @@ -19,11 +19,27 @@ const worker = new WPILibWSWorker() const PWM_SPEED = "> = new Map( Object.entries({ - "CANMotor": { + CANMotor: { "CANSparkMax[0]": { - " [key as SimType, new Map(Object.entries(value))]) + }, + }).map(([key, value]) => [key as SimType, new Map(Object.entries(value))]) ) export const simMap = new Map>() export class SimGeneric { - private constructor() { } + private constructor() {} public static Get(simType: SimType, device: string, field: string, defaultValue?: T): T | undefined { const fieldType = GetFieldType(field) @@ -138,34 +153,30 @@ export class SimGeneric { } export class SimPWM { - private constructor() { } + private constructor() {} public static GetSpeed(device: string): number | undefined { - return SimGeneric.Get("PWM", device, PWM_SPEED, 0.0) + return SimGeneric.Get(SimType.PWM, device, PWM_SPEED, 0.0) } public static GetPosition(device: string): number | undefined { - return SimGeneric.Get("PWM", device, PWM_POSITION, 0.0) + return SimGeneric.Get(SimType.PWM, device, PWM_POSITION, 0.0) } } export class SimCAN { - private constructor() { } + private constructor() {} public static GetDeviceWithID(id: number, type: SimType): any { - const id_exp = /.*\[(\d+)\]/g; + const id_exp = /.*\[(\d+)\]/g const entries = [...simMap.entries()].filter(([simType, _data]) => simType == type || simType == "SimDevice") for (const [_simType, data] of entries) { for (const key of data.keys()) { - let result; - if ((result = [...key.matchAll(id_exp)]) != undefined) { - if (result.length > 0 && result[0].length > 1) { - const parsed_id = parseInt(result[0][1]); - if (parsed_id == id) { - return data.get(key) - } - } - } + let result = [...key.matchAll(id_exp)] + if (result?.length <= 0 || result[0].length <= 1) continue + + const parsed_id = parseInt(result[0][1]) + if (parsed_id == id) return data.get(key) } } return undefined @@ -173,35 +184,63 @@ export class SimCAN { } export class SimCANMotor { - private constructor() { } + private constructor() {} + + // public static GetDutyCycle(device: string): number | undefined { + // return SimGeneric.Get("CANMotor", device, CANMOTOR_DUTY_CYCLE, 0.0) + // } + // + // public static SetSupplyVoltage(device: string, voltage: number): boolean { + // return SimGeneric.Set("CANMotor", device, CANMOTOR_SUPPLY_VOLTAGE, voltage) + // } + + public static GetPercentOutput(device: string): number | undefined { + return SimGeneric.Get(SimType.CANMOTOR, device, CANMOTOR_PERCENT_OUTPUT, 0.0) + } - public static GetDutyCycle(device: string): number | undefined { - return SimGeneric.Get("CANMotor", device, CANMOTOR_DUTY_CYCLE, 0.0) + public static GetBrakeMode(device: string): number | undefined { + return SimGeneric.Get(SimType.CANMOTOR, device, CANMOTOR_BRAKE_MODE, 0.0) } - public static SetSupplyVoltage(device: string, voltage: number): boolean { - return SimGeneric.Set("CANMotor", device, CANMOTOR_SUPPLY_VOLTAGE, voltage) + public static GetNeutralDeadband(device: string): number | undefined { + return SimGeneric.Get(SimType.CANMOTOR, device, CANMOTOR_NEUTRAL_DEADBAND, 0.0) + } + + public static SetSupplyCurrent(device: string, current: number): boolean { + return SimGeneric.Set(SimType.CANMOTOR, device, CANMOTOR_SUPPLY_CURRENT, current) + } + + public static SetMotorCurrent(device: string, current: number): boolean { + return SimGeneric.Set(SimType.CANMOTOR, device, CANMOTOR_MOTOR_CURRENT, current) + } + + public static SetBusVoltage(device: string, voltage: number): boolean { + return SimGeneric.Set(SimType.CANMOTOR, device, CANMOTOR_BUS_VOLTAGE, voltage) } } export class SimCANEncoder { - private constructor() { } + private constructor() {} - public static SetRawInputPosition(device: string, rawInputPosition: number): boolean { - return SimGeneric.Set("CANEncoder", device, CANENCODER_RAW_INPUT_POSITION, rawInputPosition) + public static SetVelocity(device: string, velocity: number): boolean { + return SimGeneric.Set(SimType.CANENCODER, device, CANENCODER_VELOCITY, velocity) + } + + public static SetPosition(device: string, position: number): boolean { + return SimGeneric.Set(SimType.CANENCODER, device, CANENCODER_POSITION, position) } } worker.addEventListener("message", (eventData: MessageEvent) => { let data: any | undefined - try { - if (typeof eventData.data == "object") { - data = eventData.data - } else { + if (typeof eventData.data == "object") { + data = eventData.data + } else { + try { data = JSON.parse(eventData.data) + } catch (e) { + console.warn(`Failed to parse data:\n${JSON.stringify(eventData.data)}`) } - } catch (e) { - console.warn(`Failed to parse data:\n${JSON.stringify(eventData.data)}`) } if (!data || !data.type) { @@ -209,36 +248,17 @@ worker.addEventListener("message", (eventData: MessageEvent) => { return } - // console.debug(data) - const device = data.device const updateData = data.data - switch (data.type) { - case "PWM": - console.debug("pwm") - UpdateSimMap("PWM", device, updateData) - break - case "Solenoid": - console.debug("solenoid") - UpdateSimMap("Solenoid", device, updateData) - break - case "SimDevice": - console.debug("simdevice") - UpdateSimMap("SimDevice", device, updateData) - break - case "CANMotor": - console.debug("canmotor") - UpdateSimMap("CANMotor", device, updateData) - break - case "CANEncoder": - console.debug("canencoder") - UpdateSimMap("CANEncoder", device, updateData) - break - default: - // console.debug(`Unrecognized Message:\n${data}`) - break + if (!(data.type in SimType)) { + console.error(`Unrecognized SimType: ${data.type}\n${data.data}`) + return } + + console.debug(data.type); + + UpdateSimMap(data.type, device, updateData) }) function UpdateSimMap(type: SimType, device: string, updateData: any) { @@ -286,7 +306,7 @@ class WPILibBrain extends Brain { // this.configureArcadeDriveBehavior() } - public addSimOutputGroup(device: SimOutputGroup) { + public addSimOutputGroup(device: SimOutputGroup): void { this._simDevices.push(device) } @@ -343,10 +363,10 @@ export class PWMGroup extends SimOutputGroup { super(name, ports, drivers, "PWM") } - public Update(deltaT: number) { + public Update(_deltaT: number) { // let average = 0; for (const port of this.ports) { - const speed = SimPWM.GetSpeed(`${port}`) ?? 0; + const speed = SimPWM.GetSpeed(`${port}`) ?? 0 // average += speed; console.log(port, speed) } @@ -366,7 +386,7 @@ export class CANGroup extends SimOutputGroup { public Update(_deltaT: number) { for (const port of this.ports) { - const device = SimCAN.GetDeviceWithID(port, this.type); + const device = SimCAN.GetDeviceWithID(port, this.type) console.log(port, device) } } From 1c065f448df10316196ae778a54ca4afe3a9ba79 Mon Sep 17 00:00:00 2001 From: Azalea Colburn Date: Mon, 29 Jul 2024 09:43:21 -0700 Subject: [PATCH 05/47] restore brain changes lost in merge --- .../simulation/wpilib_brain/WPILibBrain.ts | 164 +++++++++++++----- 1 file changed, 121 insertions(+), 43 deletions(-) diff --git a/fission/src/systems/simulation/wpilib_brain/WPILibBrain.ts b/fission/src/systems/simulation/wpilib_brain/WPILibBrain.ts index 3d9ee7d65e..a6e47e05e1 100644 --- a/fission/src/systems/simulation/wpilib_brain/WPILibBrain.ts +++ b/fission/src/systems/simulation/wpilib_brain/WPILibBrain.ts @@ -3,19 +3,43 @@ import Mechanism from "@/systems/physics/Mechanism" import Brain from "../Brain" import WPILibWSWorker from "./WPILibWSWorker?worker" +import Behavior from "../behavior/Behavior" import { SimulationLayer } from "../SimulationSystem" import World from "@/systems/World" import Driver from "../driver/Driver" +import WheelDriver from "../driver/WheelDriver" +import WheelRotationStimulus from "../stimulus/WheelStimulus" +import Jolt from "@barclah/jolt-physics" +import JOLT from "@/util/loading/JoltSyncLoader" +import ArcadeDriveBehavior from "../behavior/synthesis/ArcadeDriveBehavior" +import WPILibArcadeDriveBehavior from "../behavior/wpilib/WPILibArcadeDriveBehavior" +import { mirabuf } from "@/proto/mirabuf" const worker = new WPILibWSWorker() const PWM_SPEED = "> = new Map( + Object.entries({ + CANMotor: { + "CANSparkMax[0]": { + " [key as SimType, new Map(Object.entries(value))]) +) + export const simMap = new Map>() export class SimGeneric { @@ -107,11 +156,11 @@ export class SimPWM { private constructor() {} public static GetSpeed(device: string): number | undefined { - return SimGeneric.Get("PWM", device, PWM_SPEED, 0.0) + return SimGeneric.Get(SimType.PWM, device, PWM_SPEED, 0.0) } public static GetPosition(device: string): number | undefined { - return SimGeneric.Get("PWM", device, PWM_POSITION, 0.0) + return SimGeneric.Get(SimType.PWM, device, PWM_POSITION, 0.0) } } @@ -123,12 +172,11 @@ export class SimCAN { const entries = [...simMap.entries()].filter(([simType, _data]) => simType == type || simType == "SimDevice") for (const [_simType, data] of entries) { for (const key of data.keys()) { - const result = [...key.matchAll(id_exp)] + let result = [...key.matchAll(id_exp)] if (result?.length <= 0 || result[0].length <= 1) continue - const parsed_id = parseInt(result[0][1]) - if (parsed_id != id) continue - return data.get(key) + const parsed_id = parseInt(result[0][1]) + if (parsed_id == id) return data.get(key) } } return undefined @@ -138,33 +186,61 @@ export class SimCAN { export class SimCANMotor { private constructor() {} - public static GetDutyCycle(device: string): number | undefined { - return SimGeneric.Get("CANMotor", device, CANMOTOR_DUTY_CYCLE, 0.0) + // public static GetDutyCycle(device: string): number | undefined { + // return SimGeneric.Get("CANMotor", device, CANMOTOR_DUTY_CYCLE, 0.0) + // } + // + // public static SetSupplyVoltage(device: string, voltage: number): boolean { + // return SimGeneric.Set("CANMotor", device, CANMOTOR_SUPPLY_VOLTAGE, voltage) + // } + + public static GetPercentOutput(device: string): number | undefined { + return SimGeneric.Get(SimType.CANMOTOR, device, CANMOTOR_PERCENT_OUTPUT, 0.0) + } + + public static GetBrakeMode(device: string): number | undefined { + return SimGeneric.Get(SimType.CANMOTOR, device, CANMOTOR_BRAKE_MODE, 0.0) + } + + public static GetNeutralDeadband(device: string): number | undefined { + return SimGeneric.Get(SimType.CANMOTOR, device, CANMOTOR_NEUTRAL_DEADBAND, 0.0) } - public static SetSupplyVoltage(device: string, voltage: number): boolean { - return SimGeneric.Set("CANMotor", device, CANMOTOR_SUPPLY_VOLTAGE, voltage) + public static SetSupplyCurrent(device: string, current: number): boolean { + return SimGeneric.Set(SimType.CANMOTOR, device, CANMOTOR_SUPPLY_CURRENT, current) + } + + public static SetMotorCurrent(device: string, current: number): boolean { + return SimGeneric.Set(SimType.CANMOTOR, device, CANMOTOR_MOTOR_CURRENT, current) + } + + public static SetBusVoltage(device: string, voltage: number): boolean { + return SimGeneric.Set(SimType.CANMOTOR, device, CANMOTOR_BUS_VOLTAGE, voltage) } } export class SimCANEncoder { private constructor() {} - public static SetRawInputPosition(device: string, rawInputPosition: number): boolean { - return SimGeneric.Set("CANEncoder", device, CANENCODER_RAW_INPUT_POSITION, rawInputPosition) + public static SetVelocity(device: string, velocity: number): boolean { + return SimGeneric.Set(SimType.CANENCODER, device, CANENCODER_VELOCITY, velocity) + } + + public static SetPosition(device: string, position: number): boolean { + return SimGeneric.Set(SimType.CANENCODER, device, CANENCODER_POSITION, position) } } worker.addEventListener("message", (eventData: MessageEvent) => { let data: any | undefined - try { - if (typeof eventData.data == "object") { - data = eventData.data - } else { + if (typeof eventData.data == "object") { + data = eventData.data + } else { + try { data = JSON.parse(eventData.data) + } catch (e) { + console.warn(`Failed to parse data:\n${JSON.stringify(eventData.data)}`) } - } catch (e) { - console.warn(`Failed to parse data:\n${JSON.stringify(eventData.data)}`) } if (!data || !data.type) { @@ -175,25 +251,14 @@ worker.addEventListener("message", (eventData: MessageEvent) => { const device = data.device const updateData = data.data - switch (data.type) { - case "PWM": - UpdateSimMap("PWM", device, updateData) - break - case "Solenoid": - UpdateSimMap("Solenoid", device, updateData) - break - case "SimDevice": - UpdateSimMap("SimDevice", device, updateData) - break - case "CANMotor": - UpdateSimMap("CANMotor", device, updateData) - break - case "CANEncoder": - UpdateSimMap("CANEncoder", device, updateData) - break - default: - break + if (!(data.type in SimType)) { + console.error(`Unrecognized SimType: ${data.type}\n${data.data}`) + return } + + console.debug(data.type); + + UpdateSimMap(data.type, device, updateData) }) function UpdateSimMap(type: SimType, device: string, updateData: any) { @@ -214,10 +279,15 @@ function UpdateSimMap(type: SimType, device: string, updateData: any) { } class WPILibBrain extends Brain { + private _behaviors: Behavior[] = [] private _simLayer: SimulationLayer private _simDevices: SimOutputGroup[] = [] + public static robotsSpawned: string[] = [] + + private static _currentRobotIndex: number = 0 + constructor(mechanism: Mechanism) { super(mechanism) @@ -227,13 +297,21 @@ class WPILibBrain extends Brain { console.warn("SimulationLayer is undefined") return } + + // if (mechanism.controllable) { + // WPILibBrain.robotsSpawned.push(this.getNumberedAssemblyName()) + // } + + // WPILibBrain._currentRobotIndex++ + // this.configureArcadeDriveBehavior() } - public addSimOutputGroup(device: SimOutputGroup) { + public addSimOutputGroup(device: SimOutputGroup): void { this._simDevices.push(device) } public Update(deltaT: number): void { + // this._behaviors.forEach(b => b.Update(deltaT)) this._simDevices.forEach(d => d.Update(deltaT)) } @@ -296,7 +374,7 @@ export class PWMGroup extends SimOutputGroup { // this.drivers.forEach(d => { // (d as WheelDriver).targetWheelSpeed = average * 40 - // d.Update(_deltaT) + // d.Update(deltaT) // }) } } @@ -312,4 +390,4 @@ export class CANGroup extends SimOutputGroup { console.log(port, device) } } -} +} \ No newline at end of file From dd56b75968f72a2bece37f361cc486dc82e22f8a Mon Sep 17 00:00:00 2001 From: PepperLola Date: Mon, 29 Jul 2024 15:47:14 -0700 Subject: [PATCH 06/47] refactor sim input + output, encoder configuration modal --- .../systems/simulation/SimulationSystem.ts | 6 +- .../simulation/stimulus/ChassisStimulus.ts | 5 +- .../simulation/stimulus/EncoderStimulus.ts | 5 +- .../simulation/stimulus/HingeStimulus.ts | 5 +- .../simulation/stimulus/SliderStimulus.ts | 5 +- .../systems/simulation/stimulus/Stimulus.ts | 12 ++++ .../simulation/stimulus/WheelStimulus.ts | 5 +- .../simulation/wpilib_brain/SimInput.ts | 20 +++++++ .../simulation/wpilib_brain/SimOutput.ts | 52 +++++++++++++++++ .../simulation/wpilib_brain/WPILibBrain.ts | 53 +---------------- .../rio-config/RCConfigCANGroupModal.tsx | 5 +- .../rio-config/RCConfigEncoderModal.tsx | 57 +++++++++++++------ .../rio-config/RCConfigPWMGroupModal.tsx | 6 +- fission/src/ui/panels/DebugPanel.tsx | 10 ++-- 14 files changed, 155 insertions(+), 91 deletions(-) create mode 100644 fission/src/systems/simulation/wpilib_brain/SimInput.ts create mode 100644 fission/src/systems/simulation/wpilib_brain/SimOutput.ts diff --git a/fission/src/systems/simulation/SimulationSystem.ts b/fission/src/systems/simulation/SimulationSystem.ts index f0feeba8b2..358b5186df 100644 --- a/fission/src/systems/simulation/SimulationSystem.ts +++ b/fission/src/systems/simulation/SimulationSystem.ts @@ -87,19 +87,19 @@ class SimulationLayer { const hinge = JOLT.castObject(x.constraint, JOLT.HingeConstraint) const driver = new HingeDriver(hinge, x.info) this._drivers.push(driver) - const stim = new HingeStimulus(hinge) + const stim = new HingeStimulus(hinge, x.info) this._stimuli.push(stim) } else if (x.constraint.GetSubType() == JOLT.EConstraintSubType_Vehicle) { const vehicle = JOLT.castObject(x.constraint, JOLT.VehicleConstraint) const driver = new WheelDriver(vehicle, x.info) this._drivers.push(driver) - const stim = new WheelRotationStimulus(vehicle.GetWheel(0)) + const stim = new WheelRotationStimulus(vehicle.GetWheel(0), x.info) this._stimuli.push(stim) } else if (x.constraint.GetSubType() == JOLT.EConstraintSubType_Slider) { const slider = JOLT.castObject(x.constraint, JOLT.SliderConstraint) const driver = new SliderDriver(slider, x.info) this._drivers.push(driver) - const stim = new SliderStimulus(slider) + const stim = new SliderStimulus(slider, x.info) this._stimuli.push(stim) } }) diff --git a/fission/src/systems/simulation/stimulus/ChassisStimulus.ts b/fission/src/systems/simulation/stimulus/ChassisStimulus.ts index fa59a64f1b..41d160dc6a 100644 --- a/fission/src/systems/simulation/stimulus/ChassisStimulus.ts +++ b/fission/src/systems/simulation/stimulus/ChassisStimulus.ts @@ -1,6 +1,7 @@ import Jolt from "@barclah/jolt-physics" import Stimulus from "./Stimulus" import World from "@/systems/World" +import { mirabuf } from "@/proto/mirabuf" class ChassisStimulus extends Stimulus { private _body: Jolt.Body @@ -19,8 +20,8 @@ class ChassisStimulus extends Stimulus { return this._body.GetRotation().GetEulerAngles() } - public constructor(bodyId: Jolt.BodyID) { - super() + public constructor(bodyId: Jolt.BodyID, info?: mirabuf.IInfo) { + super(info) this._body = World.PhysicsSystem.GetBody(bodyId) this._mass = this._body.GetShape().GetMassProperties().mMass diff --git a/fission/src/systems/simulation/stimulus/EncoderStimulus.ts b/fission/src/systems/simulation/stimulus/EncoderStimulus.ts index bee93b4923..6b88f5d7b0 100644 --- a/fission/src/systems/simulation/stimulus/EncoderStimulus.ts +++ b/fission/src/systems/simulation/stimulus/EncoderStimulus.ts @@ -1,11 +1,12 @@ +import { mirabuf } from "@/proto/mirabuf" import Stimulus from "./Stimulus" abstract class EncoderStimulus extends Stimulus { public abstract get positionValue(): number public abstract get velocityValue(): number - protected constructor() { - super() + protected constructor(info?: mirabuf.IInfo) { + super(info) } public abstract Update(_: number): void diff --git a/fission/src/systems/simulation/stimulus/HingeStimulus.ts b/fission/src/systems/simulation/stimulus/HingeStimulus.ts index bcb8464275..b26dd7687d 100644 --- a/fission/src/systems/simulation/stimulus/HingeStimulus.ts +++ b/fission/src/systems/simulation/stimulus/HingeStimulus.ts @@ -1,5 +1,6 @@ import Jolt from "@barclah/jolt-physics" import EncoderStimulus from "./EncoderStimulus" +import { mirabuf } from "@/proto/mirabuf" class HingeStimulus extends EncoderStimulus { private _accum: boolean = false @@ -25,8 +26,8 @@ class HingeStimulus extends EncoderStimulus { this._accum = shouldAccum } - public constructor(hinge: Jolt.HingeConstraint) { - super() + public constructor(hinge: Jolt.HingeConstraint, info?: mirabuf.IInfo) { + super(info) this._hinge = hinge } diff --git a/fission/src/systems/simulation/stimulus/SliderStimulus.ts b/fission/src/systems/simulation/stimulus/SliderStimulus.ts index 0e66eb63b6..3235256a25 100644 --- a/fission/src/systems/simulation/stimulus/SliderStimulus.ts +++ b/fission/src/systems/simulation/stimulus/SliderStimulus.ts @@ -1,5 +1,6 @@ import Jolt from "@barclah/jolt-physics" import EncoderStimulus from "./EncoderStimulus" +import { mirabuf } from "@/proto/mirabuf" class SliderStimulus extends EncoderStimulus { private _slider: Jolt.SliderConstraint @@ -12,8 +13,8 @@ class SliderStimulus extends EncoderStimulus { return this._velocity } - public constructor(slider: Jolt.SliderConstraint) { - super() + public constructor(slider: Jolt.SliderConstraint, info?: mirabuf.IInfo) { + super(info) this._slider = slider } diff --git a/fission/src/systems/simulation/stimulus/Stimulus.ts b/fission/src/systems/simulation/stimulus/Stimulus.ts index 5dd744cce8..9c5ab8758b 100644 --- a/fission/src/systems/simulation/stimulus/Stimulus.ts +++ b/fission/src/systems/simulation/stimulus/Stimulus.ts @@ -1,5 +1,17 @@ +import { mirabuf } from "@/proto/mirabuf" + abstract class Stimulus { + private _info?: mirabuf.IInfo + + constructor(info?: mirabuf.IInfo) { + this._info = info + } + public abstract Update(deltaT: number): void + + public get info() { + return this._info + } } export default Stimulus diff --git a/fission/src/systems/simulation/stimulus/WheelStimulus.ts b/fission/src/systems/simulation/stimulus/WheelStimulus.ts index cfb6206085..32214b5336 100644 --- a/fission/src/systems/simulation/stimulus/WheelStimulus.ts +++ b/fission/src/systems/simulation/stimulus/WheelStimulus.ts @@ -1,5 +1,6 @@ import Jolt from "@barclah/jolt-physics" import EncoderStimulus from "./EncoderStimulus" +import { mirabuf } from "@/proto/mirabuf" /** * @@ -28,8 +29,8 @@ class WheelRotationStimulus extends EncoderStimulus { this._accum = shouldAccum } - public constructor(wheel: Jolt.Wheel) { - super() + public constructor(wheel: Jolt.Wheel, info?: mirabuf.IInfo) { + super(info) this._wheel = wheel } diff --git a/fission/src/systems/simulation/wpilib_brain/SimInput.ts b/fission/src/systems/simulation/wpilib_brain/SimInput.ts new file mode 100644 index 0000000000..483fcbcd2e --- /dev/null +++ b/fission/src/systems/simulation/wpilib_brain/SimInput.ts @@ -0,0 +1,20 @@ +import EncoderStimulus from "../stimulus/EncoderStimulus" +import { SimCANEncoder } from "./WPILibBrain" + +export interface SimInput { + Update: (deltaT: number) => void +} + +export class Encoder implements SimInput { + private _device: number + private _stimulus: EncoderStimulus + + constructor(device: number, stimulus: EncoderStimulus) { + this._device = device + this._stimulus = stimulus + } + + public Update(_deltaT: number) { + SimCANEncoder.SetRawInputPosition(`${this._device}`, this._stimulus.positionValue) + } +} diff --git a/fission/src/systems/simulation/wpilib_brain/SimOutput.ts b/fission/src/systems/simulation/wpilib_brain/SimOutput.ts new file mode 100644 index 0000000000..846910e96f --- /dev/null +++ b/fission/src/systems/simulation/wpilib_brain/SimOutput.ts @@ -0,0 +1,52 @@ +import Driver from "../driver/Driver" +import { SimCAN, SimPWM, SimType } from "./WPILibBrain" + +export abstract class SimOutputGroup { + public name: string + public ports: number[] + public drivers: Driver[] + public type: SimType + + public constructor(name: string, ports: number[], drivers: Driver[], type: SimType) { + this.name = name + this.ports = ports + this.drivers = drivers + this.type = type + } + + public abstract Update(deltaT: number): void +} + +export class PWMOutputGroup extends SimOutputGroup { + public constructor(name: string, ports: number[], drivers: Driver[]) { + super(name, ports, drivers, "PWM") + } + + public Update(_deltaT: number) { + // let average = 0; + for (const port of this.ports) { + const speed = SimPWM.GetSpeed(`${port}`) ?? 0 + // average += speed; + console.log(port, speed) + } + // average /= this.ports.length + + // this.drivers.forEach(d => { + // (d as WheelDriver).targetWheelSpeed = average * 40 + // d.Update(_deltaT) + // }) + } +} + +export class CANOutputGroup extends SimOutputGroup { + public constructor(name: string, ports: number[], drivers: Driver[]) { + super(name, ports, drivers, "CANMotor") + } + + public Update(_deltaT: number) { + for (const port of this.ports) { + const device = SimCAN.GetDeviceWithID(port, this.type) + console.log(port, device) + } + } +} diff --git a/fission/src/systems/simulation/wpilib_brain/WPILibBrain.ts b/fission/src/systems/simulation/wpilib_brain/WPILibBrain.ts index 3d9ee7d65e..cc848229c1 100644 --- a/fission/src/systems/simulation/wpilib_brain/WPILibBrain.ts +++ b/fission/src/systems/simulation/wpilib_brain/WPILibBrain.ts @@ -5,7 +5,8 @@ import Brain from "../Brain" import WPILibWSWorker from "./WPILibWSWorker?worker" import { SimulationLayer } from "../SimulationSystem" import World from "@/systems/World" -import Driver from "../driver/Driver" + +import { SimOutputGroup } from "./SimOutput" const worker = new WPILibWSWorker() @@ -263,53 +264,3 @@ export class SimMapUpdateEvent extends Event { } export default WPILibBrain - -abstract class SimOutputGroup { - public name: string - public ports: number[] - public drivers: Driver[] - public type: SimType - - public constructor(name: string, ports: number[], drivers: Driver[], type: SimType) { - this.name = name - this.ports = ports - this.drivers = drivers - this.type = type - } - - public abstract Update(deltaT: number): void -} - -export class PWMGroup extends SimOutputGroup { - public constructor(name: string, ports: number[], drivers: Driver[]) { - super(name, ports, drivers, "PWM") - } - - public Update(_deltaT: number) { - // let average = 0; - for (const port of this.ports) { - const speed = SimPWM.GetSpeed(`${port}`) ?? 0 - // average += speed; - console.log(port, speed) - } - // average /= this.ports.length - - // this.drivers.forEach(d => { - // (d as WheelDriver).targetWheelSpeed = average * 40 - // d.Update(_deltaT) - // }) - } -} - -export class CANGroup extends SimOutputGroup { - public constructor(name: string, ports: number[], drivers: Driver[]) { - super(name, ports, drivers, "CANMotor") - } - - public Update(_deltaT: number) { - for (const port of this.ports) { - const device = SimCAN.GetDeviceWithID(port, this.type) - console.log(port, device) - } - } -} diff --git a/fission/src/ui/modals/configuring/rio-config/RCConfigCANGroupModal.tsx b/fission/src/ui/modals/configuring/rio-config/RCConfigCANGroupModal.tsx index 8da3bec73c..e7bfe44ee3 100644 --- a/fission/src/ui/modals/configuring/rio-config/RCConfigCANGroupModal.tsx +++ b/fission/src/ui/modals/configuring/rio-config/RCConfigCANGroupModal.tsx @@ -8,7 +8,8 @@ import Checkbox from "@/components/Checkbox" import Container from "@/components/Container" import Label, { LabelSize } from "@/components/Label" import Input from "@/components/Input" -import WPILibBrain, { CANGroup, simMap } from "@/systems/simulation/wpilib_brain/WPILibBrain" +import WPILibBrain, { simMap } from "@/systems/simulation/wpilib_brain/WPILibBrain" +import { CANOutputGroup } from "@/systems/simulation/wpilib_brain/SimOutput" import World from "@/systems/World" import MirabufSceneObject from "@/mirabuf/MirabufSceneObject" import Driver from "@/systems/simulation/driver/Driver" @@ -42,7 +43,7 @@ const RCConfigCANGroupModal: React.FC = ({ modalId }) => { acceptName="Done" onAccept={() => { // no eslint complain - brain.addSimOutputGroup(new CANGroup(name, checkedPorts, checkedDrivers)) + brain.addSimOutputGroup(new CANOutputGroup(name, checkedPorts, checkedDrivers)) console.log(name, checkedPorts, checkedDrivers) const replacer = (_: unknown, value: unknown) => { if (value instanceof Map) { diff --git a/fission/src/ui/modals/configuring/rio-config/RCConfigEncoderModal.tsx b/fission/src/ui/modals/configuring/rio-config/RCConfigEncoderModal.tsx index 310aaa83d0..6febe7599c 100644 --- a/fission/src/ui/modals/configuring/rio-config/RCConfigEncoderModal.tsx +++ b/fission/src/ui/modals/configuring/rio-config/RCConfigEncoderModal.tsx @@ -6,19 +6,46 @@ import Label, { LabelSize } from "@/components/Label" import Input from "@/components/Input" import Dropdown from "@/components/Dropdown" import NumberInput from "@/components/NumberInput" +import Driver from "@/systems/simulation/driver/Driver" +import WPILibBrain, { simMap } from "@/systems/simulation/wpilib_brain/WPILibBrain" +import World from "@/systems/World" +import MirabufSceneObject from "@/mirabuf/MirabufSceneObject" +import Stimulus from "@/systems/simulation/stimulus/Stimulus" +import EncoderStimulus from "@/systems/simulation/stimulus/EncoderStimulus" const RCConfigEncoderModal: React.FC = ({ modalId }) => { const { openModal } = useModalControlContext() const [name, setName] = useState("") - const [selectedSignal, setSelectedSignal] = useState("") - const [selectedChannelA, setSelectedChannelA] = useState(0) - const [selectedChannelB, setSelectedChannelB] = useState(0) - const [conversionFactor, setConversionFactor] = useState(1) - const numPorts = 10 - const signals = ["Rev0 (uuid)", "Rev1 (uuid)", "Rev2 (uuid)", "Rev3 (uuid)"] + let stimuli: EncoderStimulus[] = [] + let simLayer + let brain: WPILibBrain + + const miraObjs = [...World.SceneRenderer.sceneObjects.entries()].filter(x => x[1] instanceof MirabufSceneObject) + if (miraObjs.length > 0) { + const mechanism = (miraObjs[0][1] as MirabufSceneObject).mechanism + simLayer = World.SimulationSystem.GetSimulationLayer(mechanism) + stimuli = simLayer?.stimuli.filter(s => s instanceof EncoderStimulus) ?? [] + brain = simLayer?.brain as WPILibBrain + } + + let devices: [string, unknown][] = [] + + const encoders = simMap.get("CANEncoder") + if (encoders) { + devices = [...encoders.entries()] + } - if (!selectedSignal) setSelectedSignal(signals[0]) + const stimMap: { [key: string]: Stimulus } = {} + + stimuli.forEach(stim => { + const label = `${stim.constructor.name} ${stim.info?.name && "(" + stim.info!.name + ")"}` + stimMap[label] = stim + }) + + const [selectedDevice, setSelectedDevice] = useState(devices[0] && devices[0][0]) + const [selectedStimulus, setSelectedStimulus] = useState(stimuli[0]) + const [conversionFactor, setConversionFactor] = useState(1) return ( = ({ modalId }) => { modalId={modalId} acceptName="Done" onAccept={() => { - // mostly doing this so eslint doesn't complain about unused variables - console.log(name, selectedSignal, selectedChannelA, selectedChannelB, conversionFactor) + console.log(name, selectedDevice, selectedStimulus) }} onCancel={() => { openModal("roborio") @@ -36,16 +62,15 @@ const RCConfigEncoderModal: React.FC = ({ modalId }) => { > - setSelectedSignal(s)} /> n.toString())} - onSelect={s => setSelectedChannelA(parseInt(s))} + label="Encoders" + options={devices.map(n => n[0])} + onSelect={s => setSelectedDevice(s)} /> n.toString())} - onSelect={s => setSelectedChannelB(parseInt(s))} + label="Stimuli" + options={Object.keys(stimMap)} + onSelect={s => setSelectedStimulus(stimMap[s])} /> = ({ modalId }) => { let brain: WPILibBrain const miraObjs = [...World.SceneRenderer.sceneObjects.entries()].filter(x => x[1] instanceof MirabufSceneObject) - console.log(`Number of mirabuf scene objects: ${miraObjs.length}`) if (miraObjs.length > 0) { const mechanism = (miraObjs[0][1] as MirabufSceneObject).mechanism simLayer = World.SimulationSystem.GetSimulationLayer(mechanism) @@ -48,7 +48,7 @@ const RCConfigPWMGroupModal: React.FC = ({ modalId }) => { acceptName="Done" onAccept={() => { // no eslint complain - brain.addSimOutputGroup(new PWMGroup(name, checkedPorts, checkedDrivers)) + brain.addSimOutputGroup(new PWMOutputGroup(name, checkedPorts, checkedDrivers)) console.log(name, checkedPorts, checkedDrivers) }} onCancel={() => { diff --git a/fission/src/ui/panels/DebugPanel.tsx b/fission/src/ui/panels/DebugPanel.tsx index c8494cb87e..9b2187a8b1 100644 --- a/fission/src/ui/panels/DebugPanel.tsx +++ b/fission/src/ui/panels/DebugPanel.tsx @@ -16,6 +16,7 @@ import Jolt from "@barclah/jolt-physics" import Label from "../components/Label" import { colorNameToVar } from "../ThemeContext" import { FaScrewdriverWrench } from "react-icons/fa6" +import { useModalControlContext } from "../ModalContext" const LabelStyled = styled(Label)({ fontWeight: 700, @@ -50,6 +51,7 @@ async function TestGodMode() { const DebugPanel: React.FC = ({ panelId }) => { const { openPanel } = usePanelControlContext() + const { openModal } = useModalControlContext() return ( = ({ panelId }) => { } }} /> - + ) +} + const AssemblyCard: React.FC = ({ mira, update }) => { + const { openPanel } = usePanelControlContext() + const { closeModal } = useModalControlContext() + + const brain = useMemo(() => (mira.brain as SynthesisBrain)?.brainIndex, [mira]) + return (

- -
) } const ManageAssembliesModal: React.FC = ({ modalId }) => { - // update tooltip based on type of drivetrain, receive message from Synthesis - // const { showTooltip } = useTooltipControlContext() - const [_, update] = useReducer(x => !x, false) const assemblies = [...World.SceneRenderer.sceneObjects.entries()] @@ -43,23 +73,14 @@ const ManageAssembliesModal: React.FC = ({ modalId }) => { .map(x => x[1] as MirabufSceneObject) return ( - } - modalId={modalId} - onAccept={() => { - // showTooltip("controls", [ - // { control: "WASD", description: "Drive" }, - // { control: "E", description: "Intake" }, - // { control: "Q", description: "Dispense" }, - // ]); - }} - > + } modalId={modalId} acceptEnabled={false} cancelName="Back">
- {assemblies.map(x => AssemblyCard({ mira: x, update: update }))} + {assemblies.map(x => ( + + ))}
) diff --git a/fission/src/ui/panels/DebugPanel.tsx b/fission/src/ui/panels/DebugPanel.tsx index c8494cb87e..9b2187a8b1 100644 --- a/fission/src/ui/panels/DebugPanel.tsx +++ b/fission/src/ui/panels/DebugPanel.tsx @@ -16,6 +16,7 @@ import Jolt from "@barclah/jolt-physics" import Label from "../components/Label" import { colorNameToVar } from "../ThemeContext" import { FaScrewdriverWrench } from "react-icons/fa6" +import { useModalControlContext } from "../ModalContext" const LabelStyled = styled(Label)({ fontWeight: 700, @@ -50,6 +51,7 @@ async function TestGodMode() { const DebugPanel: React.FC = ({ panelId }) => { const { openPanel } = usePanelControlContext() + const { openModal } = useModalControlContext() return ( = ({ panelId }) => { } }} /> -