Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
8e16e66
Manager implementation
Tortuga-AM Jan 25, 2026
07a5020
Minor fixes and adding visualize states workflow (removed forcing con…
Tortuga-AM Jan 25, 2026
51f5f28
fixes
Tortuga-AM Jan 25, 2026
dd9e392
Better looking vis
Tortuga-AM Jan 25, 2026
0c312ba
Apply Prettier format
invalid-email-address Jan 25, 2026
8a68162
bug fix
Tortuga-AM Jan 25, 2026
dca571a
🥀
Tortuga-AM Jan 25, 2026
f3bf417
wrong file path
Tortuga-AM Jan 25, 2026
efebbae
Better vis 2.0
Tortuga-AM Jan 25, 2026
79d87e4
better vis 3.0
Tortuga-AM Jan 25, 2026
18fcf95
fix import
Tortuga-AM Jan 25, 2026
11c52e2
oop
Tortuga-AM Jan 25, 2026
89e840a
arrows be important
Tortuga-AM Jan 25, 2026
4805945
More beutiful
Tortuga-AM Jan 25, 2026
18e4f6b
how did it get more cooked
Tortuga-AM Jan 25, 2026
9d61d71
substates please work
Tortuga-AM Jan 25, 2026
5532180
Trust 50/50 if it works this time
Tortuga-AM Jan 25, 2026
5b296ae
Apply Prettier format
invalid-email-address Jan 25, 2026
4293505
Better?
Tortuga-AM Jan 25, 2026
00cd566
Merge branch 'Manager' of https://github.com/FRC-7525/7525-Rebuilt in…
Tortuga-AM Jan 25, 2026
f1d7dbd
Do it be working now?
Tortuga-AM Jan 25, 2026
356351b
pleeeeeeeeeeeeaaaaaaaaasssssssseee
Tortuga-AM Jan 25, 2026
350cd84
fixes hopefully
Tortuga-AM Jan 25, 2026
6027913
did not work
Tortuga-AM Jan 25, 2026
0d46af5
can't get worse right?
Tortuga-AM Jan 25, 2026
5c8eaa0
maybe it can :skull:
Tortuga-AM Jan 25, 2026
7f5700b
trust
Tortuga-AM Jan 25, 2026
25b9bbd
don't trust
Tortuga-AM Jan 25, 2026
c6f2981
must be ragebait
Tortuga-AM Jan 25, 2026
d0b34ff
broooo
Tortuga-AM Jan 25, 2026
34070a5
Dark Mode and Spacing
Tortuga-AM Jan 25, 2026
3646fa7
:wilting_rose:
Tortuga-AM Jan 25, 2026
7f9999b
boxes
Tortuga-AM Jan 25, 2026
df295e7
boxes?
Tortuga-AM Jan 25, 2026
6d2fb05
best it gonna be back to actuall important things
Tortuga-AM Jan 26, 2026
077f9ad
Working in sim
Tortuga-AM Jan 27, 2026
cddb9af
Apply Prettier format
invalid-email-address Jan 27, 2026
1923a39
Drive fully working in sim
Tortuga-AM Jan 27, 2026
e725974
Merge branch 'Manager' of https://github.com/FRC-7525/7525-Rebuilt in…
Tortuga-AM Jan 27, 2026
b0345e1
Apply Prettier format
invalid-email-address Jan 27, 2026
34ee98a
Hopefully working decently?
Tortuga-AM Feb 1, 2026
943cfe8
Apply Prettier format
invalid-email-address Feb 1, 2026
784bd04
Constants fixes
Tortuga-AM Feb 1, 2026
2da2abf
Apply Prettier format
invalid-email-address Feb 1, 2026
627f847
12 is annoying
Tortuga-AM Feb 1, 2026
56acaac
Apply Prettier format
invalid-email-address Feb 1, 2026
58a86f8
Major annoyance fixed
Tortuga-AM Feb 1, 2026
1de5672
Apply Prettier format
invalid-email-address Feb 1, 2026
28e044a
fixing thingies
Tortuga-AM Feb 1, 2026
d23624f
🥀.java isn't ok i guess
Tortuga-AM Feb 2, 2026
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
184 changes: 184 additions & 0 deletions .github/scripts/visualizeStates.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
import sys
import re
from pathlib import Path
from graphviz import Digraph

# ---------- Parsing ManagerStates ----------
def get_manager_states(manager_states_path):
text = Path(manager_states_path).read_text(encoding="utf8")

pattern = re.compile(
r"""
(\w+)\s*
\(\s*
"(.*?)"\s*,\s*
([^,]+)\s*,\s*
([^,]+)\s*,\s*
([^,]+)\s*,\s*
([^)]+)
\)
""",
re.VERBOSE | re.DOTALL,
)

states = {}

for m in pattern.finditer(text):
name = m.group(1)

def clean(x: str) -> str:
x = x.strip()
x = re.sub(r".*?\.", "", x)
x = re.sub(r"\(.*\)", "", x)
return x

states[name] = {
"Intake": clean(m.group(3)),
"Hopper": clean(m.group(4)),
"Shooter": clean(m.group(5)),
"Climber": clean(m.group(6)),
"connectionsTo": [],
}

return states

# ---------- Parsing Triggers ----------
def get_triggers(manager_path):
file = Path(manager_path).read_text(encoding="utf8")
return re.findall(r"addTrigger\([\s\S]*?\);", file)

def parse_triggers(triggers):
parsed = []

for t in triggers:
m = re.search(
r"""
addTrigger\(
\s*(?:\w+\.)?(\w+)\s*, # from
\s*(?:\w+\.)?(\w+)\s*, # to
\s*(.*?) # condition (FULL)
\)\s*;
""",
t,
re.VERBOSE | re.DOTALL,
)
if not m:
continue

condition = m.group(3).strip()

# Remove lambda wrapper
condition = re.sub(r"^\(\)\s*->\s*", "", condition)

# Remove controller prefixes
condition = re.sub(r"(?:DRIVER|OPERATOR)_CONTROLLER::get", "", condition)
condition = re.sub(r".*?::", "", condition)

parsed.append({
"from": m.group(1),
"to": m.group(2),
"condition": condition,
})

return parsed

def attach_triggers(state_map, triggers):
for t in triggers:
if t["from"] in state_map:
state_map[t["from"]]["connectionsTo"].append(t)

# ---------- Graphviz helpers ----------
def node_id(name: str) -> str:
return re.sub(r"\W+", "_", name)

EDGE_COLORS = [
"#f6e05e", "#68d391", "#63b3ed", "#fc8181",
"#90cdf4", "#faf089", "#fbb6ce", "#9f7aea"
]

# ---------- Visualization ----------
def generate_graph(state_map):
dot = Digraph("StateMachine", format="png", engine="dot")

dot.attr(
rankdir="TB",
bgcolor="#1e1e2f",
fontname="Helvetica",
nodesep="0.6",
ranksep="0.9",
)

dot.attr(
"node",
shape="box",
style="rounded,filled",
fillcolor="#2d2d3c",
color="#68d391",
fontcolor="white",
fontname="Helvetica-Bold",
fontsize="11",
penwidth="1.4",
)

dot.attr(
"edge",
fontname="Helvetica",
fontsize="9",
arrowsize="0.8",
)

# Nodes
for state, info in state_map.items():
lines = [
f"{state}",
"────────────",
f"Intake → {info['Intake']}",
f"Hopper → {info['Hopper']}",
f"Shooter → {info['Shooter']}",
f"Climber → {info['Climber']}",
]
label = "\n".join(lines)

if state == "IDLE":
dot.node(
node_id(state),
label=label,
fillcolor="#3e2c1c",
color="#f6ad55",
penwidth="2.5",
)
else:
dot.node(node_id(state), label=label)

# Edges
color_index = 0
for state, info in state_map.items():
if not info["connectionsTo"]:
continue

color = EDGE_COLORS[color_index % len(EDGE_COLORS)]
color_index += 1

for c in info["connectionsTo"]:
dot.edge(
node_id(state),
node_id(c["to"]),
label=c["condition"],
color=color,
fontcolor=color,
penwidth="1.8",
)

dot.render("state_machine", cleanup=True)
print("Rendered state_machine.png")

# ---------- Main ----------
def main(managerStatesPath, managerPath):
state_map = get_manager_states(managerStatesPath)
triggers = parse_triggers(get_triggers(managerPath))
attach_triggers(state_map, triggers)
generate_graph(state_map)
print("Success!")

if __name__ == "__main__":
main(sys.argv[1], sys.argv[2])
61 changes: 61 additions & 0 deletions .github/workflows/visualizeStates.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: Visualize States

on:
pull_request:
types:
- reopened
- opened
- synchronize

jobs:
generate-graph:
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v3

- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y graphviz

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.x'

- name: Install dependencies
run: |
pip install graphviz

- name: Run graph generation
id: run-script
run: |
python3 .github/scripts/visualizeStates.py ./src/main/java/frc/robot/Subsystems/Manager/ManagerStates.java ./src/main/java/frc/robot/Subsystems/Manager/Manager.java
echo "exit_code=$?" >> $GITHUB_OUTPUT
continue-on-error: true

- name: Upload graph as artifact
uses: actions/upload-artifact@v4
with:
name: state-machine-graph
path: state_machine.png

- name: Comment on PR
uses: actions/github-script@v6
with:
script: |
const prNumber = context.payload.pull_request.number;
const exitCode = Number(process.env.EXIT_CODE);
const commentBody = exitCode === 0
? "✅ State machine graph generated and uploaded."
: "⚠️ Something went wrong while generating the state machine graph.";

github.rest.issues.createComment({
issue_number: prNumber,
owner: context.repo.owner,
repo: context.repo.repo,
body: commentBody
})
env:
EXIT_CODE: ${{ steps.run-script.outputs.exit_code }}
1 change: 1 addition & 0 deletions Other/AscopeFiles/PutAscopeModelsAndConfigHere.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
hmm
1 change: 1 addition & 0 deletions Other/Dashboards/PutDriverDashBoardHere.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
hmmmmmm
143 changes: 143 additions & 0 deletions Other/Sim/GoatedSimConfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
{
"Docking": {
"Data": [
"DockNode ID=0x00000002 Pos=-2,2 Size=1926,1098 Split=X",
"DockNode ID=0x00000001 Parent=0x00000002 SizeRef=1153,1095 Split=Y",
"DockNode ID=0x0000000F Parent=0x00000001 SizeRef=991,210 Split=X",
"DockNode ID=0x0000000D Parent=0x0000000F SizeRef=519,140 Split=X",
"DockNode ID=0x0000000B Parent=0x0000000D SizeRef=257,140 Selected=0x39AD1970",
"DockNode ID=0x0000000C Parent=0x0000000D SizeRef=280,140 Selected=0xD58031C5",
"DockNode ID=0x0000000E Parent=0x0000000F SizeRef=632,140 Selected=0x513EDE86",
"DockNode ID=0x00000010 Parent=0x00000001 SizeRef=991,883 Split=Y Selected=0xB5CBE9F0",
"DockNode ID=0x00000012 Parent=0x00000010 SizeRef=1153,233 Split=Y Selected=0xF9AD29AD",
"DockNode ID=0x00000014 Parent=0x00000012 SizeRef=1155,199 Selected=0x5446CBB7",
"DockNode ID=0x00000015 Parent=0x00000012 SizeRef=1155,240 Selected=0xF9AD29AD",
"DockNode ID=0x00000013 Parent=0x00000010 SizeRef=1153,650 Selected=0xB5CBE9F0",
"DockNode ID=0x00000011 Parent=0x00000002 SizeRef=767,1095 Split=Y",
"DockNode ID=0x00000007 Parent=0x00000011 SizeRef=313,611 Split=X Selected=0x3E3C37F1",
"DockNode ID=0x00000003 Parent=0x00000007 SizeRef=309,746 Selected=0x3E3C37F1",
"DockNode ID=0x00000004 Parent=0x00000007 SizeRef=458,746 Selected=0x2D9B9756",
"DockNode ID=0x00000008 Parent=0x00000011 SizeRef=313,287 Split=Y Selected=0x6AE6D891",
"DockNode ID=0x00000005 Parent=0x00000008 SizeRef=313,32 Split=X Selected=0x6AE6D891",
"DockNode ID=0x00000009 Parent=0x00000005 SizeRef=295,176 Selected=0x6AE6D891",
"DockNode ID=0x0000000A Parent=0x00000005 SizeRef=472,176 Selected=0xC8493FD8",
"DockNode ID=0x00000006 Parent=0x00000008 SizeRef=313,316 Selected=0x138219D4"
]
},
"MainWindow": {
"GLOBAL": {
"font": "Roboto Bold",
"fps": "120",
"height": "1051",
"maximized": "1",
"style": "3",
"userScale": "2",
"width": "1920",
"xpos": "0",
"ypos": "29"
}
},
"Window": {
"###/AdvantageKit/RealOutputs/Alerts": {
"Collapsed": "0",
"Pos": "137,171",
"Size": "300,148"
},
"###/FMSInfo": {
"Collapsed": "0",
"Pos": "60,60",
"Size": "168,206"
},
"###/SmartDashboard/Auto Chooser": {
"Collapsed": "0",
"DockId": "0x0000000E,0",
"Pos": "521,20",
"Size": "633,211"
},
"###/SmartDashboard/Field": {
"Collapsed": "0",
"DockId": "0x00000013,0",
"Pos": "-2,450",
"Size": "1155,650"
},
"###/SmartDashboard/VisionSystemSim-Vision/Sim Field": {
"Collapsed": "0",
"DockId": "0x00000015,0",
"Pos": "-1,233",
"Size": "1155,441"
},
"###/SmartDashboard/VisionSystemSim-main/Sim Field": {
"Collapsed": "0",
"DockId": "0x00000014,0",
"Pos": "-2,215",
"Size": "1155,233"
},
"###FMS": {
"Collapsed": "0",
"DockId": "0x0000000A,0",
"Pos": "1452,750",
"Size": "472,32"
},
"###Joysticks": {
"Collapsed": "0",
"DockId": "0x00000006,0",
"Pos": "1155,784",
"Size": "769,316"
},
"###Keyboard 0 Settings": {
"Collapsed": "0",
"DockId": "0x00000003,0",
"Pos": "1156,20",
"Size": "309,746"
},
"###NetworkTables": {
"Collapsed": "0",
"DockId": "0x00000004,0",
"Pos": "1155,2",
"Size": "769,746"
},
"###NetworkTables Info": {
"Collapsed": "0",
"Pos": "939,136",
"Size": "681,492"
},
"###Other Devices": {
"Collapsed": "0",
"Pos": "558,386",
"Size": "312,1173"
},
"###Plot <0>": {
"Collapsed": "0",
"Pos": "65,61",
"Size": "700,400"
},
"###PowerDistributions": {
"Collapsed": "0",
"Pos": "245,155",
"Size": "200,456"
},
"###System Joysticks": {
"Collapsed": "0",
"DockId": "0x00000009,0",
"Pos": "1155,750",
"Size": "295,32"
},
"###Timing": {
"Collapsed": "0",
"DockId": "0x0000000C,0",
"Pos": "552,2",
"Size": "601,211"
},
"Debug##Default": {
"Collapsed": "0",
"Pos": "60,60",
"Size": "400,400"
},
"Robot State": {
"Collapsed": "0",
"DockId": "0x0000000B,0",
"Pos": "-2,2",
"Size": "552,211"
}
}
}
Loading