Skip to content

[WIP] new bound state objects #7

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: Sussex
Choose a base branch
from
Open
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
180 changes: 180 additions & 0 deletions src/main/java/lib2202/nt/NtBind.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.

package lib2202.nt;

import java.lang.reflect.Field;
import java.util.LinkedList;
import java.util.function.Consumer;
import java.util.function.Supplier;

import edu.wpi.first.networktables.NetworkTable;
import edu.wpi.first.networktables.NetworkTableInstance;
import edu.wpi.first.wpilibj2.command.SubsystemBase;

public class NtBind extends SubsystemBase {
NetworkTable table = NetworkTableInstance.getDefault().getTable("root");
int count;

interface apply {
Boolean apply();
}

public apply buildDoubleInput(NtBind ntBind, NetworkTable table, String name, Field f, Object state) {
var a = new doubleApply();
var nt = table.getEntry(name);

a.current = () -> {
try {
return f.getDouble(state);
} catch (Exception e) {
ntBind.ReportError(table.getPath(), name, e);
return 0.0;
}
};

a.set = (Double val) -> {
try {
f.setDouble(state, val);
} catch (Exception e) {
ntBind.ReportError(table.getPath(), name, e);
}
};

a.next = () -> nt.getDouble(a.current.get());

return a;
}


public apply buildDoubleOutput(NtBind ntBind, NetworkTable table, String name, Field f, Object state) {
var a = new doubleApply();
var nt = table.getEntry(name);

a.current = () -> nt.getDouble(0.0);
a.set = (Double val) -> nt.setDouble(val);
a.next = () -> {
try {
return f.getDouble(state);
} catch (Exception e) {
ntBind.ReportError(table.getPath(), name, e);
return 0.0;
}
};

return a;
}

class doubleApply implements apply {
Supplier<Double> current;
Consumer<Double> set;
Supplier<Double> next;

public Boolean apply() {
var next = this.next.get();
var current = this.current.get();

if (next != current) {
set.accept(next);
return true;
}

return false;
}
}

class boundData implements apply {
LinkedList<apply> applys = new LinkedList<apply>();
Runnable onChange;

public Boolean apply() {
Boolean isChanged = false;

for (var a : applys) {
isChanged |= a.apply();
}

if (isChanged && onChange != null) {
onChange.run();
}

return isChanged;
}
}

LinkedList<boundData> boundObjects = new LinkedList<boundData>();

public <TStateObject> TStateObject bind(TStateObject state, String name, Runnable onChange) {
var classFields = state.getClass().getFields();
var data = new boundData();
var sub = table.getSubTable(name);

for (var field : classFields) {
for (var annotation : field.getAnnotations()) {

if (annotation instanceof NtInput) {
var ntInput = (NtInput) annotation;

// figure out we should call it
var entryName = ntInput.name();
if (entryName == "") {
entryName = field.getName();
}

if (field.getType().equals(double.class)) {
data.applys.add(buildDoubleInput(this, sub, entryName, field, state));
}
}

if (annotation instanceof NtOutput) {
var ntOutput = (NtOutput) annotation;

// figure out we should call it
var entryName = ntOutput.name();
if (entryName == "") {
entryName = field.getName();
}

if (field.getType().equals(double.class)) {
data.applys.add(buildDoubleOutput(this, sub, entryName, field, state));
}
}
}
}

boundObjects.add(data);
return state;
}

public void ReportError(String table, String name, Exception e) {
// todo: real comments and reporting and something
}

private static NtBind instance;

public static NtBind getInstance() {
if (instance == null) {
instance = new NtBind();
}

return instance;
}

/** Creates a new NtBind. */
public NtBind() {
}

@Override
public void periodic() {
count++;
if (count > 10) {
count = 0;

for (var data : boundObjects) {
data.apply();
}
}
// This method will be called once per scheduler run
}
}
17 changes: 17 additions & 0 deletions src/main/java/lib2202/nt/NtInput.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.

package lib2202.nt;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;

/** Add your docs here. */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface NtInput {
String name() default "";
}
17 changes: 17 additions & 0 deletions src/main/java/lib2202/nt/NtOutput.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.

package lib2202.nt;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;

/** Add your docs here. */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface NtOutput {
String name() default "";
}
28 changes: 28 additions & 0 deletions src/main/java/lib2202/nt/examples/DoubleInput.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package lib2202.nt.examples;


import lib2202.nt.NtInput;
import lib2202.nt.NtOutput;
import lib2202.nt.NtBind;

public class DoubleInput {
class State {

@NtInput(name = "set")
public double SetPoint = 0;

@NtOutput(name = "err")
public double Error = 0;

// @NtInput()
}

State left = NtBind.getInstance().bind(new State(), "left", this::onChanged);
State right = NtBind.getInstance().bind(new State(), "right", this::onChanged);

void onChanged() {
System.out.println("SetPoint: " + left.SetPoint + ", err: " + left.Error);
System.out.println("SetPoint: " + right.SetPoint + ", err: " + right.Error);
}

}