diff --git a/src-core/src/spec/mod.rs b/src-core/src/spec/mod.rs index 1a1c7ee9a..317a0725e 100644 --- a/src-core/src/spec/mod.rs +++ b/src-core/src/spec/mod.rs @@ -14,17 +14,21 @@ pub struct OpenFilePayload { /// A trait for types that can be snapshotted. /// This allows for the type to be converted to a f64. /// This trait is only implemented for [`f64`] and [`Expr`]. -pub trait SnapshottableType: Debug + Clone { - fn snapshot(&self) -> f64; +pub trait ExprOrNumber: Debug + Clone { + fn as_number(&self) -> f64; } -impl SnapshottableType for f64 { +impl ExprOrNumber for f64 { #[inline] - fn snapshot(&self) -> f64 { + fn as_number(&self) -> f64 { *self } } +/// A struct that represents an expression. +/// +/// The string is a mathematical expression that can be evaluated to a number. +/// The number is the result of evaluating the expression. #[derive(Debug, Serialize, Deserialize, Clone)] pub struct Expr(pub String, pub f64); impl Expr { @@ -33,9 +37,9 @@ impl Expr { Self(name.to_string(), value) } } -impl SnapshottableType for Expr { +impl ExprOrNumber for Expr { #[inline] - fn snapshot(&self) -> f64 { + fn as_number(&self) -> f64 { self.1 } } diff --git a/src-core/src/spec/project.rs b/src-core/src/spec/project.rs index f0d36c117..07f9e5fe8 100644 --- a/src-core/src/spec/project.rs +++ b/src-core/src/spec/project.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; use serde::{Deserialize, Serialize}; use trajoptlib::Translation2d; -use super::{traj::DriveType, Expr, SnapshottableType}; +use super::{traj::DriveType, Expr, ExprOrNumber}; #[derive(Debug, Serialize, Deserialize, Clone, Copy)] pub enum Dimension { @@ -36,34 +36,34 @@ pub struct Variables { pub poses: HashMap, } #[derive(Debug, Serialize, Deserialize, Clone, Copy)] -pub struct Bumper { +pub struct Bumper { pub front: T, pub left: T, pub back: T, pub right: T, } -impl Bumper { +impl Bumper { pub fn snapshot(&self) -> Bumper { Bumper { - front: self.front.snapshot(), - left: self.left.snapshot(), - back: self.back.snapshot(), - right: self.right.snapshot(), + front: self.front.as_number(), + left: self.left.as_number(), + back: self.back.as_number(), + right: self.right.as_number(), } } } #[derive(Debug, Serialize, Deserialize, Clone, Copy)] -pub struct Module { +pub struct Module { pub x: T, pub y: T, } -impl Module { +impl Module { pub fn snapshot(&self) -> Module { Module { - x: self.x.snapshot(), - y: self.y.snapshot(), + x: self.x.as_number(), + y: self.y.as_number(), } } } @@ -77,7 +77,7 @@ impl Module { } } #[derive(Debug, Serialize, Deserialize, Clone, Copy)] -pub struct RobotConfig { +pub struct RobotConfig { pub modules: [Module; 4], pub mass: T, pub inertia: T, @@ -90,26 +90,26 @@ pub struct RobotConfig { pub bumper: Bumper, } -impl RobotConfig { +impl RobotConfig { pub fn snapshot(&self) -> RobotConfig { RobotConfig { modules: self.modules.clone().map(|modu: Module| modu.snapshot()), - mass: self.mass.snapshot(), - inertia: self.inertia.snapshot(), - gearing: self.gearing.snapshot(), - radius: self.radius.snapshot(), - vmax: self.vmax.snapshot(), - tmax: self.tmax.snapshot(), + mass: self.mass.as_number(), + inertia: self.inertia.as_number(), + gearing: self.gearing.as_number(), + radius: self.radius.as_number(), + vmax: self.vmax.as_number(), + tmax: self.tmax.as_number(), bumper: self.bumper.snapshot(), } } } -impl RobotConfig { +impl RobotConfig { pub fn wheel_max_torque(&self) -> f64 { - self.tmax.snapshot() * self.gearing.snapshot() + self.tmax.as_number() * self.gearing.as_number() } pub fn wheel_max_velocity(&self) -> f64 { - self.vmax.snapshot() / self.gearing.snapshot() + self.vmax.as_number() / self.gearing.as_number() } } diff --git a/src-core/src/spec/traj.rs b/src-core/src/spec/traj.rs index c1342c915..ccd66c16f 100644 --- a/src-core/src/spec/traj.rs +++ b/src-core/src/spec/traj.rs @@ -1,12 +1,12 @@ use serde::{Deserialize, Serialize}; use trajoptlib::{DifferentialTrajectorySample, SwerveTrajectorySample}; -use super::{Expr, SnapshottableType}; +use super::{Expr, ExprOrNumber}; #[derive(Serialize, Deserialize, Clone, Copy, Debug)] #[serde(rename_all = "camelCase")] /// A waypoint parameter. -pub struct Waypoint { +pub struct Waypoint { /// The x coordinate of the waypoint (blue origin). /// /// Units: meters @@ -36,12 +36,12 @@ pub struct Waypoint { } #[allow(missing_docs)] -impl Waypoint { +impl Waypoint { pub fn snapshot(&self) -> Waypoint { Waypoint { - x: self.x.snapshot(), - y: self.y.snapshot(), - heading: self.heading.snapshot(), + x: self.x.as_number(), + y: self.y.as_number(), + heading: self.heading.as_number(), intervals: self.intervals, split: self.split, fix_translation: self.fix_translation, @@ -108,7 +108,7 @@ pub enum ConstraintScope { /// A constraint on the robot's motion. #[derive(Serialize, Deserialize, Clone, Copy, Debug)] #[serde(tag = "type", content = "props")] -pub enum ConstraintData { +pub enum ConstraintData { /// A constraint on the maximum velocity. MaxVelocity { /// The maximum velocity. @@ -149,7 +149,7 @@ pub enum ConstraintData { KeepInRectangle { x: T, y: T, w: T, h: T }, } -impl ConstraintData { +impl ConstraintData { /// The scope of the constraint. pub fn scope(&self) -> ConstraintScope { match self { @@ -162,10 +162,10 @@ impl ConstraintData { pub fn snapshot(&self) -> ConstraintData { match self { ConstraintData::MaxVelocity { max } => ConstraintData::MaxVelocity { - max: max.snapshot(), + max: max.as_number(), }, ConstraintData::MaxAngularVelocity { max } => ConstraintData::MaxAngularVelocity { - max: max.snapshot(), + max: max.as_number(), }, ConstraintData::PointAt { x, @@ -173,25 +173,25 @@ impl ConstraintData { tolerance, flip, } => ConstraintData::PointAt { - x: x.snapshot(), - y: y.snapshot(), - tolerance: tolerance.snapshot(), + x: x.as_number(), + y: y.as_number(), + tolerance: tolerance.as_number(), flip: *flip, }, ConstraintData::MaxAcceleration { max } => ConstraintData::MaxAcceleration { - max: max.snapshot(), + max: max.as_number(), }, ConstraintData::StopPoint {} => ConstraintData::StopPoint {}, ConstraintData::KeepInCircle { x, y, r } => ConstraintData::KeepInCircle { - x: x.snapshot(), - y: y.snapshot(), - r: r.snapshot(), + x: x.as_number(), + y: y.as_number(), + r: r.as_number(), }, ConstraintData::KeepInRectangle { x, y, w, h } => ConstraintData::KeepInRectangle { - x: x.snapshot(), - y: y.snapshot(), - w: w.snapshot(), - h: h.snapshot(), + x: x.as_number(), + y: y.as_number(), + w: w.as_number(), + h: h.as_number(), }, } } @@ -199,7 +199,7 @@ impl ConstraintData { /// A constraint on the robot's motion and where it applies. #[derive(Debug, Clone, Copy, Serialize, Deserialize)] -pub struct Constraint { +pub struct Constraint { /// The waypoint the constraint starts at. pub from: WaypointID, /// The waypoint the constraint ends at. @@ -210,7 +210,7 @@ pub struct Constraint { pub data: ConstraintData, } -impl Constraint { +impl Constraint { #[allow(missing_docs)] pub fn snapshot(&self) -> Constraint { Constraint:: { @@ -223,7 +223,7 @@ impl Constraint { /// A constraint on the robot's motion and where it applies. #[derive(Debug, Clone, Copy, Serialize, Deserialize)] -pub struct ConstraintIDX { +pub struct ConstraintIDX { /// The index of the waypoint the constraint starts at. pub from: usize, /// The index of the waypoint the constraint ends at. @@ -344,14 +344,14 @@ pub enum DriveType { /// The parameters used for generating a trajectory. #[derive(Serialize, Deserialize, Clone, Debug)] -pub struct Parameters { +pub struct Parameters { /// The waypoints the robot will pass through or use for initial guess. pub waypoints: Vec>, /// The constraints on the robot's motion. pub constraints: Vec>, } -impl Parameters { +impl Parameters { #[allow(missing_docs)] pub fn snapshot(&self) -> Parameters { Parameters { @@ -388,6 +388,14 @@ pub struct TrajFile { pub params: Parameters, /// The trajectory the robot will follow. pub traj: Trajectory, + /// The choreo events. + #[serde(default)] + pub events: Vec, + /// The pplib commands to execute. + /// This is a compatibility layer for working with + /// the path planner library. + #[serde(default)] + pub pplib_commands: Vec, } impl TrajFile { @@ -402,3 +410,34 @@ impl TrajFile { serde_json::from_str(content).map_err(Into::into) } } + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PplibCommandMarker { + pub name: String, + pub target: Option, + pub traj_target_index: Option, + pub target_timestamp: Option, + pub offset: f64, + pub command: PplibCommand, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase", tag = "type", content = "data")] +pub enum PplibCommand { + Named { name: String }, + Wait { wait_time: f64 }, + Sequential { commands: Vec }, + Parallel { commands: Vec }, + Race { commands: Vec }, + Deadline { commands: Vec }, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct EventMarker { + /// The name of the event. + pub event: String, + /// The offset from the beginning of the trajectory. + pub timestamp: f64, +} diff --git a/src/AppMenu.tsx b/src/AppMenu.tsx index 32f62b56a..9999d6b90 100644 --- a/src/AppMenu.tsx +++ b/src/AppMenu.tsx @@ -31,7 +31,7 @@ import { } from "./document/DocumentManager"; import SettingsModal from "./components/config/SettingsModal"; -import { Commands } from "./document/tauriCommands"; +import { Commands } from "./document/Backend"; import { version } from "./util/version"; type Props = object; diff --git a/src/components/config/CircularObstacleConfigPanel.tsx b/src/components/config/CircularObstacleConfigPanel.tsx index 5d1e69b7c..a0b5a29d0 100644 --- a/src/components/config/CircularObstacleConfigPanel.tsx +++ b/src/components/config/CircularObstacleConfigPanel.tsx @@ -1,7 +1,7 @@ import { observer } from "mobx-react"; import { Component } from "react"; import styles from "./WaypointConfigPanel.module.css"; -import { ICircularObstacleStore } from "../../document/CircularObstacleStore"; +import { ICircularObstacleStore } from "../../document/stores/CircularObstacleStore"; import ExpressionInput from "../input/ExpressionInput"; import ExpressionInputList from "../input/ExpressionInputList"; diff --git a/src/components/config/ConstraintsConfigPanel.tsx b/src/components/config/ConstraintsConfigPanel.tsx index 6d8efa9cf..be52ec203 100644 --- a/src/components/config/ConstraintsConfigPanel.tsx +++ b/src/components/config/ConstraintsConfigPanel.tsx @@ -1,6 +1,6 @@ import { observer } from "mobx-react"; import { Component } from "react"; -import { IConstraintStore } from "../../document/ConstraintStore"; +import { IConstraintStore } from "../../document/stores//ConstraintStore"; import BooleanInput from "../input/BooleanInput"; import ExpressionInput from "../input/ExpressionInput"; import ExpressionInputList from "../input/ExpressionInputList"; diff --git a/src/components/config/ScopeSlider.tsx b/src/components/config/ScopeSlider.tsx index c0adf3ed2..80d9cb316 100644 --- a/src/components/config/ScopeSlider.tsx +++ b/src/components/config/ScopeSlider.tsx @@ -1,7 +1,7 @@ import { Slider, SliderProps } from "@mui/material"; import { observer } from "mobx-react"; import { Component } from "react"; -import { IHolonomicWaypointStore } from "../../document/HolonomicWaypointStore"; +import { IHolonomicWaypointStore } from "../../document/stores/HolonomicWaypointStore"; type Props = { isRange: boolean; diff --git a/src/components/config/WaypointConfigPanel.tsx b/src/components/config/WaypointConfigPanel.tsx index 39e3727d4..5d5c92fd8 100644 --- a/src/components/config/WaypointConfigPanel.tsx +++ b/src/components/config/WaypointConfigPanel.tsx @@ -1,7 +1,7 @@ import { ToggleButton, ToggleButtonGroup, Tooltip } from "@mui/material"; import { observer } from "mobx-react"; import { Component, ReactElement } from "react"; -import { IHolonomicWaypointStore } from "../../document/HolonomicWaypointStore"; +import { IHolonomicWaypointStore } from "../../document/stores/HolonomicWaypointStore"; import { WaypointData } from "../../document/UIData"; import BooleanInput from "../input/BooleanInput"; import ExpressionInput from "../input/ExpressionInput"; diff --git a/src/components/config/eventmarker/CommandDraggable.tsx b/src/components/config/eventmarker/CommandDraggable.tsx index 85b0e8369..402065039 100644 --- a/src/components/config/eventmarker/CommandDraggable.tsx +++ b/src/components/config/eventmarker/CommandDraggable.tsx @@ -13,7 +13,7 @@ import { CommandType, CommandUIData, ICommandStore -} from "../../../document/EventMarkerStore"; +} from "../../../document/stores/PplibCommandMarkerStore"; import ExpressionInput from "../../input/ExpressionInput"; import ExpressionInputList from "../../input/ExpressionInputList"; diff --git a/src/components/config/eventmarker/EventMarkerConfigPanel.tsx b/src/components/config/eventmarker/EventMarkerConfigPanel.tsx index 8cf199cb6..fc95f59c9 100644 --- a/src/components/config/eventmarker/EventMarkerConfigPanel.tsx +++ b/src/components/config/eventmarker/EventMarkerConfigPanel.tsx @@ -6,7 +6,7 @@ import { DragDropContext } from "@hello-pangea/dnd"; import { CommandStore, IEventMarkerStore -} from "../../../document/EventMarkerStore"; +} from "../../../document/stores/PplibCommandMarkerStore"; import ExpressionInput from "../../input/ExpressionInput"; import ExpressionInputList from "../../input/ExpressionInputList"; import InputStyles from "../../input/InputList.module.css"; diff --git a/src/components/config/robotconfig/PathGradient.tsx b/src/components/config/robotconfig/PathGradient.tsx index d7c4a953f..0a9e754c1 100644 --- a/src/components/config/robotconfig/PathGradient.tsx +++ b/src/components/config/robotconfig/PathGradient.tsx @@ -1,8 +1,5 @@ -import { - DifferentialSample, - SwerveSample -} from "../../../document/2025/DocumentTypes"; import { IDocumentStore } from "../../../document/DocumentModel"; +import { DifferentialSample, SwerveSample } from "../../../document/spec/Traj"; /** * Represents a path gradient. diff --git a/src/components/config/variables/PoseVariablesConfigPanel.tsx b/src/components/config/variables/PoseVariablesConfigPanel.tsx index a2468daf8..1229a5db7 100644 --- a/src/components/config/variables/PoseVariablesConfigPanel.tsx +++ b/src/components/config/variables/PoseVariablesConfigPanel.tsx @@ -3,7 +3,10 @@ import { Tooltip } from "@mui/material"; import { observer } from "mobx-react"; import { useState } from "react"; import { doc } from "../../../document/DocumentManager"; -import { DimensionsExt, IExprPose } from "../../../document/ExpressionStore"; +import { + DimensionsExt, + IExprPose +} from "../../../document/stores/ExpressionStore"; import ExpressionInput from "../../input/ExpressionInput"; import VariableRenamingInput from "./VariableRenamingInput"; diff --git a/src/components/config/variables/VariablesConfigPanel.tsx b/src/components/config/variables/VariablesConfigPanel.tsx index ca01ae609..48c5ea5fc 100644 --- a/src/components/config/variables/VariablesConfigPanel.tsx +++ b/src/components/config/variables/VariablesConfigPanel.tsx @@ -9,7 +9,7 @@ import { DimensionNamesExt, DimensionsExt, IExpressionStore -} from "../../../document/ExpressionStore"; +} from "../../../document/stores/ExpressionStore"; import ExpressionInput from "../../input/ExpressionInput"; import { AddPoseVariablePanel } from "./PoseVariablesConfigPanel"; import VariableRenamingInput from "./VariableRenamingInput"; diff --git a/src/components/field/Field.tsx b/src/components/field/Field.tsx index 5f7bb8794..ea946004d 100644 --- a/src/components/field/Field.tsx +++ b/src/components/field/Field.tsx @@ -12,11 +12,11 @@ import { CircularProgress, Tooltip } from "@mui/material"; import Box from "@mui/material/Box/Box"; import IconButton from "@mui/material/IconButton"; import "react-toastify/dist/ReactToastify.min.css"; -import { ICircularObstacleStore } from "../../document/CircularObstacleStore"; -import { IConstraintStore } from "../../document/ConstraintStore"; -import { IEventMarkerStore } from "../../document/EventMarkerStore"; -import { IHolonomicWaypointStore } from "../../document/HolonomicWaypointStore"; -import { Commands } from "../../document/tauriCommands"; +import { ICircularObstacleStore } from "../../document/stores/CircularObstacleStore"; +import { IConstraintStore } from "../../document/stores//ConstraintStore"; +import { IEventMarkerStore } from "../../document/stores/PplibCommandMarkerStore"; +import { IHolonomicWaypointStore } from "../../document/stores/HolonomicWaypointStore"; +import { Commands } from "../../document/Backend"; import CircularObstacleConfigPanel from "../config/CircularObstacleConfigPanel"; import ConstraintsConfigPanel from "../config/ConstraintsConfigPanel"; import ViewOptionsPanel from "../config/ViewOptionsPanel"; diff --git a/src/components/field/PathAnimationSlider.tsx b/src/components/field/PathAnimationSlider.tsx index 9c46c1f20..09972a730 100644 --- a/src/components/field/PathAnimationSlider.tsx +++ b/src/components/field/PathAnimationSlider.tsx @@ -5,7 +5,7 @@ import Slider from "@mui/material/Slider"; import { Tooltip } from "@mui/material"; import { NavbarItemData } from "../../document/UIData"; import { Room } from "@mui/icons-material"; -import { IEventMarkerStore } from "../../document/EventMarkerStore"; +import { IEventMarkerStore } from "../../document/stores/PplibCommandMarkerStore"; type Props = object; diff --git a/src/components/field/svg/FieldObstacles.tsx b/src/components/field/svg/FieldObstacles.tsx index 0b0195b1b..a44e173c4 100644 --- a/src/components/field/svg/FieldObstacles.tsx +++ b/src/components/field/svg/FieldObstacles.tsx @@ -1,7 +1,7 @@ import * as d3 from "d3"; import { observer } from "mobx-react"; import React, { Component } from "react"; -import { ICircularObstacleStore } from "../../../document/CircularObstacleStore"; +import { ICircularObstacleStore } from "../../../document/stores/CircularObstacleStore"; import { doc, select } from "../../../document/DocumentManager"; type Props = { obstacle: ICircularObstacleStore; index: number }; diff --git a/src/components/field/svg/FieldOverlayRoot.tsx b/src/components/field/svg/FieldOverlayRoot.tsx index 7faed49be..f62635ef3 100644 --- a/src/components/field/svg/FieldOverlayRoot.tsx +++ b/src/components/field/svg/FieldOverlayRoot.tsx @@ -7,9 +7,8 @@ import { import * as d3 from "d3"; import { observer } from "mobx-react"; import React, { Component } from "react"; -import { Expr, Waypoint } from "../../../document/2025/DocumentTypes"; import { ConstraintKey } from "../../../document/ConstraintDefinitions"; -import { IConstraintStoreKeyed } from "../../../document/ConstraintStore"; +import { IConstraintStoreKeyed } from "../../../document/stores//ConstraintStore"; import { doc, uiState } from "../../../document/DocumentManager"; import { NavbarItemData, @@ -32,6 +31,8 @@ import OverlayWaypoint from "./OverlayWaypoint"; import FieldConstraintAddLayer from "./constraintDisplay/FieldConstraintAddLayer"; import FieldConstraintDisplayLayer from "./constraintDisplay/FieldConstraintDisplayLayer"; import FieldImage2024 from "./fields/FieldImage2024"; +import { Waypoint } from "../../../document/spec/Traj"; +import { Expr } from "../../../document/spec/Misc"; type Props = object; diff --git a/src/components/field/svg/OverlayWaypoint.tsx b/src/components/field/svg/OverlayWaypoint.tsx index 7fe3d322c..a397bde0f 100644 --- a/src/components/field/svg/OverlayWaypoint.tsx +++ b/src/components/field/svg/OverlayWaypoint.tsx @@ -2,8 +2,8 @@ import * as d3 from "d3"; import { observer } from "mobx-react"; import React, { Component } from "react"; import { doc, uiState } from "../../../document/DocumentManager"; -import { IHolonomicWaypointStore } from "../../../document/HolonomicWaypointStore"; -import { IRobotConfigStore } from "../../../document/RobotConfigStore"; +import { IHolonomicWaypointStore } from "../../../document/stores/HolonomicWaypointStore"; +import { IRobotConfigStore } from "../../../document/stores/RobotConfigStore"; type Props = { waypoint: IHolonomicWaypointStore; index: number }; diff --git a/src/components/field/svg/constraintDisplay/FieldConstraintAddLayer.tsx b/src/components/field/svg/constraintDisplay/FieldConstraintAddLayer.tsx index 4a1154252..f137e993e 100644 --- a/src/components/field/svg/constraintDisplay/FieldConstraintAddLayer.tsx +++ b/src/components/field/svg/constraintDisplay/FieldConstraintAddLayer.tsx @@ -3,10 +3,10 @@ import { doc, uiState } from "../../../../document/DocumentManager"; import { ConstraintDefinitions } from "../../../../document/ConstraintDefinitions"; import { observer } from "mobx-react"; -import { IHolonomicWaypointStore } from "../../../../document/HolonomicWaypointStore"; +import { IHolonomicWaypointStore } from "../../../../document/stores/HolonomicWaypointStore"; import { FieldMatrixContext } from "../FieldMatrixContext"; import FieldConstraintRangeLayer from "./FieldConstraintRangeLayer"; -import { tracing } from "../../../../document/tauriTracing"; +import { tracing } from "../../../../util/Tracing"; type Props = { lineColor?: string; diff --git a/src/components/field/svg/constraintDisplay/FieldConstraintDisplayLayer.tsx b/src/components/field/svg/constraintDisplay/FieldConstraintDisplayLayer.tsx index d69b971f9..3cca5ceb6 100644 --- a/src/components/field/svg/constraintDisplay/FieldConstraintDisplayLayer.tsx +++ b/src/components/field/svg/constraintDisplay/FieldConstraintDisplayLayer.tsx @@ -1,6 +1,6 @@ import { observer } from "mobx-react"; import { ConstraintKey } from "../../../../document/ConstraintDefinitions"; -import { IConstraintStoreKeyed } from "../../../../document/ConstraintStore"; +import { IConstraintStoreKeyed } from "../../../../document/stores//ConstraintStore"; import { doc } from "../../../../document/DocumentManager"; import FieldConstraintRangeLayer from "./FieldConstraintRangeLayer"; import KeepInCircleOverlay from "./KeepInCircleOverlay"; diff --git a/src/components/field/svg/constraintDisplay/FieldConstraintRangeLayer.tsx b/src/components/field/svg/constraintDisplay/FieldConstraintRangeLayer.tsx index 4e54303a6..dbe7627c2 100644 --- a/src/components/field/svg/constraintDisplay/FieldConstraintRangeLayer.tsx +++ b/src/components/field/svg/constraintDisplay/FieldConstraintRangeLayer.tsx @@ -1,6 +1,6 @@ import { observer } from "mobx-react"; import { doc } from "../../../../document/DocumentManager"; -import { IHolonomicWaypointStore } from "../../../../document/HolonomicWaypointStore"; +import { IHolonomicWaypointStore } from "../../../../document/stores/HolonomicWaypointStore"; type Props = { points: IHolonomicWaypointStore[]; diff --git a/src/components/field/svg/constraintDisplay/KeepInCircleOverlay.tsx b/src/components/field/svg/constraintDisplay/KeepInCircleOverlay.tsx index 75de891a4..ca37ffe72 100644 --- a/src/components/field/svg/constraintDisplay/KeepInCircleOverlay.tsx +++ b/src/components/field/svg/constraintDisplay/KeepInCircleOverlay.tsx @@ -1,13 +1,13 @@ import * as d3 from "d3"; import { observer } from "mobx-react"; import React, { Component } from "react"; -import { IConstraintDataStore } from "../../../../document/ConstraintDataStore"; +import { IConstraintDataStore } from "../../../../document/stores/ConstraintDataStore"; import { ConstraintKey, DataMap } from "../../../../document/ConstraintDefinitions"; import { doc } from "../../../../document/DocumentManager"; -import { IHolonomicWaypointStore } from "../../../../document/HolonomicWaypointStore"; +import { IHolonomicWaypointStore } from "../../../../document/stores/HolonomicWaypointStore"; const STROKE = 0.1; const DOT = 0.1; diff --git a/src/components/field/svg/constraintDisplay/KeepInRectangleOverlay.tsx b/src/components/field/svg/constraintDisplay/KeepInRectangleOverlay.tsx index 3e6c839fa..7a91c7cef 100644 --- a/src/components/field/svg/constraintDisplay/KeepInRectangleOverlay.tsx +++ b/src/components/field/svg/constraintDisplay/KeepInRectangleOverlay.tsx @@ -1,13 +1,13 @@ import * as d3 from "d3"; import { observer } from "mobx-react"; import React, { Component } from "react"; -import { IConstraintDataStore } from "../../../../document/ConstraintDataStore"; +import { IConstraintDataStore } from "../../../../document/stores/ConstraintDataStore"; import { ConstraintKey, DataMap } from "../../../../document/ConstraintDefinitions"; import { doc } from "../../../../document/DocumentManager"; -import { IHolonomicWaypointStore } from "../../../../document/HolonomicWaypointStore"; +import { IHolonomicWaypointStore } from "../../../../document/stores/HolonomicWaypointStore"; const STROKE = 0.1; const DOT = 0.1; diff --git a/src/components/field/svg/constraintDisplay/PointAtOverlay.tsx b/src/components/field/svg/constraintDisplay/PointAtOverlay.tsx index 0829fb1d1..b4679a2fd 100644 --- a/src/components/field/svg/constraintDisplay/PointAtOverlay.tsx +++ b/src/components/field/svg/constraintDisplay/PointAtOverlay.tsx @@ -1,13 +1,13 @@ import * as d3 from "d3"; import { observer } from "mobx-react"; import React, { Component } from "react"; -import { IConstraintDataStore } from "../../../../document/ConstraintDataStore"; +import { IConstraintDataStore } from "../../../../document/stores/ConstraintDataStore"; import { ConstraintKey, DataMap } from "../../../../document/ConstraintDefinitions"; import { doc } from "../../../../document/DocumentManager"; -import { IHolonomicWaypointStore } from "../../../../document/HolonomicWaypointStore"; +import { IHolonomicWaypointStore } from "../../../../document/stores/HolonomicWaypointStore"; type Props = { data: IConstraintDataStore; diff --git a/src/components/input/ExpressionInput.tsx b/src/components/input/ExpressionInput.tsx index 69e3ea437..4708ca958 100644 --- a/src/components/input/ExpressionInput.tsx +++ b/src/components/input/ExpressionInput.tsx @@ -2,9 +2,9 @@ import { Tooltip } from "@mui/material"; import { observer } from "mobx-react"; import { isAlive } from "mobx-state-tree"; import React, { Component } from "react"; -import { IExpressionStore, math } from "../../document/ExpressionStore"; +import { IExpressionStore, math } from "../../document/stores/ExpressionStore"; import styles from "./InputList.module.css"; -import { tracing } from "../../document/tauriTracing"; +import { tracing } from "../../util/Tracing"; type Props = { /** The text to show before the number */ diff --git a/src/components/sidebar/Sidebar.tsx b/src/components/sidebar/Sidebar.tsx index 88196d641..e2f5057d1 100644 --- a/src/components/sidebar/Sidebar.tsx +++ b/src/components/sidebar/Sidebar.tsx @@ -10,9 +10,9 @@ import { ContentCopy, Redo, Undo } from "@mui/icons-material"; import Add from "@mui/icons-material/Add"; import SidebarConstraint from "./SidebarConstraint"; import SidebarObstacle from "./SidebarObstacle"; -import { ICircularObstacleStore } from "../../document/CircularObstacleStore"; +import { ICircularObstacleStore } from "../../document/stores/CircularObstacleStore"; import SidebarEventMarker from "./SidebarEventMarker"; -import { IEventMarkerStore } from "../../document/EventMarkerStore"; +import { IEventMarkerStore } from "../../document/stores/PplibCommandMarkerStore"; type Props = object; diff --git a/src/components/sidebar/SidebarConstraint.tsx b/src/components/sidebar/SidebarConstraint.tsx index 52cf1e328..8a3369fa3 100644 --- a/src/components/sidebar/SidebarConstraint.tsx +++ b/src/components/sidebar/SidebarConstraint.tsx @@ -4,12 +4,12 @@ import { observer } from "mobx-react"; import DeleteIcon from "@mui/icons-material/Delete"; import { Instance, getParent } from "mobx-state-tree"; import React, { Component } from "react"; -import { IConstraintStore } from "../../document/ConstraintStore"; +import { IConstraintStore } from "../../document/stores//ConstraintStore"; import { doc } from "../../document/DocumentManager"; import styles from "./Sidebar.module.css"; import { PriorityHigh } from "@mui/icons-material"; -import { ChoreoPathStore } from "../../document/path/ChoreoPathStore"; +import { ChoreoPathStore } from "../../document/stores/ChoreoPathStore"; import { WaypointID } from "../../document/ConstraintDefinitions"; type Props = { diff --git a/src/components/sidebar/SidebarEventMarker.tsx b/src/components/sidebar/SidebarEventMarker.tsx index 529f5fbfb..6b3bd742e 100644 --- a/src/components/sidebar/SidebarEventMarker.tsx +++ b/src/components/sidebar/SidebarEventMarker.tsx @@ -6,9 +6,9 @@ import { getParent } from "mobx-state-tree"; import React, { Component } from "react"; import { WaypointID } from "../../document/ConstraintDefinitions"; import { doc } from "../../document/DocumentManager"; -import { IEventMarkerStore } from "../../document/EventMarkerStore"; -import { IChoreoTrajStore } from "../../document/path/ChoreoTrajStore"; -import { IHolonomicPathStore } from "../../document/path/HolonomicPathStore"; +import { IEventMarkerStore } from "../../document/stores/PplibCommandMarkerStore"; +import { IChoreoTrajStore } from "../../document/stores/ChoreoTrajStore"; +import { IHolonomicPathStore } from "../../document/stores/HolonomicPathStore"; import styles from "./Sidebar.module.css"; type Props = { diff --git a/src/components/sidebar/SidebarObstacle.tsx b/src/components/sidebar/SidebarObstacle.tsx index ec1a476d2..5acaaf6ba 100644 --- a/src/components/sidebar/SidebarObstacle.tsx +++ b/src/components/sidebar/SidebarObstacle.tsx @@ -1,6 +1,6 @@ import { Component } from "react"; import React from "react"; -import { ICircularObstacleStore } from "../../document/CircularObstacleStore"; +import { ICircularObstacleStore } from "../../document/stores/CircularObstacleStore"; import { doc, uiState } from "../../document/DocumentManager"; import styles from "./Sidebar.module.css"; import { observer } from "mobx-react"; diff --git a/src/components/sidebar/SidebarWaypoint.tsx b/src/components/sidebar/SidebarWaypoint.tsx index 0d1bf4c67..7cba38e16 100644 --- a/src/components/sidebar/SidebarWaypoint.tsx +++ b/src/components/sidebar/SidebarWaypoint.tsx @@ -6,7 +6,7 @@ import { isAlive } from "mobx-state-tree"; import React, { CSSProperties, Component } from "react"; import { Draggable, DraggingStyle, NotDraggingStyle } from "@hello-pangea/dnd"; import { doc, uiState } from "../../document/DocumentManager"; -import { IHolonomicWaypointStore } from "../../document/HolonomicWaypointStore"; +import { IHolonomicWaypointStore } from "../../document/stores/HolonomicWaypointStore"; import { NavbarItemData } from "../../document/UIData"; import styles from "./Sidebar.module.css"; diff --git a/src/components/sidebar/WaypointList.tsx b/src/components/sidebar/WaypointList.tsx index 68e843907..ff95255f2 100644 --- a/src/components/sidebar/WaypointList.tsx +++ b/src/components/sidebar/WaypointList.tsx @@ -2,7 +2,7 @@ import { observer } from "mobx-react"; import { Component } from "react"; import { DragDropContext, Droppable } from "@hello-pangea/dnd"; import { doc } from "../../document/DocumentManager"; -import { IHolonomicWaypointStore } from "../../document/HolonomicWaypointStore"; +import { IHolonomicWaypointStore } from "../../document/stores/HolonomicWaypointStore"; import styles from "./Sidebar.module.css"; import SidebarWaypoint from "./SidebarWaypoint"; diff --git a/src/document/2025/DocumentTypes.ts b/src/document/2025/DocumentTypes.ts deleted file mode 100644 index c0b232cfa..000000000 --- a/src/document/2025/DocumentTypes.ts +++ /dev/null @@ -1,2 +0,0 @@ -export type * from "./v2025_0_0"; -export { SAVE_FILE_VERSION } from "./v2025_0_0"; diff --git a/src/document/tauriCommands.ts b/src/document/Backend.ts similarity index 80% rename from src/document/tauriCommands.ts rename to src/document/Backend.ts index 4dccda900..0e0df15c1 100644 --- a/src/document/tauriCommands.ts +++ b/src/document/Backend.ts @@ -1,9 +1,11 @@ import { invoke } from "@tauri-apps/api"; -import { Expr, Project, RobotConfig, Traj } from "./2025/DocumentTypes"; import { OpenFilePayload } from "./DocumentManager"; +import { ProjectFile, RobotConfig } from "./spec/Project"; +import { Expr } from "./spec/Misc"; +import { TrajFile } from "./spec/Traj"; export const Commands = { - guessIntervals: (config: RobotConfig, traj: Traj) => + guessIntervals: (config: RobotConfig, traj: TrajFile) => invoke("guess_control_interval_counts", { config, traj }), /** @@ -15,8 +17,8 @@ export const Commands = { * * @returns The generated `Traj`. */ - generate: (project: Project, traj: Traj, handle: number) => - invoke("generate_remote", { project, traj, handle }), + generate: (project: ProjectFile, traj: TrajFile, handle: number) => + invoke("generate_remote", { project, traj, handle }), /** * Cancels all of the generators that are currently running. @@ -65,21 +67,21 @@ export const Commands = { /** * @returns The default `Project` that is loaded when a new `Project` is created. */ - defaultProject: () => invoke("default_project"), + defaultProject: () => invoke("default_project"), /** * Reads the `Project` with the specified name from the deploy root directory. * * @param name The name of the `Project` to read without the `.chor` extension. * @returns The `Project` that was read. */ - readProject: (name: string) => invoke("read_project", { name }), + readProject: (name: string) => invoke("read_project", { name }), /** * Writes the specified `Project` to the deploy root directory. * * @param project The `Project` to write. * @returns `void` */ - writeProject: (project: Project) => + writeProject: (project: ProjectFile) => invoke("write_project", { project }), /** @@ -88,20 +90,20 @@ export const Commands = { * @param name The name of the `Traj` to read without the `.traj` extension. * @returns The `Traj` that was read. */ - readTraj: (name: string) => invoke("read_traj", { name }), + readTraj: (name: string) => invoke("read_traj", { name }), /** * Scans the deploy root directory for all of the `Traj` files and returns them. * * @returns All of the `Traj` files in the deploy root directory. */ - readAllTraj: () => invoke("read_all_traj"), + readAllTraj: () => invoke("read_all_traj"), /** * Writes the specified `Traj` to the deploy root directory. * * @param traj The `Traj` to write. * @returns `void` */ - writeTraj: (traj: Traj) => invoke("write_traj", { traj }), + writeTraj: (traj: TrajFile) => invoke("write_traj", { traj }), /** * Renames the specified `Traj` to the specified name. * @@ -109,7 +111,7 @@ export const Commands = { * @param newName The new name for the `Traj`. * @returns `void` */ - renameTraj: (oldTraj: Traj, newName: string) => + renameTraj: (oldTraj: TrajFile, newName: string) => invoke("rename_traj", { oldTraj, newName }), /** * Deletes the specified `Traj` from the deploy root directory. @@ -117,7 +119,7 @@ export const Commands = { * @param traj The `Traj` to delete. * @returns `void` */ - deleteTraj: (traj: Traj) => invoke("delete_traj", { traj }), + deleteTraj: (traj: TrajFile) => invoke("delete_traj", { traj }), /** * If the application was opened via CLI and a file was specified, this will return the path of that file. @@ -129,6 +131,6 @@ export const Commands = { /** * Opens the platforms file explorer to the directory holding a newly generated diagnostic zip file. */ - openDiagnosticZip: (project: Project, trajs: Traj[]) => + openDiagnosticZip: (project: ProjectFile, trajs: TrajFile[]) => invoke("open_diagnostic_file", { project, trajs }) }; diff --git a/src/document/ConstraintDefinitions.tsx b/src/document/ConstraintDefinitions.tsx index 67d9d5a53..f7aa44e1b 100644 --- a/src/document/ConstraintDefinitions.tsx +++ b/src/document/ConstraintDefinitions.tsx @@ -7,8 +7,8 @@ import { } from "@mui/icons-material"; import { JSXElementConstructor, ReactElement } from "react"; import { ObjectTyped } from "../util/ObjectTyped"; -import { Expr } from "./2025/DocumentTypes"; -import { Dimension, DimensionName, Dimensions } from "./ExpressionStore"; +import { Expr } from "./spec/Misc"; +import { Dimension, DimensionName, Dimensions } from "./stores/ExpressionStore"; export type ConstraintPropertyType = Expr | boolean; diff --git a/src/document/DocumentManager.ts b/src/document/DocumentManager.ts index 0d50b1c4e..adb81150b 100644 --- a/src/document/DocumentManager.ts +++ b/src/document/DocumentManager.ts @@ -15,27 +15,15 @@ import "react-toastify/dist/ReactToastify.min.css"; import LocalStorageKeys from "../util/LocalStorageKeys"; import { ObjectTyped } from "../util/ObjectTyped"; import { safeGetIdentifier } from "../util/mobxutils"; -import { - Command, - EventMarker, - GroupCommand, - NamedCommand, - Project, - Traj, - WaitCommand, - type Expr, - type RobotConfig, - type Waypoint -} from "./2025/DocumentTypes"; import { CircularObstacleStore, ICircularObstacleStore -} from "./CircularObstacleStore"; +} from "./stores/CircularObstacleStore"; import { ConstraintDataObjects, IConstraintDataStore, defineCreateConstraintData -} from "./ConstraintDataStore"; +} from "./stores/ConstraintDataStore"; import { ConstraintDefinitions, ConstraintKey, @@ -45,27 +33,42 @@ import { ConstraintStore, IConstraintStore, IWaypointScope -} from "./ConstraintStore"; +} from "./stores//ConstraintStore"; import { CommandStore, EventMarkerStore, ICommandStore, IEventMarkerStore -} from "./EventMarkerStore"; -import { IExpressionStore, IVariables, Variables } from "./ExpressionStore"; +} from "./stores/PplibCommandMarkerStore"; +import { + IExpressionStore, + IVariables, + Variables +} from "./stores/ExpressionStore"; import { IHolonomicWaypointStore, HolonomicWaypointStore as WaypointStore -} from "./HolonomicWaypointStore"; +} from "./stores/HolonomicWaypointStore"; import { EXPR_DEFAULTS, IRobotConfigStore, RobotConfigStore -} from "./RobotConfigStore"; +} from "./stores/RobotConfigStore"; import { ViewLayerDefaults } from "./UIData"; import { UIStateStore } from "./UIStateStore"; -import { Commands } from "./tauriCommands"; -import { tracing } from "./tauriTracing"; +import { Commands } from "./Backend"; +import { tracing } from "../util/Tracing"; +import { + GroupCommand, + NamedCommand, + PplibCommand, + PplibCommandMarker, + TrajFile, + WaitCommand, + Waypoint +} from "./spec/Traj"; +import { Expr } from "./spec/Misc"; +import { ProjectFile, RobotConfig } from "./spec/Project"; export type OpenFilePayload = { name: string; @@ -93,7 +96,7 @@ export type EnvConstructors = { radius: number ) => ICircularObstacleStore; CommandStore: ( - command: Command & + command: PplibCommand & ( | { data: WaitCommand["data"] & @@ -103,7 +106,7 @@ export type EnvConstructors = { | object ) ) => ICommandStore; - EventMarkerStore: (marker: EventMarker) => IEventMarkerStore; + EventMarkerStore: (marker: PplibCommandMarker) => IEventMarkerStore; ConstraintData: ConstraintDataConstructors; ConstraintStore: ( type: K, @@ -113,18 +116,22 @@ export type EnvConstructors = { ) => IConstraintStore; }; function getConstructors(vars: () => IVariables): EnvConstructors { - function commandIsNamed(command: Command): command is NamedCommand { + function commandIsNamed( + command: PplibCommand + ): command is NamedCommand { return Object.hasOwn(command.data, "name"); } function commandIsGroup( - command: Command + command: PplibCommand ): command is GroupCommand { return Object.hasOwn(command.data, "commands"); } - function commandIsTime(command: Command): command is WaitCommand { + function commandIsTime( + command: PplibCommand + ): command is WaitCommand { return Object.hasOwn(command.data, "time"); } - function createCommandStore(command: Command): ICommandStore { + function createCommandStore(command: PplibCommand): ICommandStore { return CommandStore.create({ type: command.type, name: commandIsNamed(command) ? command.data.name : "", @@ -201,7 +208,7 @@ function getConstructors(vars: () => IVariables): EnvConstructors { }); }, CommandStore: createCommandStore, - EventMarkerStore: (marker: EventMarker): IEventMarkerStore => { + EventMarkerStore: (marker: PplibCommandMarker): IEventMarkerStore => { return EventMarkerStore.create({ name: marker.name, target: undefined, @@ -604,8 +611,8 @@ export async function openProject(projectPath: OpenFilePayload) { try { const dir = projectPath.dir; const name = projectPath.name.split(".")[0]; - let project: Project | undefined = undefined; - const trajs: Traj[] = []; + let project: ProjectFile | undefined = undefined; + const trajs: TrajFile[] = []; await Commands.cancelAll(); await Commands.setDeployRoot(dir); await Promise.allSettled([ @@ -809,7 +816,7 @@ export async function saveProjectDialog() { export async function openDiagnosticZipWithInfo() { const project = doc.serializeChor(); - const trajs: Traj[] = []; + const trajs: TrajFile[] = []; doc.pathlist.paths.forEach((path) => { trajs.push(path.serialize); }); diff --git a/src/document/DocumentModel.tsx b/src/document/DocumentModel.tsx index 7b92a0936..899fd36b9 100644 --- a/src/document/DocumentModel.tsx +++ b/src/document/DocumentModel.tsx @@ -3,30 +3,32 @@ import { Instance, getParent, types } from "mobx-state-tree"; import { UndoManager } from "mst-middlewares"; import { toast } from "react-toastify"; import "react-toastify/dist/ReactToastify.min.css"; -import { - DifferentialSample, - ProgressUpdate, - Project, - SAVE_FILE_VERSION, - SampleType, - SwerveSample, - Traj -} from "./2025/DocumentTypes"; import { CircularObstacleStore, ICircularObstacleStore -} from "./CircularObstacleStore"; -import { ConstraintStore, IConstraintStore } from "./ConstraintStore"; -import { EventMarkerStore, IEventMarkerStore } from "./EventMarkerStore"; -import { Variables } from "./ExpressionStore"; +} from "./stores/CircularObstacleStore"; +import { ConstraintStore, IConstraintStore } from "./stores//ConstraintStore"; +import { + EventMarkerStore, + IEventMarkerStore +} from "./stores/PplibCommandMarkerStore"; +import { Variables } from "./stores/ExpressionStore"; import { HolonomicWaypointStore, IHolonomicWaypointStore -} from "./HolonomicWaypointStore"; -import { PathListStore } from "./PathListStore"; -import { RobotConfigStore } from "./RobotConfigStore"; -import { Commands } from "./tauriCommands"; -import { tracing } from "./tauriTracing"; +} from "./stores/HolonomicWaypointStore"; +import { PathListStore } from "./stores/PathListStore"; +import { RobotConfigStore } from "./stores/RobotConfigStore"; +import { Commands } from "./Backend"; +import { tracing } from "../util/Tracing"; +import { ProjectFile, SampleType } from "./spec/Project"; +import { SAVE_FILE_VERSION } from "./spec/Misc"; +import { + DifferentialSample, + ProgressUpdate, + SwerveSample, + TrajFile +} from "./spec/Traj"; export type SelectableItemTypes = | IHolonomicWaypointStore @@ -70,7 +72,7 @@ export const DocumentStore = types hoveredSidebarItem: types.maybe(types.safeReference(SelectableItem)) }) .views((self) => ({ - serializeChor(): Project { + serializeChor(): ProjectFile { return { name: self.name, version: SAVE_FILE_VERSION, @@ -132,7 +134,7 @@ export const DocumentStore = types history: UndoManager.create({}, { targetStore: self }) })) .actions((self) => ({ - deserializeChor(ser: Project) { + deserializeChor(ser: ProjectFile) { self.name = ser.name; self.variables.deserialize(ser.variables); self.robotConfig.deserialize(ser.config); @@ -246,7 +248,7 @@ export const DocumentStore = types }) .then( (rust_traj) => { - const result: Traj = rust_traj as Traj; + const result: TrajFile = rust_traj as TrajFile; console.log(result); if (result.traj.samples.length == 0) throw "No traj"; self.history.startGroup(() => { diff --git a/src/document/UIData.tsx b/src/document/UIData.tsx index 01fd239ca..e863245db 100644 --- a/src/document/UIData.tsx +++ b/src/document/UIData.tsx @@ -20,7 +20,7 @@ import { ConstraintDefinitions, ConstraintKey } from "./ConstraintDefinitions"; -import { ConstraintStore } from "./ConstraintStore"; +import { ConstraintStore } from "./stores//ConstraintStore"; /* Navbar stuff */ export const WaypointData: { diff --git a/src/document/UIStateStore.tsx b/src/document/UIStateStore.tsx index 81d99bb46..6444c2d96 100644 --- a/src/document/UIStateStore.tsx +++ b/src/document/UIStateStore.tsx @@ -17,7 +17,7 @@ import { navbarIndexToConstraintDefinition, navbarIndexToConstraintKey } from "./UIData"; -import { tracing } from "./tauriTracing"; +import { tracing } from "../util/Tracing"; export const UIStateStore = types .model("UIStateStore", { diff --git a/src/document/spec/Misc.ts b/src/document/spec/Misc.ts new file mode 100644 index 000000000..31e933ad6 --- /dev/null +++ b/src/document/spec/Misc.ts @@ -0,0 +1,13 @@ +export const SAVE_FILE_VERSION = "v2025.0.0"; +/** + * An expression is a tuple of a string and a number. + * + * The string is a mathematical expression that can be evaluated to a number. + * The number is the value of the expression. + */ +export type Expr = [string, number]; + +/** + * A union type of an expression or a number. + */ +export type ExprOrNumber = Expr | number; diff --git a/src/document/spec/Project.ts b/src/document/spec/Project.ts new file mode 100644 index 000000000..78622e8a7 --- /dev/null +++ b/src/document/spec/Project.ts @@ -0,0 +1,52 @@ +import { Dimensions } from "../stores/ExpressionStore"; +import { Expr, ExprOrNumber, SAVE_FILE_VERSION } from "./Misc"; + +export interface Variable { + dimension: keyof typeof Dimensions; + var: Expr; +} +export interface PoseVariable { + x: Expr; + y: Expr; + heading: Expr; +} + +export interface Variables { + expressions: Record; + poses: Record; +} + +export interface Bumper { + front: T; + left: T; + back: T; + right: T; +} + +export interface Module { + x: T; + y: T; +} + +export interface RobotConfig { + modules: [Module, Module, Module, Module]; + mass: T; + inertia: T; + gearing: T; + radius: T; + /// motor rad/s + vmax: T; + /// motor N*m + tmax: T; // N*m + bumper: Bumper; +} + +export type SampleType = "Swerve" | "Differential"; + +export interface ProjectFile { + name: string; + type: SampleType; + version: typeof SAVE_FILE_VERSION; + variables: Variables; + config: RobotConfig; +} diff --git a/src/document/2025/v2025_0_0.ts b/src/document/spec/Traj.ts similarity index 62% rename from src/document/2025/v2025_0_0.ts rename to src/document/spec/Traj.ts index 10f8c107c..9d260bf6f 100644 --- a/src/document/2025/v2025_0_0.ts +++ b/src/document/spec/Traj.ts @@ -1,57 +1,5 @@ import { ConstraintData } from "../ConstraintDefinitions"; -import { Dimensions } from "../ExpressionStore"; - -export const SAVE_FILE_VERSION = "v2025.0.0"; -export type Expr = [string, number]; - -export type ExprOrNumber = Expr | number; -export interface Variable { - dimension: keyof typeof Dimensions; - var: Expr; -} -export interface PoseVariable { - x: Expr; - y: Expr; - heading: Expr; -} - -export interface Variables { - expressions: Record; - poses: Record; -} - -export interface Bumper { - front: T; - left: T; - back: T; - right: T; -} - -export interface Module { - x: T; - y: T; -} - -export interface RobotConfig { - modules: [Module, Module, Module, Module]; - mass: T; - inertia: T; - gearing: T; - radius: T; - /// motor rad/s - vmax: T; - /// motor N*m - tmax: T; // N*m - bumper: Bumper; -} - -export interface Project { - name: string; - type: SampleType; - version: typeof SAVE_FILE_VERSION; - variables: Variables; - config: RobotConfig; -} +import { Expr, ExprOrNumber, SAVE_FILE_VERSION } from "./Misc"; export interface Waypoint { x: T; @@ -110,19 +58,20 @@ export interface ChoreoPath { constraints: Constraint[]; } -export type SampleType = "Swerve" | "Differential"; -export interface Output { +export interface Trajectory { waypoints: number[]; samples: SwerveSample[][] | DifferentialSample[][]; forcesAvailable: boolean; } -export interface Traj { +export interface TrajFile { name: string; version: typeof SAVE_FILE_VERSION; params: ChoreoPath; snapshot: ChoreoPath; - traj: Output; + traj: Trajectory; + events: EventMarker[]; + pplibCommands: PplibCommandMarker[]; } export interface CircleObstacle { @@ -134,7 +83,7 @@ export interface CircleObstacle { export type GroupCommand = { type: "deadline" | "parallel" | "race" | "sequential"; data: { - commands: Command[]; + commands: PplibCommand[]; }; }; export type WaitCommand = { @@ -149,11 +98,11 @@ export type NamedCommand = { name: string | null; }; }; -export type Command = +export type PplibCommand = | WaitCommand | GroupCommand | NamedCommand; -export interface EventMarker { +export interface PplibCommandMarker { name: string; target: WaypointID; trajTargetIndex: number | undefined; @@ -162,5 +111,9 @@ export interface EventMarker { * The timestamp along the trajectory of the waypoint this marker targeted on the last generation. */ targetTimestamp: number | undefined; - command: Command; + command: PplibCommand; +} +export interface EventMarker { + event: string; + timestamp: T; } diff --git a/src/document/path/ChoreoPathStore.ts b/src/document/stores/ChoreoPathStore.ts similarity index 97% rename from src/document/path/ChoreoPathStore.ts rename to src/document/stores/ChoreoPathStore.ts index c0ea7bd7d..4f52522cc 100644 --- a/src/document/path/ChoreoPathStore.ts +++ b/src/document/stores/ChoreoPathStore.ts @@ -1,25 +1,22 @@ import { Instance, destroy, getEnv, types } from "mobx-state-tree"; import { moveItem } from "mobx-utils"; -import { - ChoreoPath, - Constraint, - Expr, - Waypoint, - WaypointID -} from "../2025/DocumentTypes"; -import { CircularObstacleStore } from "../CircularObstacleStore"; -import { ConstraintKey, DataMap } from "../ConstraintDefinitions"; + +import { CircularObstacleStore } from "./CircularObstacleStore"; import { ConstraintStore, IConstraintStore, IWaypointScope -} from "../ConstraintStore"; -import { Env } from "../DocumentManager"; +} from "./ConstraintStore"; import { DEFAULT_WAYPOINT, HolonomicWaypointStore, IHolonomicWaypointStore -} from "../HolonomicWaypointStore"; +} from "./HolonomicWaypointStore"; + +import { ConstraintKey, DataMap } from "../ConstraintDefinitions"; +import { Env } from "../DocumentManager"; +import { ChoreoPath, Constraint, Waypoint, WaypointID } from "../spec/Traj"; +import { Expr } from "../spec/Misc"; export const ChoreoPathStore = types .model("ChoreoPathStore", { diff --git a/src/document/path/ChoreoTrajStore.ts b/src/document/stores/ChoreoTrajStore.ts similarity index 94% rename from src/document/path/ChoreoTrajStore.ts rename to src/document/stores/ChoreoTrajStore.ts index dc390318f..d44b1215c 100644 --- a/src/document/path/ChoreoTrajStore.ts +++ b/src/document/stores/ChoreoTrajStore.ts @@ -1,11 +1,9 @@ import { Instance, destroy, getEnv, types } from "mobx-state-tree"; -import { - DifferentialSample, - Output, - type SwerveSample -} from "../2025/DocumentTypes"; + +import { EventMarkerStore, IEventMarkerStore } from "./PplibCommandMarkerStore"; + import { Env } from "../DocumentManager"; -import { EventMarkerStore, IEventMarkerStore } from "../EventMarkerStore"; +import { DifferentialSample, SwerveSample, Trajectory } from "../spec/Traj"; export const ChoreoTrajStore = types .model("ChoreoTrajStore", { @@ -77,7 +75,7 @@ export const ChoreoTrajStore = types } return lastSection[lastSection.length - 1].t; }, - get serialize(): Output { + get serialize(): Trajectory { return { waypoints: self.waypoints, samples: self.samples, @@ -86,7 +84,7 @@ export const ChoreoTrajStore = types } })) .actions((self) => ({ - deserialize(ser: Output) { + deserialize(ser: Trajectory) { self.waypoints = ser.waypoints; self.samples = ser.samples; self.forcesAvailable = ser.forcesAvailable; diff --git a/src/document/CircularObstacleStore.tsx b/src/document/stores/CircularObstacleStore.tsx similarity index 90% rename from src/document/CircularObstacleStore.tsx rename to src/document/stores/CircularObstacleStore.tsx index 7b20737c2..4bbdbd33c 100644 --- a/src/document/CircularObstacleStore.tsx +++ b/src/document/stores/CircularObstacleStore.tsx @@ -1,8 +1,11 @@ import { Instance, getEnv, getParent, isAlive, types } from "mobx-state-tree"; -import { CircleObstacle, Expr } from "./2025/DocumentTypes"; -import { Env } from "./DocumentManager"; + import { ExpressionStore } from "./ExpressionStore"; +import { Env } from "../DocumentManager"; +import { CircleObstacle } from "../spec/Traj"; +import { Expr } from "../spec/Misc"; + export const CircularObstacleStore = types .model("CircularObstacleStore", { x: ExpressionStore, diff --git a/src/document/ConstraintDataStore.tsx b/src/document/stores/ConstraintDataStore.tsx similarity index 98% rename from src/document/ConstraintDataStore.tsx rename to src/document/stores/ConstraintDataStore.tsx index 93b755291..a7baedc1a 100644 --- a/src/document/ConstraintDataStore.tsx +++ b/src/document/stores/ConstraintDataStore.tsx @@ -6,7 +6,7 @@ import { ModelPropertiesDeclarationToProperties, types } from "mobx-state-tree"; -import { Expr } from "./2025/DocumentTypes"; +import { Expr } from "../spec/Misc"; import { ConstraintData, ConstraintDefinition, @@ -16,7 +16,7 @@ import { DataMap, PropertyDefinitionList, consts -} from "./ConstraintDefinitions"; +} from "../ConstraintDefinitions"; import { ExpressionStore, IExpressionStore, diff --git a/src/document/ConstraintStore.tsx b/src/document/stores/ConstraintStore.tsx similarity index 93% rename from src/document/ConstraintStore.tsx rename to src/document/stores/ConstraintStore.tsx index 96b7398a2..f0c40ca9d 100644 --- a/src/document/ConstraintStore.tsx +++ b/src/document/stores/ConstraintStore.tsx @@ -1,13 +1,15 @@ import { Instance, getEnv, getParent, isAlive, types } from "mobx-state-tree"; + import { ConstraintDataObjects, IConstraintDataStore } from "./ConstraintDataStore"; -import { ConstraintKey } from "./ConstraintDefinitions"; -import { Env } from "./DocumentManager"; import { IHolonomicWaypointStore } from "./HolonomicWaypointStore"; -import { IChoreoPathStore } from "./path/ChoreoPathStore"; -import { IHolonomicPathStore } from "./path/HolonomicPathStore"; +import { IChoreoPathStore } from "./ChoreoPathStore"; +import { IHolonomicPathStore } from "./HolonomicPathStore"; + +import { ConstraintKey } from "../ConstraintDefinitions"; +import { Env } from "../DocumentManager"; export const WaypointScope = types.union( types.literal("first"), diff --git a/src/document/ExpressionStore.tsx b/src/document/stores/ExpressionStore.tsx similarity index 97% rename from src/document/ExpressionStore.tsx rename to src/document/stores/ExpressionStore.tsx index 8994219c3..9252cc868 100644 --- a/src/document/ExpressionStore.tsx +++ b/src/document/stores/ExpressionStore.tsx @@ -8,6 +8,7 @@ import { TimerOutlined } from "@mui/icons-material"; import { Tooltip } from "@mui/material"; + import { AccessorNode, ConstantNode, @@ -25,18 +26,20 @@ import { } from "mathjs"; import { IReactionDisposer, reaction, untracked } from "mobx"; import { Instance, detach, getEnv, types } from "mobx-state-tree"; -import Angle from "../assets/Angle"; -import Mass from "../assets/Mass"; -import MoI from "../assets/MoI"; -import Torque from "../assets/Torque"; -import Waypoint from "../assets/Waypoint"; + +import Angle from "../../assets/Angle"; +import Mass from "../../assets/Mass"; +import MoI from "../../assets/MoI"; +import Torque from "../../assets/Torque"; +import Waypoint from "../../assets/Waypoint"; + import { PoseVariable as DocPoseVariable, - Variables as DocVariables, - Expr -} from "./2025/DocumentTypes"; -import { Env } from "./DocumentManager"; -import { tracing } from "./tauriTracing"; + Variables as DocVariables +} from "../spec/Project"; +import { Env } from "../DocumentManager"; +import { tracing } from "../../util/Tracing"; +import { Expr } from "../spec/Misc"; export const math = create(all, { predictable: true }); @@ -504,6 +507,9 @@ export const Variables = types poses: types.map(ExprPose) }) .views((self) => ({ + /** + * Returns a serialized version of the variables + */ get serialize(): DocVariables { const out: DocVariables = { expressions: {}, diff --git a/src/document/path/HolonomicPathStore.ts b/src/document/stores/HolonomicPathStore.ts similarity index 93% rename from src/document/path/HolonomicPathStore.ts rename to src/document/stores/HolonomicPathStore.ts index d0bd98771..9680884b6 100644 --- a/src/document/path/HolonomicPathStore.ts +++ b/src/document/stores/HolonomicPathStore.ts @@ -1,20 +1,17 @@ import { Instance, types, getEnv } from "mobx-state-tree"; +import { IReactionDisposer, reaction } from "mobx"; + import { DEFAULT_WAYPOINT, IHolonomicWaypointStore -} from "../HolonomicWaypointStore"; -import { IReactionDisposer, reaction } from "mobx"; -import { - SAVE_FILE_VERSION, - type ChoreoPath, - type Traj, - Waypoint, - Expr -} from "../2025/DocumentTypes"; +} from "./HolonomicWaypointStore"; import { ChoreoPathStore } from "./ChoreoPathStore"; import { ChoreoTrajStore } from "./ChoreoTrajStore"; import { PathUIStore } from "./PathUIStore"; + import { Env } from "../DocumentManager"; +import { ChoreoPath, TrajFile, Waypoint } from "../spec/Traj"; +import { Expr, SAVE_FILE_VERSION } from "../spec/Misc"; export const HolonomicPathStore = types .model("HolonomicPathStore", { @@ -38,13 +35,15 @@ export const HolonomicPathStore = types canExport(): boolean { return self.traj.samples.length >= 2; }, - get serialize(): Traj { + get serialize(): TrajFile { return { name: self.name, version: SAVE_FILE_VERSION, params: self.params.serialize, traj: self.traj.serialize, - snapshot: self.snapshot + snapshot: self.snapshot, + events: [], + pplibCommands: [] }; }, lowestSelectedPoint(): IHolonomicWaypointStore | null { @@ -109,7 +108,7 @@ export const HolonomicPathStore = types }) .actions((self) => { return { - deserialize(ser: Traj) { + deserialize(ser: TrajFile) { self.name = ser.name; self.snapshot = ser.snapshot; self.params.deserialize(ser.params); diff --git a/src/document/HolonomicWaypointStore.ts b/src/document/stores/HolonomicWaypointStore.ts similarity index 94% rename from src/document/HolonomicWaypointStore.ts rename to src/document/stores/HolonomicWaypointStore.ts index bcc9f2253..dc9381d62 100644 --- a/src/document/HolonomicWaypointStore.ts +++ b/src/document/stores/HolonomicWaypointStore.ts @@ -1,9 +1,13 @@ import { Instance, getEnv, getParent, isAlive, types } from "mobx-state-tree"; -import { Expr, Waypoint } from "./2025/DocumentTypes"; -import { Env } from "./DocumentManager"; + import { ExpressionStore } from "./ExpressionStore"; -import { NavbarItemData } from "./UIData"; -import { tracing } from "./tauriTracing"; + +import { Env } from "../DocumentManager"; +import { NavbarItemData } from "../UIData"; +import { Waypoint } from "../spec/Traj"; +import { Expr } from "../spec/Misc"; + +import { tracing } from "../../util/Tracing"; export const DEFAULT_WAYPOINT: Waypoint = { x: 0, diff --git a/src/document/PathListStore.ts b/src/document/stores/PathListStore.ts similarity index 94% rename from src/document/PathListStore.ts rename to src/document/stores/PathListStore.ts index 581f276f9..c4b2b6fde 100644 --- a/src/document/PathListStore.ts +++ b/src/document/stores/PathListStore.ts @@ -1,7 +1,9 @@ import { Instance, getEnv, types } from "mobx-state-tree"; -import { Traj } from "./2025/DocumentTypes"; -import { Env } from "./DocumentManager"; -import { HolonomicPathStore } from "./path/HolonomicPathStore"; + +import { HolonomicPathStore } from "./HolonomicPathStore"; + +import { TrajFile } from "../spec/Traj"; +import { Env } from "../DocumentManager"; export const PathListStore = types .model("PathListStore", { @@ -83,7 +85,11 @@ export const PathListStore = types self.activePathUUID = uuid; } }, - addPath(name: string, select: boolean = false, contents?: Traj): string { + addPath( + name: string, + select: boolean = false, + contents?: TrajFile + ): string { const usedName = this.disambiguateName(name); const newUUID = crypto.randomUUID(); const env = getEnv(self); diff --git a/src/document/path/PathUIStore.ts b/src/document/stores/PathUIStore.ts similarity index 94% rename from src/document/path/PathUIStore.ts rename to src/document/stores/PathUIStore.ts index 4597f92c9..8e7c78c05 100644 --- a/src/document/path/PathUIStore.ts +++ b/src/document/stores/PathUIStore.ts @@ -1,6 +1,7 @@ import { types, getEnv, Instance } from "mobx-state-tree"; -import { DifferentialSample, type SwerveSample } from "../2025/DocumentTypes"; + import { Env } from "../DocumentManager"; +import { DifferentialSample, SwerveSample } from "../spec/Traj"; export const PathUIStore = types .model("PathUIStore", { diff --git a/src/document/PolygonObstacleStore.tsx b/src/document/stores/PolygonObstacleStore.tsx similarity index 100% rename from src/document/PolygonObstacleStore.tsx rename to src/document/stores/PolygonObstacleStore.tsx diff --git a/src/document/EventMarkerStore.tsx b/src/document/stores/PplibCommandMarkerStore.tsx similarity index 94% rename from src/document/EventMarkerStore.tsx rename to src/document/stores/PplibCommandMarkerStore.tsx index 92cea58b5..8c45724db 100644 --- a/src/document/EventMarkerStore.tsx +++ b/src/document/stores/PplibCommandMarkerStore.tsx @@ -9,13 +9,16 @@ import { types } from "mobx-state-tree"; import { moveItem } from "mobx-utils"; -import { Command, Expr } from "./2025/DocumentTypes"; -import { WaypointID } from "./ConstraintDefinitions"; + import { WaypointScope } from "./ConstraintStore"; -import { Env } from "./DocumentManager"; import { ExpressionStore } from "./ExpressionStore"; -import { IChoreoTrajStore } from "./path/ChoreoTrajStore"; -import { IHolonomicPathStore } from "./path/HolonomicPathStore"; +import { IHolonomicPathStore } from "./HolonomicPathStore"; +import { IChoreoTrajStore } from "./ChoreoTrajStore"; + +import { WaypointID } from "../ConstraintDefinitions"; +import { Env } from "../DocumentManager"; +import { PplibCommand } from "../spec/Traj"; +import { Expr } from "../spec/Misc"; export type CommandType = | "sequential" @@ -58,7 +61,7 @@ export const CommandStore = types self.type === "sequential" ); }, - get serialize(): Command { + get serialize(): PplibCommand { if (self.type === "named") { return { type: "named", @@ -84,7 +87,7 @@ export const CommandStore = types } })) .actions((self) => ({ - deserialize(ser: Command) { + deserialize(ser: PplibCommand) { self.commands.clear(); self.name = ""; self.type = ser.type; diff --git a/src/document/RobotConfigStore.ts b/src/document/stores/RobotConfigStore.ts similarity index 96% rename from src/document/RobotConfigStore.ts rename to src/document/stores/RobotConfigStore.ts index b40509025..be18fc5aa 100644 --- a/src/document/RobotConfigStore.ts +++ b/src/document/stores/RobotConfigStore.ts @@ -1,11 +1,15 @@ import { Instance, types } from "mobx-state-tree"; + +import { ExpressionStore } from "./ExpressionStore"; + +import { Bumper, Module, RobotConfig } from "../spec/Project"; +import { Expr } from "../spec/Misc"; + import { maxTorqueCurrentLimited, MotorCurves -} from "../components/config/robotconfig/MotorCurves"; -import { InToM, LbsToKg, MToIn } from "../util/UnitConversions"; -import { Bumper, Expr, Module, RobotConfig } from "./2025/DocumentTypes"; -import { ExpressionStore } from "./ExpressionStore"; +} from "../../components/config/robotconfig/MotorCurves"; +import { InToM, LbsToKg, MToIn } from "../../util/UnitConversions"; const DEFAULT_FRAME_SIZE = InToM(28); const DEFAULT_BUMPER = DEFAULT_FRAME_SIZE + 2 * InToM(2.5 + 0.75); // 28x28 bot with 2.5" noodle and 0.75" backing diff --git a/src/util/MathUtil.ts b/src/util/MathUtil.ts index d7c1b24aa..76a08b734 100644 --- a/src/util/MathUtil.ts +++ b/src/util/MathUtil.ts @@ -1,7 +1,4 @@ -import { - DifferentialSample, - SwerveSample -} from "../document/2025/DocumentTypes"; +import { DifferentialSample, SwerveSample } from "../document/spec/Traj"; /** * A port of WPILib's MathUtil.inputModulus diff --git a/src/document/tauriTracing.ts b/src/util/Tracing.ts similarity index 100% rename from src/document/tauriTracing.ts rename to src/util/Tracing.ts