diff --git a/docs-source/_static/venue-calc.css b/docs-source/_static/venue-calc.css new file mode 100644 index 0000000..84a927d --- /dev/null +++ b/docs-source/_static/venue-calc.css @@ -0,0 +1,175 @@ +/* Mirrors camera-calc.css so the two calculators read as one control. Kept as + a separate selector tree rather than shared classes because the markup and + field sets differ; only the visual language is common. */ +.venue-calc { border: 1px solid var(--color-background-border, #ccc); border-radius: 6px; padding: 1em; margin: 1em 0; } +/* Whole-form starting points, above the first section. */ +.venue-calc-scenarios { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 0.5em; + margin-bottom: 0.5em; + font-size: 0.9em; + font-weight: bold; +} +.venue-calc-scenarios + .venue-calc-note { margin: 0 0 1em; } +.venue-calc-group { border: 1px solid var(--color-background-border, #ddd); border-radius: 6px; margin: 0 0 1em 0; padding: 0.75em 1em 1em; } +.venue-calc-group legend { font-weight: bold; padding: 0 0.4em; } +.venue-calc-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 0.75em; } +.venue-calc-grid label { display: flex; flex-direction: column; font-size: 0.9em; gap: 0.25em; } +.venue-calc-grid label > span:first-child { display: flex; align-items: center; min-height: 1.4em; gap: 0.3em; } +.venue-calc-grid input, .venue-calc-grid select { padding: 0.3em; } +.venue-calc-grid input:disabled { + background: var(--color-background-secondary, #e9e9e9); + color: var(--color-foreground-muted, #767676); + border-color: var(--color-background-border, #ccc); + cursor: not-allowed; + opacity: 0.85; +} +.venue-calc-matrix { width: 100%; margin: 0.75em 0 0; font-size: 0.9em; border-collapse: collapse; } +.venue-calc-matrix th, .venue-calc-matrix td { + padding: 0.5em 0.7em; + text-align: left; + border: 1px solid var(--color-background-border, #ddd); +} +.venue-calc-matrix thead th { background: var(--color-background-secondary, #f3f3f3); } +.venue-calc-matrix input { width: 100%; max-width: 7em; padding: 0.3em; } +.venue-calc-matrix input:disabled { + background: var(--color-background-secondary, #e9e9e9); + color: var(--color-foreground-muted, #767676); + border-color: var(--color-background-border, #ccc); + cursor: not-allowed; + opacity: 0.85; +} +/* Row labels in the first column read as data labels, not headings — kept as +
${text}
`; +} + +// rows: arrays of cell strings, or { cells, cls } to style the whole row. +// A null row renders nothing, so callers can inline their conditionals. +function vcTable(headers, rows) { + vcReport.push({ + type: 'table', + headers, + rows: rows.filter(Boolean).map(r => (Array.isArray(r) ? r : r.cells)), + }); + const head = headers.map(h => `Inputs changed. Press Calculate to update the results.
'; + vcSetExportsEnabled(false); +} + +const vcRoot = document.querySelector('.venue-calc'); +if (vcRoot) { + ['input', 'change'].forEach(function (evt) { + vcRoot.addEventListener(evt, vcInvalidate); + }); +} + +document.getElementById('vc-calc').addEventListener('click', vcCalculate); + +// --- Scenarios ----------------------------------------------------------- + +// Whole-form starting points. Everything not listed here is whatever the +// section defaults already are, since applying a scenario resets the form +// first — except mains voltage and breaker rating, which follow the country +// the venue is in rather than the size of the event. +const VC_SCENARIOS = { + international: { teamsA: 8, membersA: 12, teamsB: 12, membersB: 7 }, + 'regional-a': { teamsA: 4, membersA: 12, teamsB: 0, membersB: 7 }, + 'regional-b': { teamsA: 0, membersA: 12, teamsB: 4, membersB: 7 }, +}; + +const VC_SCENARIO_BASE = { organizerTables: 2, bufferM: 1.5, pitsDropsPerTeam: 1 }; + +function vcCheckRadio(name, value) { + document.querySelectorAll(`input[name="${name}"]`).forEach(function (radio) { + radio.checked = radio.value === value; + }); +} + +function vcApplyScenario(key) { + const scenario = VC_SCENARIOS[key]; + if (!scenario) return; + + Object.keys(VC_ADVANCED_GROUPS).forEach(vcRestoreAdvanced); + vcRestoreFieldEquipment(); + vcCheckRadio('vc-team-mode', 'average'); + vcCheckRadio('vc-field-mode', 'derive'); + + document.getElementById('vc-teams-a').value = scenario.teamsA; + document.getElementById('vc-members-a').value = scenario.membersA; + document.getElementById('vc-teams-b').value = scenario.teamsB; + document.getElementById('vc-members-b').value = scenario.membersB; + document.getElementById('vc-organizer-tables').value = VC_SCENARIO_BASE.organizerTables; + document.getElementById('vc-buffer').value = VC_SCENARIO_BASE.bufferM; + document.getElementById('vc-pits-drops').value = VC_SCENARIO_BASE.pitsDropsPerTeam; + + vcSyncTeamMode(); + vcSyncFieldMode(); + vcCalculate(); +} + +document.querySelectorAll('[data-vc-scenario]').forEach(function (button) { + button.addEventListener('click', function () { + vcApplyScenario(button.getAttribute('data-vc-scenario')); + }); +}); + +// --- CSV download -------------------------------------------------------- + +// Cells are built for HTML, so strip markup and turn the handful of entities +// the report uses back into plain characters before they reach a spreadsheet. +const VC_ENTITIES = { + '×': 'x', '²': '2', '—': '-', '–': '-', + '→': '->', '⌈': '', '⌉': '', '&': '&', ' ': ' ', +}; + +function vcPlain(cell) { + let text = String(cell === null || cell === undefined ? '' : cell) + .replace(/<[^>]+>/g, ''); + Object.keys(VC_ENTITIES).forEach(function (ent) { + text = text.split(ent).join(VC_ENTITIES[ent]); + }); + return text.replace(/\s+/g, ' ').trim(); +} + +function vcCsvCell(value) { + const text = vcPlain(value); + return /[",\n]/.test(text) ? `"${text.replace(/"/g, '""')}"` : text; +} + +function vcReportToCsv() { + const lines = [ + ['SSL Venue Requirements Calculator'], + ['Generated', new Date().toISOString().slice(0, 10)], + ].map(r => r.map(vcCsvCell).join(',')); + + vcReport.forEach(function (entry) { + if (entry.type === 'head') { + lines.push(''); + lines.push(vcCsvCell(entry.text)); + return; + } + if (entry.type === 'note') { + lines.push(vcCsvCell(`Note: ${entry.text}`)); + return; + } + lines.push(entry.headers.map(vcCsvCell).join(',')); + entry.rows.forEach(row => lines.push(row.map(vcCsvCell).join(','))); + }); + return lines.join('\r\n'); +} + +function vcSummaryToMarkdown() { + const lines = [ + '# SSL Venue Requirements', + '', + `Generated ${new Date().toISOString().slice(0, 10)} by the SSL Venue Requirements Calculator.`, + '', + ]; + vcSummary.forEach(function (entry) { + lines.push(`- **${vcPlain(entry.label)}:** ${vcPlain(entry.value)}${entry.estimated ? ' (est.)' : ''}`); + }); + lines.push(''); + lines.push('Lines marked (est.) rest on assumptions this calculator makes rather than on a published league'); + lines.push('requirement. Everything else follows from figures the league documents or from what you entered.'); + lines.push(''); + lines.push('Planning figures for a venue conversation, not an electrical design. Have an electrician or the'); + lines.push("venue's own facilities team confirm circuit counts and layout."); + return lines.join('\n'); +} + +function vcSaveFile(text, filename, mime) { + const blob = new Blob([text], { type: mime }); + const url = URL.createObjectURL(blob); + const link = document.createElement('a'); + link.href = url; + link.download = filename; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + URL.revokeObjectURL(url); +} + +function vcStamp() { + return new Date().toISOString().slice(0, 10); +} + +document.getElementById('vc-download-md').addEventListener('click', function () { + if (vcSummary.length === 0) return; + vcSaveFile(vcSummaryToMarkdown(), `ssl-venue-summary-${vcStamp()}.md`, 'text/markdown;charset=utf-8;'); +}); + +document.getElementById('vc-copy').addEventListener('click', function () { + if (vcSummary.length === 0) return; + const button = this; + const restore = function (message) { + const original = button.textContent; + button.textContent = message; + setTimeout(function () { button.textContent = original; }, 1500); + }; + // The clipboard API needs a secure context, so a docs build opened over + // file:// will reject. Say so rather than failing silently. + if (!navigator.clipboard) { + restore('Copy unavailable'); + return; + } + navigator.clipboard.writeText(vcSummaryToMarkdown()) + .then(function () { restore('Copied'); }) + .catch(function () { restore('Copy failed'); }); +}); + +document.getElementById('vc-download').addEventListener('click', function () { + if (vcReport.length === 0) return; + // The BOM is what makes Excel read the file as UTF-8 rather than latin-1. + vcSaveFile('\uFEFF' + vcReportToCsv(), `ssl-venue-plan-${vcStamp()}.csv`, 'text/csv;charset=utf-8;'); +}); + +} diff --git a/docs-source/conf.py b/docs-source/conf.py index 5927370..af75b5a 100644 --- a/docs-source/conf.py +++ b/docs-source/conf.py @@ -38,8 +38,8 @@ html_theme = "furo" html_static_path = ["_static"] -html_css_files = ["site.css", "camera-calc.css"] -html_js_files = ["camera-calc.js"] +html_css_files = ["site.css", "camera-calc.css", "venue-calc.css"] +html_js_files = ["camera-calc.js", "venue-calc.js"] # Diagrams using `layout: elk` in their frontmatter need the ELK layout # plugin explicitly opted into — sphinxcontrib-mermaid doesn't load it by diff --git a/docs-source/events.md b/docs-source/events.md new file mode 100644 index 0000000..2f5a22e --- /dev/null +++ b/docs-source/events.md @@ -0,0 +1,49 @@ +# Events and Hosting Documentation + +This is the landing page for all things related to running SSL events and event hosting. If you're a participating team +looking for information about how to join our community or attend an event, please see the official +[SSL website](https://ssl.robocup.org) or [SSL Discord Server](https://discord.com/invite/t724m8c). This documentation +covers how to run an event, not how to attend. + +## Supporting an Existing Event + +### Setup and Teardown Items + +- [Pelican/Travel Case Packing](events/travelcases.md) + +## Hosting a New Event + +Hosting a new event can be challenging, but is made substantially easier with the support of the +[league committees](https://ssl.robocup.org/robocups/robocup-2026/robocup-2026-committees/), and a local university. If +you haven't already, please contact the +[organizing committee (rc-ssl-oc@lists.robocup.org)](mailto:rc-ssl-oc@lists.robocup.org) so we can help you. + +The committee recommends starting no later than 6-months out from the desired event date for regional events and no +later than 12-months out for large international events. This timeline is mostly due to venue availability being limited +on short notice. + +This page provides summary level resources to facilitate choosing a venue and supporting personnel. This wiki has +extensive technical documentation on [field](field.md) and [network](protocol.md) subsystems. + +## Early Stages + +A good first step would be to identify a head organizer and a technical lead. These individuals would then build a +"local organizing committee" and a "local technical committee". + +### Choosing a Venue + +- [Venue Requirements](events/venuerequirements.md) +- [Venue Requirements Calculator](events/venue-calculator.md) + +## Example Layouts + +```{toctree} +--- +maxdepth: 1 +caption: Contents +--- +events/venuerequirements.md +events/venue-calculator.md +events/setupguide.md +events/travelcases.md +``` diff --git a/docs-source/events/images/C2L1.jpg b/docs-source/events/images/C2L1.jpg new file mode 100644 index 0000000..ea9d9ce Binary files /dev/null and b/docs-source/events/images/C2L1.jpg differ diff --git a/docs-source/events/images/C2L2.jpg b/docs-source/events/images/C2L2.jpg new file mode 100644 index 0000000..54e79c3 Binary files /dev/null and b/docs-source/events/images/C2L2.jpg differ diff --git a/docs-source/events/images/C3L1.jpg b/docs-source/events/images/C3L1.jpg new file mode 100644 index 0000000..ccb4b56 Binary files /dev/null and b/docs-source/events/images/C3L1.jpg differ diff --git a/docs-source/events/images/C3L2.jpg b/docs-source/events/images/C3L2.jpg new file mode 100644 index 0000000..5566059 Binary files /dev/null and b/docs-source/events/images/C3L2.jpg differ diff --git a/docs-source/events/images/C3L3.jpg b/docs-source/events/images/C3L3.jpg new file mode 100644 index 0000000..218a80c Binary files /dev/null and b/docs-source/events/images/C3L3.jpg differ diff --git a/docs-source/events/images/cameras_on_truss.jpg b/docs-source/events/images/cameras_on_truss.jpg new file mode 100644 index 0000000..cec05a1 Binary files /dev/null and b/docs-source/events/images/cameras_on_truss.jpg differ diff --git a/docs-source/events/setupguide.md b/docs-source/events/setupguide.md new file mode 100644 index 0000000..b1faedc --- /dev/null +++ b/docs-source/events/setupguide.md @@ -0,0 +1,15 @@ +# Field Setup Guide + +Help wanted! + +Especially picture describing the setup in detail. + +## Pre-Arrival to the Venue + +Ensure you have a schedule created with the + +## Setup Days + +## Event Days + +## Teardown diff --git a/docs-source/events/travelcases.md b/docs-source/events/travelcases.md new file mode 100644 index 0000000..52bc554 --- /dev/null +++ b/docs-source/events/travelcases.md @@ -0,0 +1,89 @@ +# Pelican/Travel Case Packing + +The SSL owns 4 hard-shell travel cases, colloquically called "Pelicans", that are reused for each global event as well +as some of the regionals. They typically go home with a reliable team or TC/OC member for transport to the next +regional/global event. This page documents their contents and the system they use to ensure event setup and teardown is +easy. + +## Top Level Description + +The cases mostly carry the cameras, lenses, truss computers, and cabling required to setup field vision systems and +streaming. + +The league currently has 8 field camera systems (camera + lens + nuc + accessories) which can support 4 Division A +fields or 8 Division B fields. We use 5 total systems at most international events (1 Div A, 2 Div B, 1 Div B practice) +which leaves 3 spare systems. This gives us spares and the ability to run any one field redundantly if we need to test +different vision versions or configurations concurrently. + +The cases are externally labeled as follows: + +- Case 1: Equipment SSL Set 1 +- Case 2: Equipment SSL Set 2 +- Case 3: Cables SSL Set 2 (roughly 21.6kg) +- Case 4: Cables SSL Set 1 (roughly 21.5kg) + +[Laminated Packing Inserts](https://docs.google.com/document/d/1DBrpu4QNOSp4uC7DHPw7sSZ3TgjXhoRiypexUmNRG-8/edit?usp=sharing). + +## Organizational System + +The league currently owns 4 pelicans, two large, two small. They are each colored, which is the first key aspect of how +they are organized. The big pelicans are pink and orange and have a big piece of colored gaff tape on the side. The +small pelicans are green and blue and also have a piece of gaff tape on the side. Some ancillary streaming equipment is +brought by TIGERs Mannheim and this case is labeled yellow. + +**Every case, camera, computer, and cable that is league owned is labeled with colored tape.** Every items always comes +from and goes back into the case of the corresponding color. + +If you are helping with teardown, you can always move an unknown item next to the case of the corresponding color, even +if you don't know where it goes yet. Likewise, if you are following pictures in a setup guide or someone asks for an +items "from the pink case" you'll know what they mean when they make that request. + +Every case should have a laminated sheet fully enumerating the items in the case and including picture of how the case +is to be packed at every layer. The cases are very full, so it's essential that you pack the case the way the pictures +describe. These sheets can also help you located a needed piece of equipment. + +[Laminated Packing Inserts](https://docs.google.com/document/d/1DBrpu4QNOSp4uC7DHPw7sSZ3TgjXhoRiypexUmNRG-8/edit?usp=sharing). + +## Example Camera Setup + +Here's an example of two cameras in a redundant configuration on a Division A truss (one field half) in Incheon 2026. +Note the colored tape on the cameras, cables, and mounting arms. That all corresponds to the above mentioned cases. In +this picture, camera mount arms are from the green pelican, the cameras are from the orange, and one USB3 cable is from +the pink pelican. + + + +## Photos from Packing Lists + +You'll notice the following photos (taken from the laminated packing sheets) shows layer by layer color coordinated +packing as described. + +### Case 2 + +Here's an example of packing Case 2, a large pelican with camera compute and streaming cameras and lenses. All of this +guidance should also be included in the laminated packing insert. + +Layer 1 + + + +Layer 2 + + + +### Case 3 + +Here's an example of packing Case 3, a small pelican with cables and mounting hardware. All of this guidance should be +included in the laminated packing insert. + +Layer 1 + + + +Layer 2 + + + +Layer 3 + + diff --git a/docs-source/events/venue-calculator.md b/docs-source/events/venue-calculator.md new file mode 100644 index 0000000..685381c --- /dev/null +++ b/docs-source/events/venue-calculator.md @@ -0,0 +1,586 @@ +# Venue Requirements Calculator + +Sizes a venue for an SSL event: floor area, power, outlets, and network drops. + +Start from the number of teams you expect. If you venue or event is different, check the "advanced configuration" +dropdown for each section to override any simplifying assumptions that don't work for you. + +This calculator automatically uses [Venue Requirements](venuerequirements.md) to generate a summary document for you. +Defaults are sourced where a league document states the number and estimated where it doesn't. Values are rounded +conservatively. Open **Show calculations** under the results for any section for a more detail explanation of what's +going on. As always, feel free to reach out to the TC/OC for help using this page. + +Results are planning figures for a venue conversation, not an electrical design. Have an electrician or the venue's own +facilities team confirm circuit counts and layout. + +AI Disclosure: This calculator was built with the assistance of Claude Opus 5. Please verify any outputs before sending +to the venue. + +Each resets every section, including anything you changed under Advanced Configuration, + and calculates straight away. Mains voltage and breaker rating are left alone, since those follow the country + rather than the event.
+ + + + + + + + + + + + +Every formula this page uses, and where each number comes from. "Published" means a league +document states it, so follow the link and cite it to your venue. "Estimated" means this calculator picked it, and you +should replace it with a real figure once you have one.
+ +| Pit tables per team | +1 table to 3 members, 2 to 10, 3 to 18, then +1 per 8 members | +Published, 19+ band estimated |
|---|---|---|
| Pit area per team | +(2 × tables + 2) × 3 m², from 2 by 1m tables inline sharing a 1m buffer | +Published |
| Competitors, average mode | +teams × average members, per division | +Your input |
| Competitors, enumerate mode | +Σ (teams in band × band midpoint), using 2, 7, 15, 22 | +Estimated. No league document states a roster size |
| Match fields | +⌈ division teams ÷ teams per match field ⌉, at 10 Division A / 12 Division B per field | +Estimated, sized against the international event's field mix |
|---|---|---|
| Practice fields | +⌈ total teams ÷ 20 ⌉, or none at all when every match field carries 4 teams or fewer | +Estimated |
| Field of play | +13.4 × 10.4 m Division A, 10.4 × 7.4 m Division B, boundary margin included | +Published |
|---|---|---|
| Field footprint | +each dimension plus twice the buffer, so 16.4 by 13.4m for Division A and 13.4 by 10.4m for Division B at + the recommended 1.5m | +Published at a 1.5 m buffer |
| Pits | +(Σ team pit areas + organizer pit area) × 1.30 | +Areas published. The 30% circulation is estimated, since the published figures have no aisles |
| Total | +all field footprints + pits; sq.ft = m² × 10.764. Both are rounded up to whole units for display, + never down. Spectator seating, stage, and registration are not included | +|
| Per competitor | +total area ÷ competitors, to compare against the venue's occupancy limit | +Sanity check, not a code requirement |
| Per field, floor level | +vision and game controller together 500 W, + switch 30 W + router 30 W + lighting, plus 60 W per status board + not on PoE, plus 100 W audio referee where present | +Devices published, wattages estimated |
|---|---|---|
| Per field, truss level | +truss NUCs × 90 W. Truss cameras draw from their NUC | +Config published, wattage estimated |
| Field expected draw | +connected load × 0.5 diversity | +Estimated, roughly the provisioned to average team ratio |
| Pits capacity | +teams × 1400 W provisioned; teams × 750 W expected | +Published |
| Where the figures live | +none of the above are on the form, since they're regulatory, published, or nameplate estimates. All of them
+ sit in one VC_POWER structure in the page's script, and the Power section lists them |
+ Estimated against the minimum specs on + Compute Resources, not measured |
| Usable per circuit | +volts × amps × derate | +Estimated. 80% is the usual continuous load derate |
|---|---|---|
| Pits circuits | +whole team drops packed per circuit, never split, so a circuit holding 1.9 drops still takes one team | +Estimated |
| Field circuits | +counted per field, floor and truss separately, since separated fields can't share a breaker | +Estimated |
| Pits outlets | +one per team, one per organizer table. Teams bring their own power strip | +Published |
|---|---|---|
| Chairs | +one per competitor, one per organizer table, one per table at the field | +Estimated. No league document covers seating |
| Field outlets | +one per table at the field, which covers the vision and game controller computers and their monitors on a + strip, plus one for the switch and router, one per status board whether or not the board is on PoE, one for the + audio referee, one for the streaming rig where a field has one, and one for lighting if any. Totalled as field + floor, field truss and pits floor, since those are three separate asks of the venue | +Published, one outlet per table |
| Truss outlets | +one per truss NUC, at mounting height. Budget rigging for these rather than floor outlets | +Follows from the published camera config |
| Field switch ports | +truss NUCs + vision + game controller + remote controls + status boards + field team tables + audio referee + + uplink. Every field gets the same 24-port switch, so one spare fits any field; the headroom allowance only decides + whether a field needs a second one | +Devices published; headroom and the 24-port standard estimated |
| Switch PoE budget | +remote controls × 25.5 W, plus status boards if on PoE. Cameras are never on the field switch | +Published, remotes need PoE+ |
| Venue drops | +one uplink per field + pits drops per team + organizer tables + internet drops | +Estimated. League documentation sets no pits network requirement |
| VLANs | +one per field, required for isolation, plus one optional VLAN covering the pits | +Per-field isolation + published; the pits VLAN is estimated |
| Addressing | +field N gets VLAN 10N on 10.(10N).0.0/16, so the VLAN id and second octet match; + pits take VLAN 200. Gateway .0.1, reserved .0.2 through .0.50, DHCP from .0.51, broadcast .255.255 | +Subnet layout published; the numbering scheme is + this calculator's suggestion |
Not counted anywhere above: referees, organizers, volunteers, and spectators, along with +whatever space, seating, and facilities they need. Competitor count covers teams only.
+ +