Chorus
Multi-DOF Real-Time Online Trajectory Generator
Install / Use
/learn @aadi753/ChorusREADME
🎼 Chorus
<img alt="Static Badge" src="https://img.shields.io/badge/build-passing-red?logo=github"> <img alt="Static Badge" src="https://img.shields.io/badge/branch-main-pink?logo=github"> <img alt="Static Badge" src="https://img.shields.io/badge/license-GPL--3.0--license-green?style=flat"> <img alt="Static Badge" src="https://img.shields.io/badge/trajectory--generation-blue?style=flat"> <img alt="Static Badge" src="https://img.shields.io/badge/online--planning-yellow?style=flat"> <img alt="Static Badge" src="https://img.shields.io/badge/robotics-purple?style=flat"> <img alt="Static Badge" src="https://img.shields.io/badge/C%2B%2B-white?style=flat">
Chorus is a high-performance Multi-DOF RealTime Online Trajectory Generator designed for robotic applications that demand real-time, smooth, and synchronized motion planning — all while respecting system constraints. With built-in jerk limiting and trajectory tracking, Chorus delivers optimal motion profiles with ultra-low latency.
✨ Features
-
🧠 Real-Time Online Generation
Generates smooth, optimal trajectories on the fly for any number of degrees of freedom. -
⏱️ Fast Execution
Optimized for real-time performance — computation time is under 1 milliseconds to compute the output in each control cycle. -
🔄 Dynamic Target Updates
Targets and constraints can be updated during motion without stopping the system. -
📉 Jerk-Limited Profiles
Ensures continuous motion by limiting jerk, making trajectories smoother and safer for hardware. -
🛠️ Constraint-Aware Planning
Respects user-defined limits on position, velocity, acceleration, and jerk. -
🎯 Synchronized Multi-DOF Motion
All degrees of freedom are synchronized for coordinated and collision-free movement. -
🚀 Integrated Tracking Controller
Includes a responsive trajectory tracking controller for high tracking accuracy.
Before diving in let's see what Chorus can do for you:
Sample profile for a 1 DOF system

-
Blue is target position
-
Orange is output position
-
Green is output velocity
-
Red is output acceleration
-
Jerk output (Chorus outputs a constant jerk)

-
In the first image a visible noise is visible in acceleration but it is taken care of by Chorus therefore the velocity and position profiles are smooth.
Okay! one DOF is not too fun , let's see what Chorus can do for you with 2 DOF
-
2 DOF system
-
Target position are updated, constraints are kept same for the whole duration

-
Blue and red curves show the position outputs for each dof.
-
Orange and purple curves show the velocity outputs for each dof.
-
Green and brown show the acceleration outputs for each dof.
NOTE: READ THE FULL README AND READ ALL THE COMMENTS IN THE EXAMPLES FOR THE BEST UNDERSTANDING OF HOW TO DO THINGS
Sample of how the targets were updated and what constraints were used.
- Refer to the coded examples in bin folder to get proper understanding of how to do things this is just sample snippet.
// setting up the initial contraints
constraints.sampling_rate = 0.001;
constraints.max_velocity = 2.0; // rad/s
constraints.min_velocity = -2.0;
constraints.max_acceleration = 2.0; // rad/s^2
constraints.min_acceleration = -2.0;
constraints.max_jerk = 4.0; // rad/s^3
constraints.min_jerk = -4.0;
// go to the target with the constraints sets above
if ( t > 0 && t < 10 ) {
target = { 5,2 };
}
// setting new target
else if ( t > 10 && t < 15 ) {
target = { 0,0 };
}
// setting new target
else if ( t > 15 && t < 25 ) {
target = { -7,-4 };
}
// setting new target
else if ( t > 25 && t < 45 ) {
target = { 1,1 };
}
// setting new target
else {
target = { 0,0 };
}
Okay ,so what we got?
- Smooth motion ✅🚀
- Constraints respected ✅🚀
- Targets updates handled properly ✅🚀
- Synchronized motion ✅🚀
Great! Now let's see what we can do next
How about changing the Constraints this time ??
Why not, Chorus can handle that too 🚀

-
Blue and red curves show the position outputs for each dof.
-
Orange and purple curves show the velocity outputs for each dof.
-
Green and brown show the acceleration outputs for each dof.
-
NOTE: When the constraints are changed in a way such that the velocity is coming from a higher value to lower value then make sure to put the right values in contraints otherwise it may cause a little bit of overshoot or oscillation and sometimes the sync can be a little off so make sure the Constraints values are set accordingly.
Its pure game of right Constraints values.
Let's see how we can do that
- Refer to the coded examples in bin folder to get proper understanding of how to do things this is just sample snippet.
// setting up the initial contraints
constraints.sampling_rate = 0.001;
constraints.max_velocity = 2.0; // rad/s
constraints.min_velocity = -2.0;
constraints.max_acceleration = 2.0; // rad/s^2
constraints.min_acceleration = -2.0;
constraints.max_jerk = 4.0; // rad/s^3
constraints.min_jerk = -4.0;
// go to the target with the constraints sets above
if ( t > 0 && t < 6 ) {
target = { 5,2 };
}
// setting new target and modifying the constraints
else if ( t > 6 && t < 10 ) {
target = { 0,0 };
constraints.sampling_rate = 0.001;
constraints.max_velocity = 1.0;
constraints.min_velocity = -1.0;
constraints.max_acceleration = 2.0;
constraints.min_acceleration = -2.0;
constraints.max_jerk = 4.0;
constraints.min_jerk = -4.0;
}
// setting new target and modifying the constraints
else if ( t > 10 && t < 25 ) {
target = { -7,-4 };
constraints.sampling_rate = 0.001;
constraints.max_velocity = 1.5;
constraints.min_velocity = -1.5;
constraints.max_acceleration = 2.7;
constraints.min_acceleration = -2.7;
constraints.max_jerk = 3.0;
constraints.min_jerk = -3.0;
}
// setting new target and modifying the constraints
else if ( t > 25 && t < 45 ) {
target = { 1,1 };
constraints.sampling_rate = 0.001;
constraints.max_velocity = 1.0;
constraints.min_velocity = -1.0;
constraints.max_acceleration = 1.0;
constraints.min_acceleration = -1.0;
constraints.max_jerk = 4.0;
constraints.min_jerk = -4.0;
}
else {
target = { 0,0 };
}
Okay ,so what we got?
- Smooth motion ✅🚀
- Constraints respected ✅🚀
- Targets updates handled properly ✅🚀
- Synchronized motion ✅🚀
Woahhhh!🚀 What's next?
Show us what more you got Chorus!
What about changing the target and constraints together? 🤔
- Haah! Too easy
- Here we goooo

- Blue and red curves show the position outputs for each dof.
- Orange and purple curves show the velocity outputs for each dof.
- Green and brown show the acceleration outputs for each dof.
Let's see how we can do that
- Refer to the coded examples in bin folder to get proper understanding of how to do things this is just sample snippet.
// setting up the initial contraints
constraints.sampling_rate = 0.001;
constraints.max_velocity = 2.0; // rad/s
constraints.min_velocity = -2.0;
constraints.max_acceleration = 2.0; // rad/s^2
constraints.min_acceleration = -2.0;
constraints.max_jerk = 4.0; // rad/s^3
constraints.min_jerk = -4.0;
// go to the target with the constraints sets above
if ( t > 0 && t < 10 ) {
target = { 5,2 };
}
// setting new target
else if ( t > 10 && t < 15 ) {
target = { 0,0 };
}
// setting new target and modifying the constraints
else if ( t > 15 && t < 25 ) {
target = { -7,-4 };
constraints.max_velocity = 1.0;
constraints.min_velocity = -1.0;
constraints.max_acceleration = 0.9;
constraints.min_acceleration = -0.9;
constraints.max_jerk = 1.5;
constraints.min_jerk = -1.5;
}
// setting new target
else if ( t > 25 && t < 45 ) {
target = { 1,1 };
}
// setting new target
else {
target = { 0,0 };
}
Okay ,so what we got?
- Smooth motion ✅🚀
- Constraints respected ✅🚀
- Targets updates handled properly ✅🚀
- Synchronized motion ✅🚀
Impressive!🤩 What about 6 DOF's??
Why not... just Do it and let's see what happens
-
And Chorus can do that too for you! 🎶

- Position plots for 6 DOF's

-
Velocity plots for 6 DOF's
Okay ,so what we got?
- Smooth motion ✅🚀
- Constraints respected ✅🚀
- Targets updates handled properly ✅🚀
- Synchronized motion ✅🚀
Let's have a quick look at the controller output when the controller is used

- Controller output for 2 dof
- The velocity plots are the controller outputs (purple and orange curves)
- The controller works on the position error between the output position and the position feedback given to Chorus
- The controller in Chorus is working as
