Files
PX4-Autopilot/docs/assets/config/mc/ThrustCurve.ipynb
T
Hamish WilleeandRamon Roche 88d623bedb Move PX4 Guide source into /docs (#24490)
* Add vitepress tree

* Update existing workflows so they dont trigger on changes in the docs path

* Add nojekyll, package.json, LICENCE etc

* Add crowdin docs upload/download scripts

* Add docs flaw checker workflows

* Used docs prefix for docs workflows

* Crowdin obvious fixes

* ci: docs move to self hosted runner

runs on a beefy server for faster builds

Signed-off-by: Ramon Roche <mrpollo@gmail.com>

* ci: don't run build action for docs or ci changes

Signed-off-by: Ramon Roche <mrpollo@gmail.com>

* ci: update runners

Signed-off-by: Ramon Roche <mrpollo@gmail.com>

* Add docs/en

* Add docs assets and scripts

* Fix up editlinks to point to PX4 sources

* Download just the translations that are supported

* Add translation sources for zh, uk, ko

* Update latest tranlsation and uorb graphs

* update vitepress to latest

---------

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
Co-authored-by: Ramon Roche <mrpollo@gmail.com>
2025-03-13 16:08:27 +11:00

111 KiB

In [1]:
import pandas as pd
import numpy as np
from scipy import optimize
from functools import partial
from pathlib import Path

import matplotlib.pyplot as plt
In [2]:
plt.rcParams['figure.figsize'] = 8, 5
plt.rcParams['axes.grid'] = True
plt.rcParams['figure.dpi'] = 96
plt.rcParams['savefig.dpi'] = 240
In [3]:
FILENAMES = 'RampTest_2019-10-03_*.csv'
PWM_MIN, PWM_MAX = 1000, 1850
PWM_MASK_MIN, PWM_MASK_MAX = 1000, 1850
In [4]:
def read_file(fname):
    rcb = pd.read_csv(fname, index_col='Time (s)')
    rcb.index = pd.TimedeltaIndex(rcb.index, unit='s')
    return rcb

def thrust_model_func(pwm, α, k):
    pwm_rel = (pwm - PWM_MIN) / (PWM_MAX - PWM_MIN)
    return α * (k * pwm_rel**2 + (1-k) * pwm_rel)
In [5]:
fig, ax = plt.subplots()
pwm_space = np.linspace(PWM_MASK_MIN, PWM_MASK_MAX)

for i, fname in enumerate(sorted(Path().glob(FILENAMES))):
    rcb = read_file(fname)

    V = rcb.loc[rcb['Motor Electrical Speed (RPM)'] < 10, 'Voltage (V)'].mean()
    pwm = rcb['ESC signal (µs)']
    thrust = rcb['Thrust (kgf)']
    mask = (pwm >= PWM_MASK_MIN) & (pwm <= PWM_MASK_MAX)

    (α, k), _ = optimize.curve_fit(thrust_model_func, pwm[mask], thrust[mask])
    thrust_model = partial(thrust_model_func, α=α, k=k)
    
    c = f'C{i}'

    ax.plot(pwm, thrust, '.', color=c)
    ax.plot(pwm_space, thrust_model(pwm_space), '-', color=c,
            label=f"{V:.1f} V (α={α:.2f}, k={k:.2f})")

ax.set_xlabel("ESC PWM Signal in µs")
ax.set_ylabel("Propeller Thrust in kgf")

ax.set_title("PX4 Thrust Curve Compensation")
ax.legend()
fig.tight_layout()
fig.savefig("px4-thrust-curve-compensation")