Skip to content

Commit 06814ec

Browse files
committed
add: basic nextcontrol info + sidebar
Signed-off-by: Zach Harel <zach.harel42@gmail.com>
1 parent 8b3eda2 commit 06814ec

7 files changed

Lines changed: 295 additions & 13 deletions

File tree

.idea/workspace.xml

Lines changed: 39 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.vitepress/config.mts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {tabsMarkdownPlugin} from "vitepress-plugin-tabs";
33
import guide from "./sidebar/guide.mts";
44
import nextftc from "./sidebar/nextftc.mts";
55
import bindings from "./sidebar/bindings.mts";
6+
import control from "./sidebar/control.mts";
67

78
// https://vitepress.dev/reference/site-config
89
export default defineConfig({
@@ -62,7 +63,8 @@ export default defineConfig({
6263
sidebar: {
6364
'/guide/': guide,
6465
'/nextftc/': nextftc,
65-
'/bindings/': bindings
66+
'/bindings/': bindings,
67+
'/control/': control
6668
},
6769

6870
socialLinks:

.vitepress/sidebar/control.mts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import {DefaultTheme} from "vitepress";
2+
3+
type SidebarItem = DefaultTheme.SidebarItem;
4+
5+
export default [
6+
{
7+
text: "Overview",
8+
link: "/control/",
9+
},
10+
{
11+
text: "Kinetic States",
12+
link: "/control/kineticstates",
13+
},
14+
{
15+
text: "Control Systems",
16+
link: "/control/controlsystem",
17+
},
18+
{
19+
text: "Examples",
20+
items: [
21+
{
22+
text: "Linear Slides",
23+
link: "/control/examples/slides",
24+
}
25+
]
26+
}
27+
] satisfies SidebarItem[]

src/control/controlsystem.md

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# Control System
2+
3+
Control Systems represent a combination of the Four Elements of control described earlier.
4+
They are created using convenient builder syntax, or, for Kotlin users, a DSL-style builder.
5+
6+
Here is an easy example:
7+
8+
::: tabs key:code
9+
10+
== Kotlin
11+
12+
```kotlin
13+
val system = controlSystem {
14+
posPid(0.5, 0.0, 0.0)
15+
}
16+
17+
system.goal = KineticState(10.0, 0.0, 0.0)
18+
```
19+
20+
== Java
21+
22+
```java
23+
ControlSystem system = ControlSystem.builder()
24+
.posPid(0.5, 0, 0)
25+
.build();
26+
27+
system.setGoal(new KineticState(10.0, 0.0, 0.0));
28+
```
29+
30+
:::
31+
32+
There are many quick methods to add pre-defined control elements,
33+
or you can define your own!
34+
35+
::: tabs key:code
36+
37+
== Kotlin
38+
39+
```kotlin
40+
val controller = controlSystem {
41+
posFilter {
42+
custom {
43+
state -> 0.5 * state
44+
}
45+
}
46+
}
47+
```
48+
49+
== Java
50+
51+
```java
52+
val controller = ControlSystem.builder()
53+
.posFilter(
54+
filterBuilder -> filterBuilder.custom(
55+
state -> state * 0.5
56+
)
57+
).build();
58+
```
59+
60+
:::
61+
62+
::: warning
63+
If you do not add an interpolator using the builder,
64+
you should specify the goal of the control system.
65+
The default is `KineticState(0.0, 0.0, 0.0)`.
66+
:::
67+
68+
## Using a Control System
69+
70+
To run the control system's calculations, call `calculate`,
71+
which accepts one `KineticState` argument representing the current measurement,
72+
and returns an output following the process defined earlier.
73+
74+
We can then use this output to, say, power a motor.
75+
76+
More examples on using `ControlSystem`s will be provided in the Examples section.

src/control/examples/slides.md

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# Linear Slides Example
2+
3+
Linear slides are a commonly used mechanism in FTC,
4+
and most often controlled with a positional PID feedback
5+
controller and a static feedforward term to account for gravity.
6+
7+
With NextControl, that would be implemented like this (using hypothetical constants):
8+
9+
::: tabs key:code
10+
11+
== Kotlin
12+
13+
```kotlin
14+
controlSystem {
15+
posPid(0.1, 0.0, 0.0)
16+
elevatorFF(0.04)
17+
}
18+
```
19+
20+
== Java
21+
22+
```java
23+
ControlSystem.builder()
24+
.posPid(0.1, 0.0, 0.0)
25+
.elevatorFF(0.04)
26+
.build();
27+
```
28+
29+
:::
30+
31+
## What can I do with this?
32+
33+
If you're using a command-based framework, like NextFTC,
34+
you can create commands using your control system.
35+
An example of a Linear Slides subsystem using NextControl can be found
36+
[here](../../guide/subsystems/lift.md).
37+
38+
If not, we can create OpModes that use our controllers directly.
39+
For example, lets say we wanted to change the target of our slides using a button press.
40+
We can easily do that by simply changing the `goal` of our ControlSystem:
41+
42+
::: tabs key:code
43+
44+
== Kotlin
45+
46+
```kotlin
47+
class SlideExample() : OpMode() {
48+
val slideMotor by lazy { hardwareMap.get(DcMotorEx.class, "slides") }
49+
val controller = controlSystem {
50+
posPid(0.1, 0.0, 0.0)
51+
elevatorFF(0.04)
52+
}
53+
54+
override fun init() {
55+
controller.goal = KineticState(0.0, 0.0, 0.0)
56+
}
57+
58+
override fun loop() {
59+
if (gamepad1.a) {
60+
controller.goal = KineticState(1000.0, 0.0, 0.0)
61+
} else if (gamepad1.b) {
62+
controller.goal = KineticState(0.0, 0.0, 0.0)
63+
} else if (gamepad1.x) {
64+
controller.goal = KineticState(500.0, 0.0, 0.0)
65+
}
66+
67+
slideMotor.power = controller.calculate(
68+
slideMotor.currentPosition,
69+
slideMotor.velocity
70+
)
71+
}
72+
}
73+
```
74+
75+
== Java
76+
77+
```java
78+
public class SlideExample extends OpMode {
79+
private DcMotorEx slideMotor;
80+
private ControlSystem controller;
81+
82+
@Override
83+
public void init() {
84+
slideMotor = hardwareMap.get(DcMotorEx.class, "slides");
85+
86+
controller = ControlSystem.builder()
87+
.posPid(0.1, 0.0, 0.0)
88+
.elevatorFF(0.04)
89+
.build();
90+
91+
controller.goal = new KineticState(0.0, 0.0, 0.0);
92+
}
93+
94+
@Override
95+
public void loop() {
96+
if (gamepad1.a) {
97+
controller.goal = new KineticState(1000.0, 0.0, 0.0);
98+
} else if (gamepad1.b) {
99+
controller.goal = new KineticState(0.0, 0.0, 0.0);
100+
} else if (gamepad1.x) {
101+
controller.goal = new KineticState(500.0, 0.0, 0.0);
102+
}
103+
104+
slideMotor.setPower(controller.calculate(
105+
slideMotor.getCurrentPosition(),
106+
slideMotor.getVelocity()
107+
));
108+
}
109+
}
110+
```
111+

src/control/index.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Control
2+
3+
NextControl is our robust control library that uses the "Four Elements"
4+
of control systems to model actuated systems.
5+
6+
Some examples are featured in the [examples folder](/control/examples],
7+
and all components have thorough javadoc/kdoc documentation.
8+
9+
## The Four Elements
10+
These four elements make up a Control System. Not all are required, of course.
11+
- **Feedback elements** provide feedback (closed-loop) control for your system.
12+
For example, PID Control, SquID
13+
Control, and
14+
Bang-Bang Control.
15+
- **Feedforward elements** provide feedforward (open-loop) control. NextControl
16+
has three feedforward controllers:
17+
basic, elevator, and arm.
18+
- **Filter elements** filter your sensor measurements to remove noise. Examples
19+
are low-pass filters and Kalman filters.
20+
- **Interpolator elements** interpolate the setpoint in order to smooth out
21+
setpoint changes.
22+
For example, a trapezoidal motion profile or a moving-average setpoint filter.
23+
24+
25+
The control system calculation process involves:
26+
1. Filtering sensor measurements
27+
2. Obtaining the current reference from the interpolator
28+
3. Calculating feedback component based on error
29+
4. Calculating feedforward component based on reference
30+
5. Returning the sum of feedback and feedforward
31+

src/control/kineticstates.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# KineticStates
2+
3+
A `KineticState` is simply a structure for storing the one-dimensional motion states of a system at a given point in time.
4+
It contains a `position`, a `velocity`, and an `acceleration`, and works for whatever unit you provide:
5+
if `position` is given in inches, `velocity` should be given in inches per second,
6+
and `acceleration` should be given in inches per second squared.
7+
8+
`KineticState`s can be added or subtracted componentwise, or multiplied by a scalar quantity.

0 commit comments

Comments
 (0)