SkillAgentSearch skills...

Chorus

Multi-DOF Real-Time Online Trajectory Generator

Install / Use

/learn @aadi753/Chorus

README

🎼 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

Chorus Architecture

  • Blue is target position

  • Orange is output position

  • Green is output velocity

  • Red is output acceleration

  • Jerk output (Chorus outputs a constant jerk)

    Chorus Architecture

  • 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 Chorus Architecture

  • 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?

  1. Smooth motion ✅🚀
  2. Constraints respected ✅🚀
  3. Targets updates handled properly ✅🚀
  4. 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 🚀

Chorus Architecture

  • 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?

  1. Smooth motion ✅🚀
  2. Constraints respected ✅🚀
  3. Targets updates handled properly ✅🚀
  4. 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 Chorus Architecture
  • 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?

  1. Smooth motion ✅🚀
  2. Constraints respected ✅🚀
  3. Targets updates handled properly ✅🚀
  4. 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! 🎶 Chorus Architecture

    • Position plots for 6 DOF's

    Chorus Architecture

  • Velocity plots for 6 DOF's

Okay ,so what we got?

  1. Smooth motion ✅🚀
  2. Constraints respected ✅🚀
  3. Targets updates handled properly ✅🚀
  4. Synchronized motion ✅🚀

Let's have a quick look at the controller output when the controller is used

Chorus Architecture

  • 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
View on GitHub
GitHub Stars9
CategoryDevelopment
Updated2mo ago
Forks2

Languages

C++

Security Score

90/100

Audited on Jan 19, 2026

No findings