diff --git a/public/hardware-intro/spark-max-motor-controller.webp b/public/hardware-intro/spark-max-motor-controller.webp new file mode 100644 index 00000000..339a8ec4 Binary files /dev/null and b/public/hardware-intro/spark-max-motor-controller.webp differ diff --git a/public/hardware-intro/talonfx-motor-controller.webp b/public/hardware-intro/talonfx-motor-controller.webp new file mode 100644 index 00000000..8329aa86 Binary files /dev/null and b/public/hardware-intro/talonfx-motor-controller.webp differ diff --git a/src/components/ContentCard.astro b/src/components/ContentCard.astro new file mode 100644 index 00000000..182308c0 --- /dev/null +++ b/src/components/ContentCard.astro @@ -0,0 +1,83 @@ +--- +import type { HTMLAttributes } from 'astro/types'; + +interface Props extends Omit, 'title'> { + title: string; + description?: string; + eyebrow?: string; + href: string; +} + +const { title, description, eyebrow, href, ...attributes } = Astro.props; +--- + + + {eyebrow &&

{eyebrow}

} +

{title}

+ {description &&

{description}

} + + +
+ + diff --git a/src/components/ContentTitleBar.astro b/src/components/ContentTitleBar.astro new file mode 100644 index 00000000..21cc1909 --- /dev/null +++ b/src/components/ContentTitleBar.astro @@ -0,0 +1,48 @@ +--- +interface Props { + label?: string; + title: string; + description?: string; +} + +const { label, title, description } = Astro.props; +--- + +
+ {label &&

{label}

} +

{title}

+ {description &&

{description}

} +
+ + diff --git a/src/config/sidebarConfig.ts b/src/config/sidebarConfig.ts index 834b44e2..4d09735e 100644 --- a/src/config/sidebarConfig.ts +++ b/src/config/sidebarConfig.ts @@ -249,8 +249,10 @@ export const sidebarSections: Record = { { label: 'Resources', items: [ - { label: 'Overview', slug: 'resources' }, + { label: 'Overview', slug: 'resources/overview' }, + { label: 'Glossary', slug: 'resources/glossary' }, { label: 'Documentation', slug: 'resources/docs' }, + { label: 'Hardware', slug: 'resources/hardware-intro' }, { label: 'Examples', slug: 'resources/examples' }, { label: 'Glossary', slug: 'resources/glossary' }, ], @@ -272,6 +274,82 @@ export const sidebarSections: Record = { ], }, ], + + // Getting Started section + '/getting-started': [ + { + label: 'Getting Started', + items: [ + { + label: 'Website Feature Guide', + slug: 'learning-course/getting-started/website-feature-guide', + }, + { + label: 'Required Tools', + slug: 'learning-course/getting-started/required-tools', + }, + { + label: 'VS Code Overview', + slug: 'learning-course/getting-started/vscode-overview', + }, + { + label: 'Forking and Cloning', + slug: 'learning-course/getting-started/forking-and-cloning', + }, + { + label: 'Intro to Java', + slug: 'learning-course/stage0/stage-overview', + }, + ], + }, + ], + + // Intro To Java section + '/intro-to-java': [ + { + label: 'Intro to Java', + items: [ + { + label: 'Stage Overview', + slug: 'learning-course/stage0/stage-overview', + }, + { + label: 'Java fundamentals', + slug: 'learning-course/stage0/java-fundamentals', + }, + { + label: 'operators', + slug: 'learning-course/stage0/operators', + }, + ], + }, + ], + + // Resources section (content lives at /resources but navbar says "Other Resources") + '/resources': [ + { + label: 'Resources', + items: [ + { label: 'Overview', slug: 'resources/overview' }, + { + label: 'Examples', + slug: 'resources/examples', + }, + { + label: 'Glossary', + slug: 'resources/glossary', + }, + { + label: 'Hardware', + slug: 'resources/hardware-intro', + }, + { + label: 'Documentation', + slug: 'resources/docs', + }, + ], + }, + ], }; /** diff --git a/src/config/sidebarTopics.ts b/src/config/sidebarTopics.ts index 89d6088b..76810381 100644 --- a/src/config/sidebarTopics.ts +++ b/src/config/sidebarTopics.ts @@ -39,9 +39,9 @@ export const sidebarTopics = [ { label: 'Resources', id: 'resources', - link: '/resources/docs/', - icon: 'document', - items: sidebarSections['/other-resources']![0]!.items.map(convertItem), + link: '/resources/overview/', + icon: 'folder', + items: sidebarSections['/resources']![0]!.items.map(convertItem), }, { label: 'Contribution', diff --git a/src/content/docs/contribution/methodsOfContributing.mdx b/src/content/docs/contribution/methodsOfContributing.mdx index f524273e..72d8b0e0 100644 --- a/src/content/docs/contribution/methodsOfContributing.mdx +++ b/src/content/docs/contribution/methodsOfContributing.mdx @@ -93,7 +93,7 @@ You can get a local hosted version of the website to have a live preview of the Make sure to run `pnpm dev` every time you open VS Code to edit. diff --git a/src/content/docs/index.mdx b/src/content/docs/index.mdx index 0e308db8..433fa3d9 100644 --- a/src/content/docs/index.mdx +++ b/src/content/docs/index.mdx @@ -28,6 +28,12 @@ import HomeCard from '../../components/HomeCard.astro'; icon="book" description="A guide for educators implementing the FRCSoftware.org Learning Course." /> + diff --git a/src/content/docs/resources/hardware-intro.mdx b/src/content/docs/resources/hardware-intro.mdx new file mode 100644 index 00000000..6c1665ea --- /dev/null +++ b/src/content/docs/resources/hardware-intro.mdx @@ -0,0 +1,58 @@ +--- +title: Hardware Intro +description: An introduction to hardware components for programmers +--- + +## Motor Controllers + +While motors are the physical actuators that spin a robot's mechanisms, motor controllers are the electronic interfaces that control the speed and direction of the motor. +Most motor controllers also offer smart abilities like onboard PID controllers and integrated encoders. + +Motor controllers are used throughout the robot in many mechanisms: + +- Intakes: Spin wheels to collect game pieces +- Shooters: Spin flywheels to launch game pieces +- Indexers: Move game pieces through the robot +- Arms/Elevators: Raise and lower mechanisms (often with position control) +- Climbers: Extend or retract climbing mechanisms + +CAN motor controllers are available through vendors such as CTR Electronics (Talon FX) and REV Robotics (SPARK MAX). + +![TalonFX motor controller](../../../../public/hardware-intro/talonfx-motor-controller.webp#w=30) +![SPARK MAX motor controller](../../../../public/hardware-intro/spark-max-motor-controller.webp#w=20) + +## Encoders + +Encoders measure rotational motion. +They are reliable and less-prone to noise and interference than analog devices (such as potentiometers) because they produce digital signals. +They can return the position and velocity of a mechanism. +Encoders come in a variety of form factors, and may be mounted at the end of a shaft or have a shaft run through them. +Many motor controllers also have integrated encoders. +Relative encoders track changes in position and reset to zero when the robot is turned off, while absolute encoders track exact, unique positions across a full rotation and retain this data even when powered off. + +## Beam Break + +A beam break detects if anything is between two points and returns a binary value. +Beam breaks are typically [`DigitalInput`](https://github.wpilib.org/allwpilib/docs/2027/java/org/wpilib/hardware/discrete/DigitalInput.html)s and will return a `boolean`. +Beam breaks can be used to detect when game pieces pass a specific point on a robot. + +## Limit Switch + +A limit switch detects if something is at a certain position or distance and returns a binary value. +Limit switches are often used to restrict the range of motion of a joint or detect the presence of game pieces. +While beam breaks and limit switches both detect the presence of an object, they differ in how they do this. +Beam breaks detect whether a beam of light is being blocked by an object, while limit switches require physical contact with an object to detect it. + +## Inertial Measurement Units (IMUs) + +An IMU is a sensor that combines an accelerometer and a gyroscope. +IMUs are used to measure a robot's orientation, rates of rotation, and acceleration and return these signals as a [`Rotation2d`](https://github.wpilib.org/allwpilib/docs/2027/java/org/wpilib/math/geometry/Rotation2d.html). +They typically use degrees or radians for angular position (yaw/heading, pitch, and roll) and degrees per second or radians per second for angular velocity. +They can be used for robot heading readings and odometry calculations. +The most popular IMUs in FRC are navX2, Pigeon 2.0, and the onboard SystemCore IMU. +Note that the onboard SystemCore IMU is new for 2027 and has not undergone significant successful testing. + +One important thing to note is that gyros measure rate rather than position. +Position is inferred by repeatedly measuring the angular velocity and multiplying those values by the delta time between readings. +Gyro angle measurements are always relative to some arbitrary zero angle determined by the angle of the gyro either when the robot was turned on or a zeroing method was called. +They can have accumulated errors (called “drift”) that increase in magnitude the longer the gyro is used. diff --git a/src/content/docs/resources/overview.mdx b/src/content/docs/resources/overview.mdx new file mode 100644 index 00000000..d8e98d58 --- /dev/null +++ b/src/content/docs/resources/overview.mdx @@ -0,0 +1,36 @@ +--- +title: Overview +description: An overview of additional programming resources +--- + +import { CardGrid } from '@astrojs/starlight/components'; +import ContentCard from '../../../components/ContentCard.astro'; +import ContentTitleBar from '../../../components/ContentTitleBar.astro'; + +import CourseSection from '@components/CourseSection.astro'; + +Many other resources exist out there for FRC programming. +The Resource section includes different resources that can be helpful for learning more programming or for the build season! + + +

+ A lot of documentation from FIRST Vendors, software libraries, logging + software, and more are helpful tools. This page has links to helpful + documentation that you might reference when programming. +

+
+ + +

+ Software and hardware overlap! This page covers different pieces of + hardware (e.g., SPARK MAX, Talon FX, etc.) that you will code or + encounter when programming a robot. +

+
+ + +

+ This website has a lot of terms that may be new to new programmers. Our + glossary is a list of all the terms and their definitions. +

+
diff --git a/src/data/glossary.ts b/src/data/glossary.ts new file mode 100644 index 00000000..e7834629 --- /dev/null +++ b/src/data/glossary.ts @@ -0,0 +1,132 @@ +/** + * Glossary of terms and abbreviations + * + * Add terms here to automatically highlight them across the site + * with a dotted underline and hover tooltip. + * + * Definitions should not have a period at the end + * + * @property definition: The explanation shown on hover + * @property caseSensitive: If true, match this term only in its exact casing (e.g. "CAN" won't match "can"). Defaults to false. + * @property term: The word/abbreviation to match (case-insensitive unless caseSensitive is true) + */ + +export interface GlossaryTerm { + /** + * The word/abbreviation to match (case-insensitive) + * @example "SystemCore" + */ + term: string; + /** + * The explanation shown on hover + * @example "Main processor for robot code, contains various IO" + */ + definition: string; + /** + * If true, match this term only in its exact casing (e.g. "CAN" won't match "can"). + * @default false + */ + caseSensitive?: boolean; +} + +export const glossaryTerms: GlossaryTerm[] = [ + // Electronics + { + term: 'PDH', + definition: 'Power Distribution Hub', + }, + { + term: 'Spark MAX', + definition: 'Motor controller for REV motors', + }, + { + term: 'Talon FX', + definition: 'Motor controller for CTRE motors', + }, + { + term: 'SystemCore', + definition: 'Main processor for robot code, contains various IO', + }, + { + term: 'CAN', + definition: + 'Controller Area Network: typically yellow and green cable used to communicate with motor controllers and sensors, can be run in various topographies instead of each cable needing to connect to SystemCore', + caseSensitive: true, + }, + { + term: 'PWM', + definition: + 'Pulse Width Modulation: A communication spec used to communicate with motor controllers and sensors, needs to connect back to SystemCore', + }, + { + term: 'Main Breaker', + definition: 'Power switch for the robot', + }, + { + term: 'Limit Switch', + definition: + 'Type of sensor that triggers when physically or magnetically hit. Can be used to trigger actions on a rising or falling edge, or check state of a mechanism', + }, + { + term: 'Throughbore Encoder', + definition: + 'An encoder that allows shafts to pass through its center to record angular position', + }, + { + term: 'Magnetic Encoder', + definition: + 'An encoder that uses a receiver and a magnet to measure position and motion', + }, + + // Software + { + term: 'Repository', + definition: + 'A storage location for your code and related assets, often used in version control systems like Git. Repositories are just folders that contain files and subfolders, and they can be hosted on platforms like GitHub to facilitate collaboration and version tracking', + }, + { + term: 'CI', + definition: + 'Continuous Integration: A software development practice where developers frequently merge code changes into a shared repository, triggering automated builds and tests to ensures the codebase remains stable', + }, + { + term: 'WPILib', + definition: + 'WPILib is the standard software library and toolsuite provided for teams to write, test, and debug code for their FIRST® Robotics Competition and FIRST® Tech Challenge robots', + }, + { + term: 'GitHub', + definition: + 'GitHub is like Google Drive, but for code. It hosts git repositories and allows for improved collaboration on projects through pull requests and issues', + }, + { + term: 'Heading', + definition: + 'The direction the robot is pointed, usually expressed as an angle in degrees', + }, + { + term: 'Odometry', + definition: + 'Using sensors on the robot to create an estimate of the pose of the robot on the field.', + }, +]; + +/** + * Get a glossary term by its name (case-insensitive) + */ +export function getGlossaryTerm(term: string): GlossaryTerm | undefined { + return glossaryTerms.find( + (g) => g.term.toLowerCase() === term.toLowerCase(), + ); +} + +/** + * Get all terms as a map for quick lookup + */ +export function getGlossaryMap(): Map { + const map = new Map(); + glossaryTerms.forEach(({ term, definition }) => { + map.set(term.toLowerCase(), definition); + }); + return map; +}