diff --git a/.vitepress/sidebar/nextftc.mts b/.vitepress/sidebar/nextftc.mts index 4f90130..26ccbc4 100644 --- a/.vitepress/sidebar/nextftc.mts +++ b/.vitepress/sidebar/nextftc.mts @@ -118,6 +118,33 @@ export default [ text: "RunToState", link: "/nextftc/hardware/motor-and-servo-commands/runtostate" } + ] + }, + { + text: "Sensors and Webcams", + items: [ + { + text: "Color Sensors", + link: "/nextftc/hardware/sensors-and-webcams/color-sensors" + }, + { + text: "Distance Sensors", + link: "/nextftc/hardware/sensors-and-webcams/distance-sensors" + }, + { + text: "Digital Sensors", + link: "/nextftc/hardware/sensors-and-webcams/digital-sensors" + }, + { + text: "Limelight", + link: "/nextftc/hardware/sensors-and-webcams/limelight" + }, + { + text: "HuskyLens", + link: "/nextftc/hardware/sensors-and-webcams/husky-lens" + } + + ] } ] diff --git a/src/nextftc/hardware/sensors-and-webcams/color-sensors.md b/src/nextftc/hardware/sensors-and-webcams/color-sensors.md new file mode 100644 index 0000000..e95da6a --- /dev/null +++ b/src/nextftc/hardware/sensors-and-webcams/color-sensors.md @@ -0,0 +1,147 @@ +# Color Sensor + +`NextColorDistanceSensor` wraps a `NormalizedColorSensor` and an optional `DistanceSensor` providing color and distance readings with support for color matching in multiple color spaces. + +## Declarations + +:::tabs key:code + +== Kotlin +```kotlin +// Color only +val sensor = NextColorDistanceSensor("sensor_name") + +// With distance +val sensor = NextColorDistanceSensor("sensor_name", true) +``` + +== Java +```java +// Color only +NextColorDistanceSensor sensor = new NextColorDistanceSensor("sensor_name"); + +// With distance +NextColorDistanceSensor sensor = new NextColorDistanceSensor("sensor_name", true); +``` + +::: + +## Usage + +**Call `update()` once per loop before reading any values:** + +:::tabs key:code + +== Kotlin +```kotlin +override fun periodic() { + sensor.update() +} +``` + +== Java +```java +@Override +public void periodic() { + sensor.update(); +} +``` + +::: + + +## ColorProfile +`ColorProfile` defines a target color and tolerances for that target color. HSV is recommended because it is more stable under different lighting conditions, however RGB is also supported. + + +:::tabs key:code + +== Kotlin +```kotlin +val green = ColorProfile( + space = ColorSpace.HSV, //Desired Color Space (.HSV and .RGB both work) + color = NextColor.hsv(130f, 0.7f, 0.6f), //The target color you want (use desired space) + tolerance = NextColor.hsv(20f, 0.3f, 1f), //The tolerance of the target (use desired space) +) + +override fun periodic() { + sensor.update() + if (sensor.isColor(green)) { ... } +} +``` +In this example, `.isColor(green)` returns true if the detected color falls within the target color's tolerance and false otherwise. + +== Java +```java +ColorProfile green = new ColorProfile( + ColorSpace.HSV, //Desired Color Space (.HSV and .RGB both work) + NextColor.hsv(130f, 0.7f, 0.6f), //The target color you want (use desired space) + NextColor.hsv(20f, 0.3f, 1f) //The tolerance of the target (use desired space) +); + +@Override +public void periodic() { + sensor.update(); + if (sensor.isColor(green)) { ... } +} +``` +In this example, `.isColor(green)` returns true if the detected color falls within the target color's tolerance and false otherwise. +::: + +You can use [`debug()`](./color-sensors.md#debug) to calibrate a target color and determine appropriate tolerance values. + + +### Color and Distance Features + +See [Distance Sensor](./distance-sensors.md#usage) for usage of distance methods, `NextColorDistanceSensor` exposes the same methods. + +:::tabs key:code + +== Kotlin +```kotlin +// Checks if the reading is within the tolerance of green +val isGreen = sensor.isColor(green) + +// Checks if the reading is within the tolerance of green and the object is within 4 cm +val isCloseToGreen = sensor.isColorWithinDistance(green, 4.0) + +// Checks if the reading is within the tolerance of green and the object is within 2 inches +val isCloseToGreenInches = sensor.isColorWithinDistance(green, 2.0, DistanceUnit.INCH) +``` +Any distance features will use centimeters by default + +== Java +```java +// Checks if the reading is within the tolerance of green +boolean isGreen = sensor.isColor(green); + +// Checks if the reading is within the tolerance of green and the object is within 4 cm +boolean isCloseToGreen = sensor.isColorWithinDistance(green, 4.0); + +// Checks if the reading is within the tolerance of green and the object is within 2 inches +boolean isCloseToGreenInches = sensor.isColorWithinDistance(green, 2.0, DistanceUnit.INCH); +``` + +Any distance features will use centimeters by default +::: + +### Debug + +You can use `debug()` in telemetry to calibrate a `ColorProfile`: + +:::tabs key:code + +== Kotlin +```kotlin +// Outputs: RGB=(r,g,b) HSV=(h,s,v) Dist=d +telemetry.addLine(sensor.debug()) +``` + +== Java +```java +// Outputs: RGB=(r,g,b) HSV=(h,s,v) Dist=d +telemetry.addLine(sensor.debug()); +``` + +::: + diff --git a/src/nextftc/hardware/sensors-and-webcams/digital-sensors.md b/src/nextftc/hardware/sensors-and-webcams/digital-sensors.md new file mode 100644 index 0000000..96ac41f --- /dev/null +++ b/src/nextftc/hardware/sensors-and-webcams/digital-sensors.md @@ -0,0 +1,75 @@ +# Digital Sensor + +`NextDigitalSensor` wraps a `DigitalChannel` for reading digital sensors like limit switches, magnetic switches, +and beam breaks. + + +## Declarations +Most digital sensors are "active low" which means they read `false` +when triggered and `true` when idle. `NextDigitalSensor` handles this inversion automatically, +though it can be reverted if needed. Check your sensors documentation for more info on it. + + +:::tabs key:code + +== Kotlin +```kotlin +val sensor = NextDigitalSensor("sensor_name") + +// Not inverted (active high) +val sensor = NextDigitalSensor("sensor_name", inverted = false) +``` + +== Java +```java +NextDigitalSensor sensor = new NextDigitalSensor("sensor_name"); + +// Not inverted (active high) +NextDigitalSensor sensor = new NextDigitalSensor("sensor_name", false); +``` + +::: + +## Usage +`isTriggered` returns `true` when the sensor is activated, and `rawState` returns the raw state of the sensor +(raw state does not account for inversion). + +:::tabs key:code + +== Kotlin +```kotlin +if (sensor.isTriggered) { ... } + +// Raw state if needed +val raw = sensor.rawState +``` + +== Java +```java +if (sensor.isTriggered()) { ... } + +// Raw state if needed +boolean raw = sensor.getRawState(); +``` + +::: + +### Debug +Use `debug()` in telemetry to see the current triggered state, raw state, and whether inversion is `true`. + + +:::tabs key:code + +== Kotlin +```kotlin +// Outputs: Sensor State: boolean, Raw State: boolean, Inverted: boolean +telemetry.addLine(sensor.debug()) +``` + +== Java +```java +// Outputs: Sensor State: boolean, Raw State: boolean, Inverted: boolean +telemetry.addLine(sensor.debug()); +``` + +::: \ No newline at end of file diff --git a/src/nextftc/hardware/sensors-and-webcams/distance-sensors.md b/src/nextftc/hardware/sensors-and-webcams/distance-sensors.md new file mode 100644 index 0000000..afcd629 --- /dev/null +++ b/src/nextftc/hardware/sensors-and-webcams/distance-sensors.md @@ -0,0 +1,56 @@ +# Distance Sensor + +`NextDistanceSensor` wraps a `DistanceSensor` and provides easy-to-use distance readings with built-in utility features. + +## Declarations + +:::tabs key:code + +== Kotlin +```kotlin +val sensor = NextDistanceSensor("sensor_name") +``` + +== Java +```java +NextDistanceSensor sensor = new NextDistanceSensor("sensor_name"); +``` + +::: + +## Usage +**Call `update()` once per loop before reading any values:** + +:::tabs key:code + +== Kotlin +```kotlin +override fun periodic() { + sensor.update() + + val cm = sensor.getDistance() + val inches = sensor.getDistance(DistanceUnit.INCH) + + if (sensor.isWithinDistance(2.0)) { ... } + if (sensor.isWithinDistance(2.0, DistanceUnit.INCH)) { ... } +} +``` +`sensor.isWithinDistance(2.0)` returns true if the distance is within 2 cm, if a unit is specified, it will use that unit. + +== Java +```java +@Override +public void periodic() { + sensor.update(); + + double cm = sensor.getDistance(); + double inches = sensor.getDistance(DistanceUnit.INCH); + + if (sensor.isWithinDistance(2.0)) { ... } + if (sensor.isWithinDistance(2.0, DistanceUnit.INCH)) { ... } +} +``` +`sensor.isWithinDistance(2.0)` returns true if the distance is within 2 cm, if a unit is specified, it will use that unit. +::: + +Any distance features will use centimeters by default diff --git a/src/nextftc/hardware/sensors-and-webcams/husky-lens.md b/src/nextftc/hardware/sensors-and-webcams/husky-lens.md new file mode 100644 index 0000000..c428ac8 --- /dev/null +++ b/src/nextftc/hardware/sensors-and-webcams/husky-lens.md @@ -0,0 +1,60 @@ +# HuskyLens +`NextHuskyLens` wraps a `HuskyLens`, providing convenient methods for selecting algorithms and reading detecting objects. + +## Declarations + +:::tabs key:code + +== Kotlin +```kotlin +val huskyLens = NextHuskyLens("husky_lens") +``` + +== Java +```java +NextHuskyLens huskyLens = new NextHuskyLens("husky_lens"); +``` + +::: + +## Usage + +### Setup + +Call `selectAlgorithm()` once on startup to set the recognition mode, and `knock()` to verify the sensor is responding: + +:::tabs key:code + +== Kotlin +```kotlin +huskyLens.selectAlgorithm(HuskyLens.Algorithm.TAG_RECOGNITION) // or any desired algorithm +val connected = huskyLens.knock() +``` + +== Java +```java +huskyLens.selectAlgorithm(HuskyLens.Algorithm.TAG_RECOGNITION); // or any desired algorithm +boolean connected = huskyLens.knock(); +``` + +::: + +### Blocks and Arrows + +`blocks()` and `arrows()` return up to 6 currently visible results. Pass an ID to filter for a specific learned object. + +:::tabs key:code + +== Kotlin +```kotlin +val all = huskyLens.blocks() +val filtered = huskyLens.blocks(1) +``` + +== Java +```java +HuskyLens.Block[] all = huskyLens.blocks(); +HuskyLens.Block[] filtered = huskyLens.blocks(1); +``` +::: + diff --git a/src/nextftc/hardware/sensors-and-webcams/limelight.md b/src/nextftc/hardware/sensors-and-webcams/limelight.md new file mode 100644 index 0000000..7b14144 --- /dev/null +++ b/src/nextftc/hardware/sensors-and-webcams/limelight.md @@ -0,0 +1,89 @@ +# Limelight + +`NextLimelight` wraps a `Limelight3A` making it easier to start the camera, switch pipelines, and retrieve robot pose and target data. + + +## Declarations + +:::tabs key:code + +== Kotlin +```kotlin +val limelight = NextLimelight("limelight") +``` + +== Java +```java +NextLimelight limelight = new NextLimelight("limelight"); +``` + +::: + +## Usage + +### Starting and Stopping + +:::tabs key:code + +== Kotlin +```kotlin +limelight.startReading(pipeline = 0) // default 100 Hz +limelight.startReading(pipeline = 0, hz = 50) + +limelight.stop() +``` + +== Java +```java +limelight.startReading(0); //sets pipeline to 0 and defaults 100 Hz +limelight.startReading(0, 50); //sets pipeline to 0 and 50 Hz + +limelight.stop(); +``` + +::: + +### Distance + +Returns the straight-line distance (hypotenuse) to an AprilTag. +If no unit is specified, inches are used by default. + +:::tabs key:code + +== Kotlin +```kotlin +val dist = limelight.getDistance() // default: inches +val cm = limelight.getDistance(DistanceUnit.CM) +val inches = limelight.getDistance(id = 20) // specific tag, inches +val cm3 = limelight.getDistance(DistanceUnit.CM, id = 3) +``` + +== Java +```java +double dist = limelight.getDistance(); // default: inches +double cm = limelight.getDistance(DistanceUnit.CM); +double inches = limelight.getDistance(DistanceUnit.CM, 20); // specific tag, and in CM +``` +::: +If a specfic ID is not given the distance will be calculated using any detected april tag. + + +## Relocalization + +`getPedroPoseFromLimelight()` returns the robot's field position as a `Pose2d` in [Pedro coordinates](https://pedropathing.com/docs/pathing/reference/coordinates), or `null` if no valid pose is available. + +:::tabs key:code + +== Kotlin +```kotlin +val pose = limelight.getPedroPoseFromLimelight() ?: return +``` +This method uses any detected AprilTag. It is recommended to exclude unwanted tags in the Limelight pipeline. + +== Java +```java +Pose2d pose = limelight.getPedroPoseFromLimelight(); +if (pose == null) return; +``` +This method uses any detected AprilTag. It is recommended to exclude unwanted tags in the Limelight pipeline. +::: \ No newline at end of file