Quick Start Guide#

This guide will help you get started with Qontrol quickly.

Basic Concepts#

Qontrol is built around three main concepts:

  1. Model: Represents the robot kinematic/dynamic model

  2. Problem: Defines the control problem (velocity, acceleration, or torque)

  3. Tasks & Constraints: Define what you want the robot to do and what limits to respect

Simple Velocity Control Example#

Below are simple examples of velocity control in both Python and C++.

import qontrol
import numpy as np

# 1. Load robot model from URDF
# Ensure you have a valid URDF file
urdf_path = "path/to/robot.urdf"
model = qontrol.RobotModel.load_from_file(urdf_path)

# 2. Create a velocity control problem
# (Uses qpmad solver by default if available)
problem = qontrol.JointVelocityProblem(model)

# 3. Create and add a Cartesian velocity task
# Tasks are added via the problem's task_set
task = problem.task_set.add_cartesian_velocity("main_task", 1.0)

# 4. Add joint velocity limits as constraints
# Constraints are added via the problem's constraint_set
constraint = problem.constraint_set.add_joint_velocity("joint_limits")

# Define desired Cartesian velocity for end-effector
# Format: [vx, vy, vz, wx, wy, wz] (linear and angular velocities)
desired_twist = np.array([0.1, 0.0, 0.0, 0.0, 0.0, 0.0])

# Simulation / Control Loop
dt = 0.001

# Update robot state (pseudo-code)
# You would typically get q (positions) and dq (velocities) from your robot
state = qontrol.RobotState()
state.resize(model.get_nr_of_degrees_of_freedom())
# state.joint_position = ...
# state.joint_velocity = ...
model.set_robot_state(state)

# Set task target
task.set_target_velocity(desired_twist)

# Update the problem and solve it
problem.update(dt)

if problem.solution_found():
    # Get computed joint velocities
    dq_cmd = problem.get_joint_velocity_command()
    print("Joint velocity command:", dq_cmd)
#include <Qontrol/Qontrol.hpp>
#include <iostream>

using namespace Qontrol;

int main() {
    // 1. Load robot model from URDF
    std::string urdf_path = "path/to/robot.urdf";
    auto model = Model::RobotModel::loadModelFromFile(urdf_path);

    // 2. Create a velocity control problem
    auto problem = std::make_shared<JointVelocityProblem>(model);

    // 3. Create and add a Cartesian velocity task
    auto task = problem->task_set->add<Task::CartesianVelocity>("main_task");

    // 4. Add joint velocity limits
    auto constraint = problem->constraint_set->add<Constraint::JointVelocity>("joint_limits");

    // Define desired Cartesian velocity
    Eigen::VectorXd desired_twist(6);
    desired_twist << 0.1, 0.0, 0.0, 0.0, 0.0, 0.0;

    double dt = 0.001;

    // Update robot state (pseudo-code)
    RobotState state;
    state.resize(model->getNrOfDegreesOfFreedom());
    // state.joint_position = ...
    model->setRobotState(state);

    // Set task target
    task->setTargetVelocity(desired_twist);

    // Update the problem and solve it
    problem->update(dt);

    if (problem->solutionFound()) {
        Eigen::VectorXd dq_cmd = problem->getJointVelocityCommand();
        std::cout << "Joint velocity command: " << dq_cmd.transpose() << std::endl;
    }

    return 0;
}

Adding Constraints#

Constraints are hard limits that must always be satisfied:

# Joint position limits
pos_constraint = qontrol.JointPositionLimits(model)
pos_constraint.set_limits(q_min, q_max)
problem.add_constraint(pos_constraint)

# Joint velocity limits
vel_constraint = qontrol.JointVelocityLimits(model)
vel_constraint.set_limits(v_min, v_max)
problem.add_constraint(vel_constraint)

Acceleration Control#

For acceleration control:

# Create acceleration problem
problem = qontrol.AccelerationProblem(model)

# Add Cartesian acceleration task
task = qontrol.CartesianAccelerationTask(model)
task.set_desired_acceleration(desired_acc)
problem.add_task(task)

# Solve
solution = problem.update(dt)
joint_accelerations = solution.get_joint_velocity_command()

Torque Control#

For torque control (requires dynamic model):

# Create torque problem
problem = qontrol.TorqueProblem(model)

# Add joint torque task
task = qontrol.JointTorqueTask(model)
task.set_desired_torque(desired_torques)
problem.add_task(task)

# Add torque limits
constraint = qontrol.JointTorqueLimits(model)
constraint.set_limits(tau_min, tau_max)
problem.add_constraint(constraint)

# Solve
solution = problem.update(dt)
joint_torques = solution.get_joint_torque_command()

Next Steps#