sleipnirgroup / choreo Goto Github PK
View Code? Open in Web Editor NEWA graphical tool for planning time-optimized trajectories for autonomous mobile robots in the FIRST Robotics Competition.
License: BSD 3-Clause "New" or "Revised" License
A graphical tool for planning time-optimized trajectories for autonomous mobile robots in the FIRST Robotics Competition.
License: BSD 3-Clause "New" or "Revised" License
It prints a lot of warnings on app startup that should get fixed. We can catch them in CI instead.
[0] Compiled with warnings.
[0]
[0] [eslint]
[0] src/components/field/Field.tsx
[0] Line 4:8: 'DocumentManagerContext' is defined but never used @typescript-eslint/no-unused-vars
[0] Line 5:8: 'FieldOverlay' is defined but never used @typescript-eslint/no-unused-vars
[0] Line 8:8: 'Moveable' is defined but never used @typescript-eslint/no-unused-vars
[0] Line 17:3: Useless constructor @typescript-eslint/no-useless-constructor
[0]
[0] src/components/field/svg/FieldOverlayRoot.tsx
[0] Line 1:10: 'autorun' is defined but never used @typescript-eslint/no-unused-vars
[0] Line 1:19: 'IReactionDisposer' is defined but never used @typescript-eslint/no-unused-vars
[0] Line 3:28: 'LegacyRef' is defined but never used @typescript-eslint/no-unused-vars
[0] Line 3:39: 'ReactNode' is defined but never used @typescript-eslint/no-unused-vars
[0] Line 7:10: 'IHolonomicWaypointStore' is defined but never used @typescript-eslint/no-unused-vars
[0] Line 8:8: 'styles' is defined but never used @typescript-eslint/no-unused-vars
[0] Line 10:8: 'OverlayWaypointOld' is defined but never used @typescript-eslint/no-unused-vars
[0] Line 11:13: 'd3' is defined but never used @typescript-eslint/no-unused-vars
[0] Line 20:7: 'FieldBackground' is assigned a value but never used @typescript-eslint/no-unused-vars
[0]
[0] src/components/field/svg/OverlayWaypoint.tsx
[0] Line 6:8: 'ReactDOM' is defined but never used @typescript-eslint/no-unused-vars
[0] Line 7:10: 'DragContainerElement' is defined but never used @typescript-eslint/no-unused-vars
[0] Line 14:7: 'ROTATE_HANDLE_DIST' is assigned a value but never used @typescript-eslint/no-unused-vars
[0] Line 131:28: Expected '===' and instead saw '==' eqeqeq
[0] Line 132:28: Expected '===' and instead saw '==' eqeqeq
[0] Line 140:11: 'px' is assigned a value but never used @typescript-eslint/no-unused-vars
[0]
[0] src/components/navbar/PathSelect.tsx
[0] Line 44:3: Useless constructor @typescript-eslint/no-useless-constructor
[0] Line 51:45: Expected '!==' and instead saw '!=' eqeqeq
[0] Line 51:91: Expected '!==' and instead saw '!=' eqeqeq
[0]
[0] src/components/sidebar/Sidebar.tsx
[0] Line 10:9: 'faDiscord' is defined but never used @typescript-eslint/no-unused-vars
[0] Line 10:20: 'faGithub' is defined but never used @typescript-eslint/no-unused-vars
[0] Line 11:9: 'faGear' is defined but never used @typescript-eslint/no-unused-vars
[0]
[0] src/document/DocumentModel.ts
[0] Line 215:15: 'element' is assigned a value but never used @typescript-eslint/no-unused-vars
[0]
[0] Search for the keywords to learn more about each warning.
[0] To ignore, add // eslint-disable-next-line to the line before.
[0]
[0] WARNING in [eslint]
[0] src/components/field/Field.tsx
[0] Line 4:8: 'DocumentManagerContext' is defined but never used @typescript-eslint/no-unused-vars
[0] Line 5:8: 'FieldOverlay' is defined but never used @typescript-eslint/no-unused-vars
[0] Line 8:8: 'Moveable' is defined but never used @typescript-eslint/no-unused-vars
[0] Line 17:3: Useless constructor @typescript-eslint/no-useless-constructor
[0]
[0] src/components/field/svg/FieldOverlayRoot.tsx
[0] Line 1:10: 'autorun' is defined but never used @typescript-eslint/no-unused-vars
[0] Line 1:19: 'IReactionDisposer' is defined but never used @typescript-eslint/no-unused-vars
[0] Line 3:28: 'LegacyRef' is defined but never used @typescript-eslint/no-unused-vars
[0] Line 3:39: 'ReactNode' is defined but never used @typescript-eslint/no-unused-vars
[0] Line 7:10: 'IHolonomicWaypointStore' is defined but never used @typescript-eslint/no-unused-vars
[0] Line 8:8: 'styles' is defined but never used @typescript-eslint/no-unused-vars
[0] Line 10:8: 'OverlayWaypointOld' is defined but never used @typescript-eslint/no-unused-vars
[0] Line 11:13: 'd3' is defined but never used @typescript-eslint/no-unused-vars
[0] Line 20:7: 'FieldBackground' is assigned a value but never used @typescript-eslint/no-unused-vars
[0]
[0] src/components/field/svg/OverlayWaypoint.tsx
[0] Line 6:8: 'ReactDOM' is defined but never used @typescript-eslint/no-unused-vars
[0] Line 7:10: 'DragContainerElement' is defined but never used @typescript-eslint/no-unused-vars
[0] Line 14:7: 'ROTATE_HANDLE_DIST' is assigned a value but never used @typescript-eslint/no-unused-vars
[0] Line 131:28: Expected '===' and instead saw '==' eqeqeq
[0] Line 132:28: Expected '===' and instead saw '==' eqeqeq
[0] Line 140:11: 'px' is assigned a value but never used @typescript-eslint/no-unused-vars
[0]
[0] src/components/navbar/PathSelect.tsx
[0] Line 44:3: Useless constructor @typescript-eslint/no-useless-constructor
[0] Line 51:45: Expected '!==' and instead saw '!=' eqeqeq
[0] Line 51:91: Expected '!==' and instead saw '!=' eqeqeq
[0]
[0] src/components/sidebar/Sidebar.tsx
[0] Line 10:9: 'faDiscord' is defined but never used @typescript-eslint/no-unused-vars
[0] Line 10:20: 'faGithub' is defined but never used @typescript-eslint/no-unused-vars
[0] Line 11:9: 'faGear' is defined but never used @typescript-eslint/no-unused-vars
[0]
[0] src/document/DocumentModel.ts
[0] Line 215:15: 'element' is assigned a value but never used @typescript-eslint/no-unused-vars
[0]
[0] webpack compiled with 1 warning
From #115 and others
After making a fairly long path, the generate button becomes disabled with the text "Generate path (needs 2 waypoints)". This is on the current alpha release version.
{
"version": "v0.0.0",
"robotConfiguration": {
"mass": 63.5029,
"rotationalInertia": 5.6,
"wheelMaxTorque": 1.9,
"wheelMaxVelocity": 16,
"wheelbase": 0.57785,
"trackWidth": 0.57785,
"bumperLength": 0.9,
"bumperWidth": 0.9,
"wheelRadius": 0.0508
},
"paths": {
"Broken Path": {
"waypoints": [
{
"x": 1.847985029220581,
"y": 2.9409890174865723,
"heading": 3.1286062808745037,
"velocityMagnitude": 0,
"velocityAngle": 0,
"xConstrained": true,
"yConstrained": true,
"headingConstrained": true,
"velocityMagnitudeConstrained": false,
"velocityAngleConstrained": false,
"angularVelocity": 0,
"angularVelocityConstrained": false,
"controlIntervalCount": 0
},
{
"x": 2.8469085693359375,
"y": 3.332319974899292,
"heading": 3.141592653589793,
"velocityMagnitude": 0,
"velocityAngle": 0,
"xConstrained": true,
"yConstrained": true,
"headingConstrained": true,
"velocityMagnitudeConstrained": false,
"velocityAngleConstrained": false,
"angularVelocity": 0,
"angularVelocityConstrained": false,
"controlIntervalCount": 0
},
{
"x": 5.946660995483398,
"y": 3.414705514907837,
"heading": 0,
"velocityMagnitude": 0,
"velocityAngle": 0,
"xConstrained": true,
"yConstrained": true,
"headingConstrained": true,
"velocityMagnitudeConstrained": false,
"velocityAngleConstrained": false,
"angularVelocity": 0,
"angularVelocityConstrained": false,
"controlIntervalCount": 0
},
{
"x": 6.8940935134887695,
"y": 3.404407262802124,
"heading": 0,
"velocityMagnitude": 0,
"velocityAngle": 0,
"xConstrained": true,
"yConstrained": true,
"headingConstrained": true,
"velocityMagnitudeConstrained": false,
"velocityAngleConstrained": false,
"angularVelocity": 0,
"angularVelocityConstrained": false,
"controlIntervalCount": 0
},
{
"x": 6.430675506591797,
"y": 3.404407262802124,
"heading": 0,
"velocityMagnitude": 0,
"velocityAngle": 0,
"xConstrained": true,
"yConstrained": true,
"headingConstrained": true,
"velocityMagnitudeConstrained": false,
"velocityAngleConstrained": false,
"angularVelocity": 0,
"angularVelocityConstrained": false,
"controlIntervalCount": 0
},
{
"x": 5.26698112487793,
"y": 3.414705514907837,
"heading": 3.1254650337956287,
"velocityMagnitude": 0,
"velocityAngle": 0,
"xConstrained": true,
"yConstrained": true,
"headingConstrained": true,
"velocityMagnitudeConstrained": false,
"velocityAngleConstrained": false,
"angularVelocity": 0,
"angularVelocityConstrained": false,
"controlIntervalCount": 0
},
{
"x": 2.970486640930176,
"y": 3.404407262802124,
"heading": 3.134599712470048,
"velocityMagnitude": 0,
"velocityAngle": 0,
"xConstrained": true,
"yConstrained": true,
"headingConstrained": true,
"velocityMagnitudeConstrained": false,
"velocityAngleConstrained": false,
"angularVelocity": 0,
"angularVelocityConstrained": false,
"controlIntervalCount": 0
},
{
"x": 1.9612650871276855,
"y": 3.6000726222991943,
"heading": 3.141592653589793,
"velocityMagnitude": 0,
"velocityAngle": 0,
"xConstrained": true,
"yConstrained": true,
"headingConstrained": true,
"velocityMagnitudeConstrained": false,
"velocityAngleConstrained": false,
"angularVelocity": 0,
"angularVelocityConstrained": false,
"controlIntervalCount": 0
},
{
"x": 2.8366103172302246,
"y": 3.3735127449035645,
"heading": 0.00961515464871096,
"velocityMagnitude": 0,
"velocityAngle": 0,
"xConstrained": true,
"yConstrained": true,
"headingConstrained": true,
"velocityMagnitudeConstrained": false,
"velocityAngleConstrained": false,
"angularVelocity": 0,
"angularVelocityConstrained": false,
"controlIntervalCount": 0
},
{
"x": 5.339068412780762,
"y": 3.394109010696411,
"heading": 0,
"velocityMagnitude": 0,
"velocityAngle": 0,
"xConstrained": true,
"yConstrained": true,
"headingConstrained": true,
"velocityMagnitudeConstrained": false,
"velocityAngleConstrained": false,
"angularVelocity": 0,
"angularVelocityConstrained": false,
"controlIntervalCount": 0
},
{
"x": 6.337991714477539,
"y": 3.929614543914795,
"heading": 0.7562093421285745,
"velocityMagnitude": 0,
"velocityAngle": 0,
"xConstrained": true,
"yConstrained": true,
"headingConstrained": true,
"velocityMagnitudeConstrained": false,
"velocityAngleConstrained": false,
"angularVelocity": 0,
"angularVelocityConstrained": false,
"controlIntervalCount": 0
},
{
"x": 6.852900505065918,
"y": 4.413629055023193,
"heading": 0.7509291723814462,
"velocityMagnitude": 0,
"velocityAngle": 0,
"xConstrained": true,
"yConstrained": true,
"headingConstrained": true,
"velocityMagnitudeConstrained": false,
"velocityAngleConstrained": false,
"angularVelocity": 0,
"angularVelocityConstrained": false,
"controlIntervalCount": 0
},
{
"x": 6.440973281860352,
"y": 4.053192615509033,
"heading": 0.7356656243694437,
"velocityMagnitude": 0,
"velocityAngle": 0,
"xConstrained": true,
"yConstrained": true,
"headingConstrained": true,
"velocityMagnitudeConstrained": false,
"velocityAngleConstrained": false,
"angularVelocity": 0,
"angularVelocityConstrained": false,
"controlIntervalCount": 0
},
{
"x": 5.318471908569336,
"y": 3.414705514907837,
"heading": 3.126778992329981,
"velocityMagnitude": 0,
"velocityAngle": 0,
"xConstrained": true,
"yConstrained": true,
"headingConstrained": true,
"velocityMagnitudeConstrained": false,
"velocityAngleConstrained": false,
"angularVelocity": 0,
"angularVelocityConstrained": false,
"controlIntervalCount": 0
},
{
"x": 2.795417547225952,
"y": 3.3735127449035645,
"heading": 2.9729955306423057,
"velocityMagnitude": 0,
"velocityAngle": 0,
"xConstrained": true,
"yConstrained": true,
"headingConstrained": true,
"velocityMagnitudeConstrained": false,
"velocityAngleConstrained": false,
"angularVelocity": 0,
"angularVelocityConstrained": false,
"controlIntervalCount": 0
},
{
"x": 2.0333521366119385,
"y": 3.476494550704956,
"heading": 3.0118902024990373,
"velocityMagnitude": 0,
"velocityAngle": 0,
"xConstrained": true,
"yConstrained": true,
"headingConstrained": true,
"velocityMagnitudeConstrained": false,
"velocityAngleConstrained": false,
"angularVelocity": 0,
"angularVelocityConstrained": false,
"controlIntervalCount": 0
}
],
"trajectory": null
}
}
}
Use JSON Schema for the document specification.
Opened JSON files can then be validated using jsonschema.
Uncaught (in promise) Error in Opti::subject_to [OptiNode] at .../casadi/core/optistack.cpp:94:
.../casadi/core/optistack_internal.cpp:905: Assertion "!g.is_constant()" failed:
You passed a constant to `subject_to`. You need a symbol to form a constraint.
Due to the current state of the trajectory generator, the physics parameters of the robot often need to be modified and tuned for each path. This is not ideal, but it's just the way it is right now. I know this from using HelixNavigator in the 2023 season.
If this feature is not added, users will be forced into creating a separate document file for each path, not utilizing the multi-path selection user interface within the app.
from #115
Currently, the robot config set in the frontend is not plumbed to the Rust function for generating trajectories.
Create the proper structs in Rust and JS plumbing to accept a robot config in the generate command.
Whenever I try to run the program on MacOS (Intel Silicon), I'm getting issues with it finding the dylib for /usr/local/lib/libTrajoptLib.dylib
. I get the error of
dyld[53276]: Library not loaded: @rpath/libTrajoptLib.dylib
Referenced from: <A497B11A-EBBB-325A-9BD5-006564060FE6> /Users/bacon/dev/frc/UntitledWaypointEditor/src-tauri/target/debug/untitled-waypoint-editor
Reason: tried: '/Users/bacon/dev/frc/UntitledWaypointEditor/src-tauri/target/debug/libTrajoptLib.dylib' (no such file), '/Users/bacon/dev/frc/UntitledWaypointEditor/src-tauri/target/debug/libTrajoptLib.dylib' (no such file), '/usr/local/lib/libTrajoptLib.dylib' (no such file), '/usr/lib/libTrajoptLib.dylib' (no such file, not in dyld cache)
Is there a step that's not included in the readme that I'm missing?
Note: I've tried setting LD_LIBRARY_PATH
and it doesn't seem to affect anything.
Keybinds for the most used parts of the UI:
This enables more flexibility and less duplication of data types.
There are two main options to do this:
1.
a. TS frontend sends path string to Tauri Rust backend through a Tauri command.
b. Rust parses it and sets up TrajoptLib through CXX bindings similar to the existing setup.
c. TrajoptLib returns an array of samples, which Rust serialized and returns as the command response.
2. Same as 1 but Rust directly forwards the string to be parsed by TrajoptLib, negating the need for individual bindings.
from #115
This is less of an issue with the less-intrusive waypoint and constraint panels.
From #115
In task manager, Choreo is listed under its description text, "A graphical tool for planning...". Unclear where the task manager title is pulled from.
Here is my idea for a better way of doing the numeric input text boxes:
Input
component should have three states: non-focused, focused, and editing.Note that this approach would mean the value in the document model won't update until the user presses "Enter". I think that's fine though.
The example project is at https://github.com/SleipnirGroup/ChoreoSwerveBot.
I didn't actually check if any issues are already open, but this is a collection of my feedback.
Application is quite stable for me. Wasn't able to force a crash without doing malicious things (deleting app/system files). My complains are honestly pretty minor.
After a trajectory is generated then the user modifies the path, the user must be able to tell that the currently stored generated trajectory is no longer valid for the newly modified path.
From #115
Reinstate the line in main.rs that hides this.
From #115
Relevant configuration is at the end of tauri.conf.json
In the spirit of one-click builds, I'd like the build task of a freshly cloned robot project to noninteractively generate trajectories and output them to the deploy folder for GradleRIO to deploy. A noninteractive commandline mode would facilitate this.
This makes tweaking waypoints before a match via the project JSON or via the UI less error-prone, because it ensures the generated outputs during a deploy are up to date.
From #115
Memory leak when adding paths. Added 100 paths, initially spiked to 200MB then settled down to 100. Was initially 80. I can reliably reproduce this and have gotten it to about 300MB settled after ~300 paths.
Hypothesis: is this the undo history? investigate limited-length undo history.
Opening Choreo:
./choreo: error loading shared libraries: libcasadi.so.3.7: cannot open shared object file: No such file or directory
So choreo
is able to find libTrajoptLib.so
, but it can't find libcasadi.so.3.7
.
objdump -x libTrajoptLib.so |grep 'R.*PATH'
This yields the following:
RUNPATH /home/runner/work/Choreo/Choreo/src-tauri/target/release/build/trajoptlib-c5c9b7a7279c9368/out/lib
There should be another rpath entry for the current directory, so $ORIGIN/
.
This is likely an issue with TrajoptLib not adding the proper rpath entries to libTrajoptLib.so
.
Clicking away should be the same as hitting Enter.
From #115
From #115
from #115 in regards to waypoints
Example: typing 2 + 3
into a number text box should enter the value of 5
.
Basic mathematical syntax, functions, and constants should be supported. (sin(pi/2)+1*2)^2
will result in 9
.
An example implementation of this is in HelixNavigator.
The mouse pointer currently changes to a finger when you hover above the orientation handle for a waypoint.
For consistency, recommend also doing this when you hover above the x-y position handle.
I followed these steps:
target
folder and any left over .so files in the src-tauri folder.npm install
from the repo rootnpm run tauri dev
from the repo root Finished dev [unoptimized + debuginfo] target(s) in 2m 30s
/home/tav/git/Choreo/src-tauri/target/debug/choreo: error while loading shared libraries: libTrajoptLib.so: cannot open shared object file: No such file or directory
Here's what's in my folders:
[tav@myriad Choreo]$ ls
icon node_modules public spec tsconfig.json
index.html package-lock.json README.md src tsconfig.node.json
LICENSE package.json scripts src-tauri vite.config.ts
[tav@myriad src-tauri]$ pwd
/home/tav/git/Choreo/src-tauri
[tav@myriad src-tauri]$ ls
build.rs libcasadi_nlpsol_ipopt.so libTrajoptLib.so
Cargo.lock libcoinmetis.so.2 src
Cargo.toml libcoinmumps.so.3 target
icons libgfortran-040039e1.so.5.0.0 tauri.conf.in.json
libcasadi-tp-openblas.so.0 libipopt.so.3 tauri.conf.json
libcasadi.so.3.7 libquadmath-96973f99.so.0.0.0
[tav@myriad debug]$ pwd
/home/tav/git/Choreo/src-tauri/target/debug
[tav@myriad debug]$ ls
build choreo choreo.d deps examples incremental
Add a button to export just the trajectory (sequence of sample points). These files could be placed in the “deploy” directory of a robot project so the robot code would have access to them.
From #115
Open question: where do we get the number/how do we handle dev artifacts
There's a lot of detail for developers in the main readme that users don't care about. The main readme should talk about high-level things the user cares about, as well as demos and how to use it.
A later section can link to a document with how to build it, since there's so much.
Show a pop up if casadi/trajoptlib fails to optimize the path.
Use TrajoptLib's interface for getting the current state of the solver variables to visualize the evolution of the optimization.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.