Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Configuring Mirabuf Brains #1033

Merged
merged 8 commits into from
Aug 9, 2024
Merged
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
7 changes: 7 additions & 0 deletions fission/src/Synthesis.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ import { ProgressHandle } from "./ui/components/ProgressNotificationData.ts"
import ConfigureRobotModal from "./ui/modals/configuring/ConfigureRobotModal.tsx"
import ResetAllInputsModal from "./ui/modals/configuring/ResetAllInputsModal.tsx"
import ZoneConfigPanel from "./ui/panels/configuring/scoring/ZoneConfigPanel.tsx"
import ConfigureRobotBrainPanel from "./ui/panels/configuring/ConfigureRobotBrainPanel.tsx"
import SceneOverlay from "./ui/components/SceneOverlay.tsx"

import WPILibWSWorker from "@/systems/simulation/wpilib_brain/WPILibWSWorker.ts?worker"
Expand Down Expand Up @@ -266,6 +267,12 @@ const initialPanels: ReactElement[] = [
<ZoneConfigPanel key="zone-config" panelId="zone-config" openLocation="right" sidePadding={8} />,
<ImportMirabufPanel key="import-mirabuf" panelId="import-mirabuf" />,
<PokerPanel key="poker" panelId="poker" />,
<ConfigureRobotBrainPanel
key="config-robot-brain"
panelId="config-robot-brain"
openLocation="right"
sidePadding={8}
/>,
<WSViewPanel key="ws-view" panelId="ws-view" />,
]

Expand Down
4 changes: 4 additions & 0 deletions fission/src/mirabuf/MirabufSceneObject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ class MirabufSceneObject extends SceneObject {
return this._mechanism
}

get brain() {
return this._brain
}

get assemblyName() {
return this._assemblyName
}
Expand Down
4 changes: 2 additions & 2 deletions fission/src/systems/simulation/Brain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import Mechanism from "../physics/Mechanism"
abstract class Brain {
protected _mechanism: Mechanism

constructor(mechansim: Mechanism) {
this._mechanism = mechansim
constructor(mechanism: Mechanism) {
this._mechanism = mechanism
}

public abstract Update(deltaT: number): void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ class ArcadeDriveBehavior extends Behavior {
private _driveSpeed = 30
private _turnSpeed = 30

public get wheels(): WheelDriver[] {
return this.leftWheels.concat(this.rightWheels)
}

constructor(
leftWheels: WheelDriver[],
rightWheels: WheelDriver[],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ class GenericArmBehavior extends Behavior {

private _rotationalSpeed = 6

public get hingeDriver(): HingeDriver {
return this._hingeDriver
}

constructor(
hingeDriver: HingeDriver,
hingeStimulus: HingeStimulus,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ class GenericElevatorBehavior extends Behavior {

private _linearSpeed = 2.5

public get sliderDriver(): SliderDriver {
return this._sliderDriver
}

constructor(
sliderDriver: SliderDriver,
sliderStimulus: SliderStimulus,
Expand Down
4 changes: 4 additions & 0 deletions fission/src/systems/simulation/driver/HingeDriver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ class HingeDriver extends Driver {
private _targetVelocity: number = 0.0
private _targetAngle: number

public get constraint(): Jolt.HingeConstraint {
return this._constraint
}

public get targetVelocity(): number {
return this._targetVelocity
}
Expand Down
4 changes: 4 additions & 0 deletions fission/src/systems/simulation/driver/SliderDriver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ class SliderDriver extends Driver {
private _targetVelocity: number = 0.0
private _targetPosition: number = 0.0

public get constraint(): Jolt.SliderConstraint {
return this._constraint
}

public get targetVelocity(): number {
return this._targetVelocity
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ class SynthesisBrain extends Brain {
private _assemblyName: string
private _assemblyIndex: number = 0

public get behaviors(): Behavior[] {
return this._behaviors
}

// Tracks the number of each specific mira file spawned
public static numberRobotsSpawned: { [key: string]: number } = {}

Expand Down
5 changes: 5 additions & 0 deletions fission/src/ui/components/MainHUD.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,11 @@ const MainHUD: React.FC = () => {
}}
/>
<MainHUDButton value={"Configure"} icon={<FaGear />} onClick={() => openModal("config-robot")} />
<MainHUDButton
value={"Configure Brain"}
icon={<FaGear />}
onClick={() => openPanel("config-robot-brain")}
/>
</div>
{userInfo ? (
<MainHUDButton
Expand Down
247 changes: 247 additions & 0 deletions fission/src/ui/panels/configuring/ConfigureRobotBrainPanel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
import { MiraType } from "@/mirabuf/MirabufLoader"
import MirabufSceneObject, { RigidNodeAssociate } from "@/mirabuf/MirabufSceneObject"
import World from "@/systems/World"
import Label, { LabelSize } from "@/ui/components/Label"
import Button from "@/ui/components/Button"
import Panel, { PanelPropsImpl } from "@/ui/components/Panel"
import { useMemo, useState } from "react"
import { FaGear } from "react-icons/fa6"
import { ToggleButton, ToggleButtonGroup } from "@/ui/components/ToggleButtonGroup"
import { Divider, styled } from "@mui/material"
import ArcadeDriveBehavior from "@/systems/simulation/behavior/ArcadeDriveBehavior"
import GenericArmBehavior from "@/systems/simulation/behavior/GenericArmBehavior"
import GenericElevatorBehavior from "@/systems/simulation/behavior/GenericElevatorBehavior"
import Stack, { StackDirection } from "@/ui/components/Stack"
import { JSX } from "react/jsx-runtime"

// eslint-disable-next-line react-refresh/only-export-components
export enum ConfigureRobotBrainTypes {
SYNTHESIS = 0,
WIPLIB = 1,
}

const LabelStyled = styled(Label)({
fontWeight: 700,
margin: "0pt",
})

const DividerStyled = styled(Divider)({
borderColor: "white",
})

/**
* Retrieves the joints of a robot and generates JSX elements for each joint.
* @param robot The MirabufSceneObject representing the robot.
* @returns An array of JSX elements representing the joints of the robot.
*/
function GetJoints(robot: MirabufSceneObject): JSX.Element[] {
const output: JSX.Element[] = []
let elementKey = 0

/* Iterate through each behavior of the robot */
robot.brain?.behaviors.forEach(behavior => {
/* Adds the joints that the wheels are associated with */
if (behavior instanceof ArcadeDriveBehavior) {
behavior.wheels.forEach(wheel => {
const assoc = World.PhysicsSystem.GetBodyAssociation(
wheel.constraint.GetVehicleBody().GetID()
) as RigidNodeAssociate

if (!assoc || assoc.sceneObject !== robot) {
return
}

output.push(
<Stack
key={`Behavior ${elementKey}`}
direction={StackDirection.Horizontal}
className="items-center"
>
<LabelStyled
key={`wheel-node-notation ${elementKey}`}
size={LabelSize.Small}
className="text-center mt-[4pt] mb-[2pt] mx-[5%]"
>
Wheel Node {elementKey}
</LabelStyled>
<LabelStyled
key={`wheel-node-number ${elementKey}`}
size={LabelSize.Small}
className="text-center mt-[4pt] mb-[2pt] mx-[5%]"
>
{assoc.rigidNodeId}
</LabelStyled>
</Stack>
)
elementKey++
})
output.push(<DividerStyled key={`divider-${elementKey}`} />)
} else if (behavior instanceof GenericArmBehavior) {

/* Adds the joints that the arm is associated with */
// Get the rigid node associates for the two bodies
const assoc1 = World.PhysicsSystem.GetBodyAssociation(
behavior.hingeDriver.constraint.GetBody1().GetID()
) as RigidNodeAssociate
const assoc2 = World.PhysicsSystem.GetBodyAssociation(
behavior.hingeDriver.constraint.GetBody2().GetID()
) as RigidNodeAssociate

if (!assoc1 || assoc1.sceneObject !== robot || !assoc2 || assoc2.sceneObject !== robot) {
return
}

output.push(
<Stack key={`Behavior ${elementKey}`} direction={StackDirection.Horizontal} className="items-center">
<LabelStyled
key={`arm-nodes-notation ${elementKey}`}
size={LabelSize.Small}
className="text-center mt-[4pt] mb-[2pt] mx-[5%]"
>
Arm Nodes
</LabelStyled>
<LabelStyled
key={`arm-nodes ${elementKey}`}
size={LabelSize.Small}
className="text-center mt-[4pt] mb-[2pt] mx-[5%]"
>
{assoc1.rigidNodeId + " " + assoc2.rigidNodeId}
</LabelStyled>
</Stack>
)
elementKey++
} else if (behavior instanceof GenericElevatorBehavior) {

/* Adds the joints that the elevator is associated with */
// Get the rigid node associates for the two bodies
const assoc1 = World.PhysicsSystem.GetBodyAssociation(
behavior.sliderDriver.constraint.GetBody1().GetID()
) as RigidNodeAssociate
const assoc2 = World.PhysicsSystem.GetBodyAssociation(
behavior.sliderDriver.constraint.GetBody2().GetID()
) as RigidNodeAssociate

if (!assoc1 || assoc1.sceneObject !== robot || !assoc2 || assoc2.sceneObject !== robot) {
return
}

output.push(
<Stack key={`Behavior ${elementKey}`} direction={StackDirection.Horizontal} className="items-center">
<LabelStyled
key={`elevator-nodes-notation ${elementKey}`}
size={LabelSize.Small}
className="text-center mt-[4pt] mb-[2pt] mx-[5%]"
>
Elevator Nodes
</LabelStyled>
<LabelStyled
key={`elevator-nodes ${elementKey}`}
size={LabelSize.Small}
className="text-center mt-[4pt] mb-[2pt] mx-[5%]"
>
{assoc1.rigidNodeId + " " + assoc2.rigidNodeId}
</LabelStyled>
</Stack>
)
elementKey++
}
})

return output
}

const ConfigureRobotBrainPanel: React.FC<PanelPropsImpl> = ({ panelId, openLocation, sidePadding }) => {
const [selectedRobot, setSelectedRobot] = useState<MirabufSceneObject | undefined>(undefined)
const [viewType, setViewType] = useState<ConfigureRobotBrainTypes>(ConfigureRobotBrainTypes.SYNTHESIS)
const robots = useMemo(() => {
const assemblies = [...World.SceneRenderer.sceneObjects.values()].filter(x => {
if (x instanceof MirabufSceneObject) {
return x.miraType === MiraType.ROBOT
}
return false
}) as MirabufSceneObject[]
return assemblies
}, [])

return (
<Panel
name="Configure Robot Brain"
icon={<FaGear />}
panelId={panelId}
openLocation={openLocation}
sidePadding={sidePadding}
onAccept={() => {}}
onCancel={() => {}}
>
{selectedRobot?.ejectorPreferences == undefined ? (
<>
<Label>Select a robot</Label>
{/** Scroll view for selecting a robot to configure */}
<div className="flex overflow-y-auto flex-col gap-2 min-w-[20vw] max-h-[40vh] bg-background-secondary rounded-md p-2">
{robots.map(mirabufSceneObject => {
return (
<Button
value={mirabufSceneObject.assemblyName}
onClick={() => {
setSelectedRobot(mirabufSceneObject)
}}
key={mirabufSceneObject.id}
></Button>
)
})}
</div>
{/* TODO: remove the accept button on this version */}
</>
) : (
<>
<div className="flex flex-col gap-2 bg-background-secondary rounded-md p-2">
<ToggleButtonGroup
value={viewType}
exclusive
onChange={(_, v) => v != null && setViewType(v)}
sx={{
alignSelf: "center",
}}
>
<ToggleButton value={ConfigureRobotBrainTypes.SYNTHESIS}>SynthesisBrain</ToggleButton>
<ToggleButton value={ConfigureRobotBrainTypes.WIPLIB}>WIPLIBBrain</ToggleButton>
</ToggleButtonGroup>
{viewType === ConfigureRobotBrainTypes.SYNTHESIS ? (
<>
<LabelStyled size={LabelSize.Medium} className="text-center mt-[4pt] mb-[2pt] mx-[5%]">
Behaviors
</LabelStyled>
<DividerStyled />
{GetJoints(selectedRobot)}
</>
) : (
<>
<LabelStyled size={LabelSize.Medium} className="text-center mt-[4pt] mb-[2pt] mx-[5%]">
Example WIPLIB Brain
</LabelStyled>
<DividerStyled />

<LabelStyled size={LabelSize.Medium} className="text-center mt-[4pt] mb-[2pt] mx-[5%]">
Example 2
</LabelStyled>
<DividerStyled />

<LabelStyled size={LabelSize.Medium} className="text-center mt-[4pt] mb-[2pt] mx-[5%]">
Example 3
</LabelStyled>
<DividerStyled />

<LabelStyled size={LabelSize.Medium} className="text-center mt-[4pt] mb-[2pt] mx-[5%]">
Example 4
</LabelStyled>
<DividerStyled />
</>
)}
</div>
</>
)}
</Panel>
)
}

export default ConfigureRobotBrainPanel
Loading