Skip to content
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ to [kdoc.nextftc.dev](https://kdoc.nextftc.dev/).

| Module | Description |
|----------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------|
| [`util`](util/Module.md) | Pure-JVM pieces shared by every module: WPILib struct schemas, an `EventLoop`, and a `Log` facade. |
| [`units`](units/Module.md) | Type-safe physical units (distance, time, mass, force, voltage, angle, etc.) modeled after WPILib's units library. |
| [`linalg`](linalg/Module.md) | A Kotlin wrapper around EJML with `Nat` phantom types, so matrix/vector dimension mismatches are caught at compile time. |
| [`control`](control/Module.md) | Feedback controllers (PID, LQR), feedforward models, signal filters, motion profiling, and typed 2D geometry (`Pose2d`, `Rotation2d`, etc.). |
Expand Down
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ plugins {
}

dependencies {
dokka(project(":util"))
dokka(project(":units"))
dokka(project(":linalg"))
dokka(project(":control"))
Expand Down
1 change: 1 addition & 0 deletions control/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ plugins {
description = "A WPIMath inspired library for controls and other math classes and functions."

dependencies {
api(project(":util"))
api(project(":units"))
api(project(":linalg"))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@
package dev.nextftc.control.geometry

import dev.nextftc.units.InchesPerSecondSquared
import dev.nextftc.units.MetersPerSecondSquared
import dev.nextftc.units.RadiansPerSecondSquared
import dev.nextftc.units.measuretypes.AngularAcceleration
import dev.nextftc.units.measuretypes.Time
import dev.nextftc.units.unittypes.DistanceUnit
import dev.nextftc.units.unittypes.PerUnit
import dev.nextftc.units.unittypes.TimeUnit
import dev.nextftc.util.struct.StructSchema
import dev.nextftc.util.struct.structSchema

/**
* @usesMathJax
Expand Down Expand Up @@ -180,5 +183,16 @@ data class ChassisAccelerations(
Vector2d.zero(InchesPerSecondSquared),
RadiansPerSecondSquared.of(0.0),
)

/**
* The WPILib `ChassisAccelerations` struct: `ax` and `ay` in meters per second squared and
* `alpha` in radians per second squared.
*/
@JvmField
val struct: StructSchema<ChassisAccelerations> = structSchema("ChassisAccelerations") {
float64("ax") { it.linearAcc.x.into(MetersPerSecondSquared) }
float64("ay") { it.linearAcc.y.into(MetersPerSecondSquared) }
float64("alpha") { it.angAcc.into(RadiansPerSecondSquared) }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@
package dev.nextftc.control.geometry

import dev.nextftc.units.InchesPerSecond
import dev.nextftc.units.MetersPerSecond
import dev.nextftc.units.RadiansPerSecond
import dev.nextftc.units.measuretypes.AngularVelocity
import dev.nextftc.units.unittypes.DistanceUnit
import dev.nextftc.units.unittypes.PerUnit
import dev.nextftc.units.unittypes.TimeUnit
import dev.nextftc.util.struct.StructSchema
import dev.nextftc.util.struct.structSchema

/**
* @usesMathJax
Expand Down Expand Up @@ -153,5 +156,16 @@ data class ChassisVelocities(
*/
@JvmField
val zero = ChassisVelocities(Vector2d.zero(InchesPerSecond), RadiansPerSecond.of(0.0))

/**
* The WPILib `ChassisVelocities` struct: `vx` and `vy` in meters per second and `omega` in
* radians per second.
*/
@JvmField
val struct: StructSchema<ChassisVelocities> = structSchema("ChassisVelocities") {
float64("vx") { it.linearVel.x.into(MetersPerSecond) }
float64("vy") { it.linearVel.y.into(MetersPerSecond) }
float64("omega") { it.angVel.into(RadiansPerSecond) }
}
}
}
11 changes: 11 additions & 0 deletions control/src/main/kotlin/dev/nextftc/control/geometry/Pose2d.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import dev.nextftc.units.Inches
import dev.nextftc.units.measuretypes.Angle
import dev.nextftc.units.measuretypes.Distance
import dev.nextftc.units.unittypes.DistanceUnit
import dev.nextftc.util.struct.StructSchema
import dev.nextftc.util.struct.structSchema
import kotlin.math.abs
import kotlin.math.cos
import kotlin.math.sin
Expand Down Expand Up @@ -309,6 +311,15 @@ data class Pose2d(
}

companion object {
/**
* The WPILib `Pose2d` struct: a translation in meters and a rotation in radians.
*/
@JvmField
val struct: StructSchema<Pose2d> = structSchema("Pose2d") {
struct("translation", Vector2d.translation2dStruct) { it.position }
struct("rotation", Rotation2d.struct) { it.heading }
}

/**
* Computes the pose exponential map from a twist.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@
package dev.nextftc.control.geometry

import dev.nextftc.units.InchesPerSecondSquared
import dev.nextftc.units.MetersPerSecondSquared
import dev.nextftc.units.RadiansPerSecondSquared
import dev.nextftc.units.measuretypes.AngularAcceleration
import dev.nextftc.units.measuretypes.Time
import dev.nextftc.units.unittypes.DistanceUnit
import dev.nextftc.units.unittypes.PerUnit
import dev.nextftc.units.unittypes.TimeUnit
import dev.nextftc.util.struct.StructSchema
import dev.nextftc.util.struct.structSchema

/**
* @usesMathJax
Expand Down Expand Up @@ -191,5 +194,16 @@ data class PoseAcceleration2d(
Vector2d.zero(InchesPerSecondSquared),
RadiansPerSecondSquared.of(0.0),
)

/**
* The WPILib `ChassisAccelerations` struct, which WPILib uses for field-frame accelerations
* too: `ax` and `ay` in meters per second squared and `alpha` in radians per second squared.
*/
@JvmField
val struct: StructSchema<PoseAcceleration2d> = structSchema("ChassisAccelerations") {
float64("ax") { it.linearAcc.x.into(MetersPerSecondSquared) }
float64("ay") { it.linearAcc.y.into(MetersPerSecondSquared) }
float64("alpha") { it.angAcc.into(RadiansPerSecondSquared) }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@
package dev.nextftc.control.geometry

import dev.nextftc.units.InchesPerSecond
import dev.nextftc.units.MetersPerSecond
import dev.nextftc.units.RadiansPerSecond
import dev.nextftc.units.measuretypes.AngularVelocity
import dev.nextftc.units.unittypes.DistanceUnit
import dev.nextftc.units.unittypes.PerUnit
import dev.nextftc.units.unittypes.TimeUnit
import dev.nextftc.util.struct.StructSchema
import dev.nextftc.util.struct.structSchema

/**
* @usesMathJax
Expand Down Expand Up @@ -168,5 +171,16 @@ data class PoseVelocity2d(
companion object {
@JvmField
val zero = PoseVelocity2d(Vector2d.zero(InchesPerSecond), RadiansPerSecond.of(0.0))

/**
* The WPILib `ChassisVelocities` struct, which WPILib uses for field-frame velocities too: `vx`
* and `vy` in meters per second and `omega` in radians per second.
*/
@JvmField
val struct: StructSchema<PoseVelocity2d> = structSchema("ChassisVelocities") {
float64("vx") { it.linearVel.x.into(MetersPerSecond) }
float64("vy") { it.linearVel.y.into(MetersPerSecond) }
float64("omega") { it.angVel.into(RadiansPerSecond) }
}
}
}
10 changes: 10 additions & 0 deletions control/src/main/kotlin/dev/nextftc/control/geometry/Rotation2d.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import dev.nextftc.units.Radians
import dev.nextftc.units.Unit
import dev.nextftc.units.inches
import dev.nextftc.units.measuretypes.Angle
import dev.nextftc.util.struct.StructSchema
import dev.nextftc.util.struct.structSchema
import kotlin.math.atan2
import kotlin.math.cos
import kotlin.math.sin
Expand Down Expand Up @@ -214,5 +216,13 @@ data class Rotation2d(@JvmField val real: Double, @JvmField val imag: Double) {
*/
@JvmField
val zero = Rotation2d(1.0, 0.0)

/**
* The WPILib `Rotation2d` struct: `double value`, the angle in radians.
*/
@JvmField
val struct: StructSchema<Rotation2d> = structSchema("Rotation2d") {
float64("value") { it.log() }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import dev.nextftc.units.Inches
import dev.nextftc.units.measuretypes.Angle
import dev.nextftc.units.measuretypes.Distance
import dev.nextftc.units.unittypes.DistanceUnit
import dev.nextftc.util.struct.StructSchema
import dev.nextftc.util.struct.structSchema

/**
* @usesMathJax
Expand Down Expand Up @@ -268,5 +270,14 @@ data class Transform2d(
*/
@JvmField
val identity = Transform2d(Vector2d.zero(Inches), Rotation2d.zero)

/**
* The WPILib `Transform2d` struct: a translation in meters and a rotation in radians.
*/
@JvmField
val struct: StructSchema<Transform2d> = structSchema("Transform2d") {
struct("translation", Vector2d.translation2dStruct) { it.translation }
struct("rotation", Rotation2d.struct) { it.rotation }
}
}
}
13 changes: 13 additions & 0 deletions control/src/main/kotlin/dev/nextftc/control/geometry/Twist2d.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@
package dev.nextftc.control.geometry

import dev.nextftc.units.Inches
import dev.nextftc.units.Meters
import dev.nextftc.units.measuretypes.Angle
import dev.nextftc.units.measuretypes.Distance
import dev.nextftc.units.unittypes.DistanceUnit
import dev.nextftc.util.struct.StructSchema
import dev.nextftc.util.struct.structSchema

/**
* @usesMathJax
Expand Down Expand Up @@ -171,5 +174,15 @@ data class Twist2d(@JvmField val line: Vector2d<DistanceUnit>, @JvmField val ang
companion object {
@JvmField
val zero = Twist2d(Vector2d.zero(Inches), 0.0)

/**
* The WPILib `Twist2d` struct: `dx` and `dy` in meters and `dtheta` in radians.
*/
@JvmField
val struct: StructSchema<Twist2d> = structSchema("Twist2d") {
float64("dx") { it.line.x.into(Meters) }
float64("dy") { it.line.y.into(Meters) }
float64("dtheta") { it.angle }
}
}
}
13 changes: 13 additions & 0 deletions control/src/main/kotlin/dev/nextftc/control/geometry/Vector2d.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
package dev.nextftc.control.geometry

import dev.nextftc.units.Measure
import dev.nextftc.units.Meters
import dev.nextftc.units.Unit
import dev.nextftc.units.inches
import dev.nextftc.units.inchesPerSecond
Expand All @@ -19,6 +20,8 @@ import dev.nextftc.units.measuretypes.Time
import dev.nextftc.units.unittypes.DistanceUnit
import dev.nextftc.units.unittypes.PerUnit
import dev.nextftc.units.unittypes.TimeUnit
import dev.nextftc.util.struct.StructSchema
import dev.nextftc.util.struct.structSchema
import kotlin.math.sqrt

/**
Expand Down Expand Up @@ -182,6 +185,16 @@ data class Vector2d<U : Unit<U>>(@JvmField val x: Measure<U>, @JvmField val y: M
@JvmField
val zero = Vector2d(0.0.inches, 0.0.inches)

/**
* The WPILib `Translation2d` struct: `x` and `y` in meters. It describes a displacement, so it
* applies to a `Vector2d<DistanceUnit>`.
*/
@JvmField
val translation2dStruct: StructSchema<Vector2d<DistanceUnit>> = structSchema("Translation2d") {
float64("x") { it.x.into(Meters) }
float64("y") { it.y.into(Meters) }
}

/**
* Creates a zero vector with the specified unit.
*
Expand Down
Loading
Loading