Skip to content

Commit

Permalink
Change to use 1d array in traj file samples (#732)
Browse files Browse the repository at this point in the history
  • Loading branch information
shueja committed Sep 17, 2024
1 parent 9961f1a commit 2adf923
Show file tree
Hide file tree
Showing 9 changed files with 56 additions and 58 deletions.
14 changes: 3 additions & 11 deletions src-core/src/generation/transformers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ fn postprocess(result: &[Sample], mut path: TrajFile, counts_vec: Vec<usize>) ->
let total_intervals = interval;
interval += pt.1.intervals;
(
pt.1.split || pt.0 == 0 || pt.0 == snapshot.waypoints.len() - 1,
pt.1.split && !(pt.0 == 0 || pt.0 == snapshot.waypoints.len() - 1),
total_intervals,
result.get(total_intervals).map_or(0.0, |s| match s {
Sample::Swerve { t, .. } => *t,
Expand All @@ -252,16 +252,8 @@ fn postprocess(result: &[Sample], mut path: TrajFile, counts_vec: Vec<usize>) ->
.filter(|a| a.0) // filter by split flag
.map(|a| a.1) // map to associate interval
.collect::<Vec<usize>>();
path.traj.samples = splits
.windows(2) // get adjacent pairs of interval counts
.filter_map(|window| {
result
// grab the range including both endpoints,
// there are no bounds checks on this slice so be weary of crashes
.get((window[0])..=(window[1]))
.map(|slice| slice.to_vec())
})
.collect::<Vec<Vec<Sample>>>();
path.traj.splits = splits;
path.traj.samples = result.to_vec();
path.traj.waypoints = waypoint_times;
path.snapshot = Some(snapshot);
path
Expand Down
6 changes: 5 additions & 1 deletion src-core/src/spec/traj.rs
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,11 @@ pub struct Trajectory {
/// The times at which the robot will reach each waypoint.
pub waypoints: Vec<f64>,
/// The samples of the trajectory.
pub samples: Vec<Vec<Sample>>,
pub samples: Vec<Sample>,
/// The indices of samples which are associated with split waypoints.
/// First and last samples are never in this list even if the split toggle is set
/// for first or last waypoints
pub splits: Vec<usize>,
/// Whether the forces are available to use in the samples.
#[serde(default)]
pub forces_available: bool,
Expand Down
4 changes: 2 additions & 2 deletions src/components/config/robotconfig/PathGradient.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export type PathGradientArgs<S extends SwerveSample | DifferentialSample> = {
point: S;
prev: S;
next: S;
arr: S[][];
arr: S[];
total: number;
count: number;
sect: number;
Expand Down Expand Up @@ -188,7 +188,7 @@ class PathGradientFunctions {
* @returns The color gradient in HSL format.
*/
static splitTrajectories({ arr, sect: i }: PathGradientArgs<any>): string {
if (arr.length < 2) {
if (i == 0) {
return "var(--select-yellow)";
}

Expand Down
2 changes: 1 addition & 1 deletion src/components/field/svg/FieldGeneratedLines.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ function FieldGeneratedLines() {
prev: arr[i - 1],
next: arr[i + 1],
arr: path.ui.generating
? [path.ui.generationProgress]
? path.ui.generationProgress
: path.traj.samples,
total: arr.length,
count: i,
Expand Down
3 changes: 2 additions & 1 deletion src/document/2025/v2025_0_0.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,8 @@ export interface ChoreoPath<T extends ExprOrNumber> {
export type SampleType = "Swerve" | "Differential";
export interface Output {
waypoints: number[];
samples: SwerveSample[][] | DifferentialSample[][];
samples: SwerveSample[] | DifferentialSample[];
splits: number[];
forcesAvailable: boolean;
}

Expand Down
1 change: 1 addition & 0 deletions src/document/DocumentModel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ export const DocumentStore = types
self.history.startGroup(() => {
const newTraj = result.traj.samples;
pathStore.traj.setSamples(newTraj);
pathStore.traj.setSplits(result.traj.splits);
pathStore.traj.setWaypoints(result.traj.waypoints);

pathStore.setSnapshot(result.snapshot);
Expand Down
22 changes: 13 additions & 9 deletions src/document/EventMarkerStore.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ export const CommandStore = types
self.commands.push(newCommand);
return undefined;
},
pushCommand(subcommand: ICommandStore) {
pushCommand(subcommand: IAnyType) {
self.commands.push(subcommand);
},
detachCommand(index: number) {
Expand Down Expand Up @@ -228,15 +228,19 @@ export const EventMarkerStore = types
} else if (self.offset.value == 0) {
return true;
} else {
const splitTimes = path.traj.samples.map((sect) => sect[0]?.t);
splitTimes.forEach((stopTimestamp) => {
if (
(targetTimestamp < stopTimestamp && timestamp > stopTimestamp) ||
(targetTimestamp > stopTimestamp && timestamp < stopTimestamp)
) {
retVal = false;
const splitTimes = path.traj.splits.map(
(idx) => path.traj.samples[idx]?.t
);
[0, ...splitTimes, path.traj.getTotalTimeSeconds()].forEach(
(stopTimestamp) => {
if (
(targetTimestamp < stopTimestamp && timestamp > stopTimestamp) ||
(targetTimestamp > stopTimestamp && timestamp < stopTimestamp)
) {
retVal = false;
}
}
});
);
}
return retVal;
}
Expand Down
2 changes: 2 additions & 0 deletions src/document/PathListStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export const PathListStore = types
traj: {
waypoints: [],
samples: [],
splits: [],
markers: []
}
})
Expand Down Expand Up @@ -108,6 +109,7 @@ export const PathListStore = types
traj: {
waypoints: [],
samples: [],
splits: [],
markers: []
}
});
Expand Down
60 changes: 27 additions & 33 deletions src/document/path/ChoreoTrajStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,20 @@ import { EventMarkerStore, IEventMarkerStore } from "../EventMarkerStore";
export const ChoreoTrajStore = types
.model("ChoreoTrajStore", {
waypoints: types.frozen<number[]>(),
samples: types.frozen<SwerveSample[][] | DifferentialSample[][]>(),
samples: types.frozen<SwerveSample[] | DifferentialSample[]>(),
splits: types.frozen<number[]>(),
forcesAvailable: false,
markers: types.array(EventMarkerStore)
})
.views((self) => ({
get fullTraj(): SwerveSample[] | DifferentialSample[] {
//@ts-expect-error This might be a TS bug, flatMap on an A[] | B[] returns an (A | B)[]
return self.samples.flatMap((sect, i, _samp) => {
if (i != 0) {
return sect.slice(1);
}
return sect;
});
return self.samples;
},
get isSwerve(): boolean {
return (
this.fullTraj.length === 0 || Object.hasOwn(this.fullTraj[0], "vx")
);
return self.samples.length === 0 || Object.hasOwn(self.samples[0], "vx");
},
get isDifferential(): boolean {
return (
this.fullTraj.length === 0 || Object.hasOwn(this.fullTraj[0], "vl")
);
return self.samples.length === 0 || Object.hasOwn(self.samples[0], "vl");
},
// 01234567
// ...
Expand All @@ -50,45 +41,45 @@ export const ChoreoTrajStore = types
if (self.samples.length === 0) {
return undefined;
}
let sect = 0;
while (
self.samples[sect] !== undefined &&
self.samples[sect].length <= indexRemaining + 1
) {
indexRemaining -= self.samples[sect].length - 1;
sect++;
if (self.splits.length === 0) {
return [0, indexRemaining];
}
let sect = 0;
// intentionally goes past valid index
for (; sect <= self.splits.length; sect++) {
const prevSplit = self.splits[sect - 1] ?? 0;
if (prevSplit <= indexRemaining) {
const nextSplit = self.splits[sect];

if (self.samples[sect] === undefined) {
return undefined;
} else {
// indexRemaining calculates the number of elements in the last section before and include the target
// but we need the index within that section
return [sect, indexRemaining];
if (nextSplit === undefined || nextSplit > indexRemaining) {
return [sect, indexRemaining - prevSplit];
}
}
}
return [0, indexRemaining];
},
getTotalTimeSeconds(): number {
if (self.samples.length === 0) {
return 0;
}
const lastSection = self.samples[self.samples.length - 1];
if (lastSection.length === 0) {
return 0;
}
return lastSection[lastSection.length - 1].t;
const last = self.samples[self.samples.length - 1];
return last.t;
},
get serialize(): Output {
return {
waypoints: self.waypoints,
samples: self.samples,
splits: self.splits,
forcesAvailable: self.forcesAvailable
};
}
}))
.actions((self) => ({
deserialize(ser: Output) {
self.waypoints = ser.waypoints;
self.splits = ser.splits;
self.samples = ser.samples;

self.forcesAvailable = ser.forcesAvailable;
},
deleteMarkerUUID(uuid: string) {
Expand Down Expand Up @@ -123,9 +114,12 @@ export const ChoreoTrajStore = types
self.markers.push(marker as IEventMarkerStore);
return marker;
},
setSamples(samples: SwerveSample[][] | DifferentialSample[][]) {
setSamples(samples: SwerveSample[] | DifferentialSample[]) {
self.samples = samples;
},
setSplits(splits: number[]) {
self.splits = splits;
},
setWaypoints(waypoints: number[]) {
self.waypoints = waypoints;
},
Expand Down

0 comments on commit 2adf923

Please sign in to comment.