Lower limb exosuit hip controller.
Project description
hip-controller
Simple README.md for a Python project template.
Install
To install the library from PyPI:
uv pip install hip-controller==latest
OR
uv add git+https://github.com/TUM-Aries-Lab/hip-controller.git@<specific-tag> # needs credentials
Development
- Install uv from Astral.
git clone git@github.com:TUM-Aries-Lab/hip-controller.gitmake initto create the virtual environment and install dependenciesmake formatto format the code and check for errorsmake testto run the test suitemake cleanto delete the temporary files and directories
Publishing
It's super easy to publish your own packages on PyPI. To build and publish this package, run:
- Update the version number in pyproject.toml and imu_module/init.py
- Commit your changes and add a
git tag <new.version.number> - Push the tag
git push --tag
uv build
uv publish # make sure your version in pyproject.toml is updated
or
Update the version number in pyproject.toml and imu_module/__init__.py
Commit your changes and add a git tag v<new.version.number>
Push the tag git push --tag
The package can then be found at: https://pypi.org/project/hip-controller
## Module Usage
```python
"""Basic docstring for my module."""
from loguru import logger
from hip_controller import definitions
def main() -> None:
"""Run a simple demonstration."""
logger.info("Hello World!")
if __name__ == "__main__":
main()
Program Usage
uv run python -m hip_controller
To use plotting via PyQt6:
On linux computer, edit the Jetson entry in .ssh/config or $HOME\.ssh\config on Windows (to be verified)
Host jetson
HostName 10.183.230.183
User aries-orin-1
ForwardX11 yes
ForwardX11Trusted yes
Then (in VSCode) run this in the remote terminal:
echo $DISPLAY
Which should show: (if empty, then forwarding is not working properly)
localhost:10.0
To run PyQT6 on the Jetson, it also needs to install libxcb-cursor-dev with:
sudo apt-get install -y libxcb-cursor-dev
Introduction
The hip-controller is a Python-based control system designed for lower limb exosuits, specifically targeting hip assistance during gait. It integrates sensor data processing, real-time gait phase detection, and adaptive assistance control to enhance mobility and reduce energy expenditure for users.
Key components include:
- Signal Processing: Filters and preprocessors for IMU and other sensor data.
- Gait Phase Control: Detection of stride events, motion state machines, and steady-state tracking.
- Assistance Control: PID controllers, amplitude modulation, and mid-level control strategies.
- Plotting and Simulation: Tools for visualization, live plotting, and offline simulation.
This project is developed as part of research at TUM-Aries-Lab, focusing on exoskeleton technology for rehabilitation and assistance.
Features
- Real-time sensor data preprocessing with filters like Kalman, notch, and low-pass filters.
- Gait phase estimation using motion state machines and stride event detection.
- Adaptive assistance control with PID and amplitude modulation.
- Visualization tools for phase portraits, comparison plots, and CSV playback.
- Comprehensive test suite for validation.
- Docker support for containerized deployment.
Requirements
- Python 3.11 to 3.13
- Dependencies managed via
uv(seepyproject.tomlfor details) - Optional: MATLAB for simulation files (not required for Python usage)
Installation
In addition to the PyPI installation mentioned above, for development:
- Ensure
uvis installed. - Clone the repository.
- Run
make initto set up the virtual environment and install dependencies.
For Docker usage:
docker build -t hip-controller .
docker run hip-controller
How to Import
Import the main module:
from hip_controller import definitions
Import specific components:
from hip_controller.control.app import AppController
from hip_controller.control.signal_processing.kalman_filter import KalmanFilter
from hip_controller.plotter.simulator import Simulator
Architecture and Flow
The hip-controller follows a modular architecture:
- Data Input: Sensor data (e.g., IMU angles, velocities) from CSV files or live sources.
- Preprocessing: Apply filters (second-order low pass, notch, sogi-fll) to clean the data.
- Gait Phase Detection: Use state machines and event detectors to identify phases (stance, swing).
- Control Calculation: Compute assistance motor command using PID controllers and modulation.
- Output: Generate control signals for the exosuit actuators.
- Visualization: Plot results in real-time or from recorded data.
The main entry point is app.py in the control module, which orchestrates the flow.
Usage
Basic Program Usage
Run the main application:
from hip_controller.control.app import WalkOnController
from hip_controller.definitions import SensorSignal
logger.info("Initializing the lower limb controller.")
self.controller_left = WalkOnController(reverse=False, plot=False)
self.controller_right = WalkOnController(reverse=True, plot=False)
while True:
signal_left = SensorSignal(timestamp=timestamp_left, angle_rad=data_left.quat.to_euler(seq="xyz").z, velocity_rad_per_sec=data_left.device_data.gyro.z)
signal_right = SensorSignal(timestamp=timestamp_right, angle_rad=data_right.quat.to_euler(seq="xyz").z, velocity_rad_per_sec=data_right.device_data.gyro.z)
command_left = self.controller_left.step(curr_signal=signal_left)
command_right = self.controller_right.step(curr_signal=signal_left)
motor_left.set_velocity(command_left)
motor_right.set_velocity(command_right)
time.sleep(0.01)
Module Usage Examples
Preprocessing Raw Sensor Data
from hip_controller.control.signal_processing.sensor_preprocessor import SensorPreprocessor
from hip_controller.definitions import PreprocessorConfig, SensorSignal
# Initialize preprocessor with default config
preprocessor = SensorPreprocessor(config=PreprocessorConfig())
# Raw sensor signal
raw_signal = SensorSignal(timestamp=0.01, angle_rad=0.5, velocity_rad_per_sec=1.2)
# Get filtered angle and estimated velocity
processed_signal = preprocessor.filter(raw_signal)
Computing Gait Phase
from hip_controller.control.gait_phase_control.gait_controller import GaitController
from hip_controller.definitions import SensorSignal
# Initialize gait controller
gait_controller = GaitController()
# Sensor signals with angle and velocity
signal1 = SensorSignal(timestamp=0.01, angle_rad=0.1, velocity_rad_per_sec=0.5)
signal2 = SensorSignal(timestamp=0.02, angle_rad=0.15, velocity_rad_per_sec=0.8)
# Update and compute gait phase
gait_phase1 = gait_controller.update_and_compute(signal1)
gait_phase2 = gait_controller.update_and_compute(signal2)
Computing Motor Command Velocity with Assistance Controller
from hip_controller.control.assistance_control.assistance_controller import MotionReferenceController
from hip_controller.control.assistance_control.amplitude_modulation import LevelGroundMode
# Initialize controllers
motion_controller = MotionReferenceController()
amplitude_mode = LevelGroundMode()
# Compute motor command (position reference)
motor_command = motion_controller.compute_motor_command(gait_phase, amplitude)
Using PID Controller for Velocity Control
from hip_controller.control.assistance_control.pid_controller import PIDController
from hip_controller.definitions import PIDConfig, LowPassFilterConfig, SolverType
# Initialize PID config
pid_config = PIDConfig(
proportional_gain=1.0,
integral_gain=0.1,
derivative_gain=0.05,
output_limits=(-10.0, 10.0)
)
filter_config = LowPassFilterConfig(
wn=20.0, zt=1.0, x0=0.0, solver_type=SolverType.RK4
)
pid_controller = PIDController(pid_config, filter_config)
# Example: motor reference position and current position
timestamp = 0.01
motor_reference = 1.0
motor_position = 0.8
# Compute velocity command
velocity_command = pid_controller.pid_tuning(timestamp, motor_reference, motor_position)
Plotting with Simulator
from hip_controller.plotter.simulator import simulate_comparison_dynamic
from pathlib import Path
from hip_controller.definitions import DATA_DIR
# Example: simulate motion mapping comparison
def motion_mapping_func(value):
# Simplified example
return value * 0.5, None
csv_path = DATA_DIR / "sensor_data" / "look_up_table_2026_02_25.csv"
simulate_comparison_dynamic(
input_name="motion_mapping_key",
expected_output_name="motion_mapping_value",
func=motion_mapping_func,
path=csv_path
)
Using the Main Exosuit Controller
from hip_controller.control.app import ExoController
from hip_controller.definitions import ExosuitData, SensorSignal
# Initialize the main controller
controller = ExoController()
# Example sensor data for left and right limbs
left_signal = SensorSignal(timestamp=0.01, angle_rad=0.2, velocity_rad_per_sec=0.5)
right_signal = SensorSignal(timestamp=0.01, angle_rad=0.1, velocity_rad_per_sec=0.3)
sensor_data = ExosuitData(timestamp=0.01, left=left_signal, right=right_signal)
# Step the controller to compute motor commands
controller.step(sensor_data)
# Motor commands are computed internally; access via controller.left_controller.step() or similar for individual limbs
Using a Single Limb Controller
from hip_controller.control.app import WalkOnController
from hip_controller.definitions import SensorSignal
# Initialize for left limb (reverse=False for left, True for right if needed)
limb_controller = WalkOnController(reverse=False, plot=False)
# Sensor signal
signal = SensorSignal(timestamp=0.01, angle_rad=0.2, velocity_rad_per_sec=0.5)
# Compute motor command
motor_command = limb_controller.step(signal)
Structure
The following tree shows the important permanent files. Run make tree to update.
├── data
│ ├── evaluation_raw_data
│ │ ├── incline_walk
│ │ │ ├── incline_walk_10
│ │ │ │ ├── AB01_incline_walk_2_down10_angle.csv
│ │ │ │ ├── AB01_incline_walk_2_up10_angle.csv
│ │ │ │ ├── AB02_incline_walk_2_down10_angle.csv
│ │ │ │ ├── AB02_incline_walk_2_up10_angle.csv
│ │ │ │ ├── AB03_incline_walk_2_down10_angle.csv
│ │ │ │ ├── AB03_incline_walk_2_up10_angle.csv
│ │ │ │ ├── AB05_incline_walk_2_down10_angle.csv
│ │ │ │ ├── AB05_incline_walk_2_up10_angle.csv
│ │ │ │ ├── AB06_incline_walk_2_down10_angle.csv
│ │ │ │ ├── AB06_incline_walk_2_up10_angle.csv
│ │ │ │ ├── AB07_incline_walk_2_angle.csv
│ │ │ │ ├── AB08_incline_walk_2_down10_angle.csv
│ │ │ │ ├── AB08_incline_walk_2_up10_angle.csv
│ │ │ │ ├── AB09_incline_walk_2_down10_angle.csv
│ │ │ │ ├── AB09_incline_walk_2_up10_angle.csv
│ │ │ │ ├── AB10_incline_walk_2_down10_angle.csv
│ │ │ │ ├── AB10_incline_walk_2_up10_angle.csv
│ │ │ │ ├── AB11_incline_walk_2_down10_angle.csv
│ │ │ │ ├── AB11_incline_walk_2_up10_angle.csv
│ │ │ │ ├── AB12_incline_walk_2_down10_angle.csv
│ │ │ │ ├── AB12_incline_walk_2_up10_angle.csv
│ │ │ │ ├── AB13_incline_walk_2_down10_angle.csv
│ │ │ │ └── AB13_incline_walk_2_up10_angle.csv
│ │ │ └── incline_walk_5
│ │ │ ├── AB01_incline_walk_1_down5_angle.csv
│ │ │ ├── AB01_incline_walk_1_up5_angle.csv
│ │ │ ├── AB02_incline_walk_1_down5_angle.csv
│ │ │ ├── AB02_incline_walk_1_up5_angle.csv
│ │ │ ├── AB03_incline_walk_1_down5_angle.csv
│ │ │ ├── AB03_incline_walk_1_up5_angle.csv
│ │ │ ├── AB05_incline_walk_1_down5_angle.csv
│ │ │ ├── AB05_incline_walk_1_up5_angle.csv
│ │ │ ├── AB06_incline_walk_1_down5_angle.csv
│ │ │ ├── AB06_incline_walk_1_up5_angle.csv
│ │ │ ├── AB07_incline_walk_1_angle.csv
│ │ │ ├── AB08_incline_walk_1_down5_angle.csv
│ │ │ ├── AB08_incline_walk_1_up5_angle.csv
│ │ │ ├── AB09_incline_walk_1_down5_angle.csv
│ │ │ ├── AB09_incline_walk_1_up5_angle.csv
│ │ │ ├── AB10_incline_walk_1_down5_angle.csv
│ │ │ ├── AB10_incline_walk_1_up5_angle.csv
│ │ │ ├── AB11_incline_walk_1_down5_angle.csv
│ │ │ ├── AB11_incline_walk_1_up5_angle.csv
│ │ │ ├── AB12_incline_walk_1_down5_angle.csv
│ │ │ ├── AB12_incline_walk_1_up5_angle.csv
│ │ │ ├── AB13_incline_walk_1_down5_angle.csv
│ │ │ └── AB13_incline_walk_1_up5_angle.csv
│ │ ├── incline_walk_combined
│ │ │ ├── AB01_incline_walk_10_combined.csv
│ │ │ ├── AB01_incline_walk_5_combined.csv
│ │ │ ├── AB02_incline_walk_10_combined.csv
│ │ │ ├── AB02_incline_walk_5_combined.csv
│ │ │ ├── AB03_incline_walk_10_combined.csv
│ │ │ ├── AB03_incline_walk_5_combined.csv
│ │ │ ├── AB05_incline_walk_10_combined.csv
│ │ │ ├── AB05_incline_walk_5_combined.csv
│ │ │ ├── AB06_incline_walk_10_combined.csv
│ │ │ ├── AB06_incline_walk_5_combined.csv
│ │ │ ├── AB07_incline_walk_10_combined.csv
│ │ │ ├── AB07_incline_walk_5_combined.csv
│ │ │ ├── AB08_incline_walk_10_combined.csv
│ │ │ ├── AB08_incline_walk_5_combined.csv
│ │ │ ├── AB09_incline_walk_10_combined.csv
│ │ │ ├── AB09_incline_walk_5_combined.csv
│ │ │ ├── AB10_incline_walk_10_combined.csv
│ │ │ ├── AB10_incline_walk_5_combined.csv
│ │ │ ├── AB11_incline_walk_10_combined.csv
│ │ │ ├── AB11_incline_walk_5_combined.csv
│ │ │ ├── AB12_incline_walk_10_combined.csv
│ │ │ ├── AB12_incline_walk_5_combined.csv
│ │ │ ├── AB13_incline_walk_10_combined.csv
│ │ │ └── AB13_incline_walk_5_combined.csv
│ │ ├── normal_walk
│ │ │ ├── normal_walk_0_6
│ │ │ │ ├── AB01_normal_walk_1_0-6_angle.csv
│ │ │ │ ├── AB02_normal_walk_1_0-6_angle.csv
│ │ │ │ ├── AB03_normal_walk_1_0-6_angle.csv
│ │ │ │ ├── AB05_normal_walk_1_0-6_angle.csv
│ │ │ │ ├── AB06_normal_walk_1_0-6_angle.csv
│ │ │ │ ├── AB08_normal_walk_1_0-6_angle.csv
│ │ │ │ ├── AB09_normal_walk_1_0-6_angle.csv
│ │ │ │ ├── AB10_normal_walk_1_0-6_angle.csv
│ │ │ │ ├── AB11_normal_walk_1_0-6_angle.csv
│ │ │ │ ├── AB12_normal_walk_1_0-6_angle.csv
│ │ │ │ └── AB13_normal_walk_1_0-6_angle.csv
│ │ │ ├── normal_walk_1_2
│ │ │ │ ├── AB01_normal_walk_1_1-2_angle.csv
│ │ │ │ ├── AB02_normal_walk_1_1-2_angle.csv
│ │ │ │ ├── AB03_normal_walk_1_1-2_angle.csv
│ │ │ │ ├── AB05_normal_walk_1_1-2_angle.csv
│ │ │ │ ├── AB06_normal_walk_1_1-2_angle.csv
│ │ │ │ ├── AB08_normal_walk_1_1-2_angle.csv
│ │ │ │ ├── AB09_normal_walk_1_1-2_angle.csv
│ │ │ │ ├── AB10_normal_walk_1_1-2_angle.csv
│ │ │ │ ├── AB11_normal_walk_1_1-2_angle.csv
│ │ │ │ ├── AB12_normal_walk_1_1-2_angle.csv
│ │ │ │ └── AB13_normal_walk_1_1-2_angle.csv
│ │ │ └── normal_walk_1_8
│ │ │ ├── AB01_normal_walk_1_1-8_angle.csv
│ │ │ ├── AB02_normal_walk_1_1-8_angle.csv
│ │ │ ├── AB03_normal_walk_1_1-8_angle.csv
│ │ │ ├── AB05_normal_walk_1_1-8_angle.csv
│ │ │ ├── AB06_normal_walk_1_1-8_angle.csv
│ │ │ ├── AB08_normal_walk_1_1-8_angle.csv
│ │ │ ├── AB09_normal_walk_1_1-8_angle.csv
│ │ │ ├── AB10_normal_walk_1_1-8_angle.csv
│ │ │ ├── AB11_normal_walk_1_1-8_angle.csv
│ │ │ ├── AB12_normal_walk_1_1-8_angle.csv
│ │ │ └── AB13_normal_walk_1_1-8_angle.csv
│ │ ├── parsing_mat
│ │ │ ├── incline_walk_10
│ │ │ │ ├── 01
│ │ │ │ │ ├── incline_walk_2_down10_parsing.mat
│ │ │ │ │ └── incline_walk_2_up10_parsing.mat
│ │ │ │ ├── 02
│ │ │ │ │ ├── incline_walk_2_down10_parsing.mat
│ │ │ │ │ └── incline_walk_2_up10_parsing.mat
│ │ │ │ ├── 03
│ │ │ │ │ ├── incline_walk_2_down10_parsing.mat
│ │ │ │ │ └── incline_walk_2_up10_parsing.mat
│ │ │ │ ├── 05
│ │ │ │ │ ├── incline_walk_2_down10_parsing.mat
│ │ │ │ │ └── incline_walk_2_up10_parsing.mat
│ │ │ │ ├── 06
│ │ │ │ │ ├── incline_walk_2_down10_parsing.mat
│ │ │ │ │ └── incline_walk_2_up10_parsing.mat
│ │ │ │ ├── 08
│ │ │ │ │ ├── incline_walk_2_down10_parsing.mat
│ │ │ │ │ └── incline_walk_2_up10_parsing.mat
│ │ │ │ ├── 09
│ │ │ │ │ ├── incline_walk_2_down10_parsing.mat
│ │ │ │ │ └── incline_walk_2_up10_parsing.mat
│ │ │ │ ├── 10
│ │ │ │ │ ├── incline_walk_2_down10_parsing.mat
│ │ │ │ │ └── incline_walk_2_up10_parsing.mat
│ │ │ │ ├── 11
│ │ │ │ │ ├── incline_walk_2_down10_parsing.mat
│ │ │ │ │ └── incline_walk_2_up10_parsing.mat
│ │ │ │ ├── 12
│ │ │ │ │ ├── incline_walk_2_down10_parsing.mat
│ │ │ │ │ └── incline_walk_2_up10_parsing.mat
│ │ │ │ └── 13
│ │ │ │ ├── incline_walk_2_down10_parsing.mat
│ │ │ │ └── incline_walk_2_up10_parsing.mat
│ │ │ ├── incline_walk_5
│ │ │ │ ├── 01
│ │ │ │ │ ├── incline_walk_1_down5_parsing.mat
│ │ │ │ │ └── incline_walk_1_up5_parsing.mat
│ │ │ │ ├── 02
│ │ │ │ │ ├── incline_walk_1_down5_parsing.mat
│ │ │ │ │ └── incline_walk_1_up5_parsing.mat
│ │ │ │ ├── 03
│ │ │ │ │ ├── incline_walk_1_down5_parsing.mat
│ │ │ │ │ └── incline_walk_1_up5_parsing.mat
│ │ │ │ ├── 05
│ │ │ │ │ ├── incline_walk_1_down5_parsing.mat
│ │ │ │ │ └── incline_walk_1_up5_parsing.mat
│ │ │ │ ├── 06
│ │ │ │ │ ├── incline_walk_1_down5_parsing.mat
│ │ │ │ │ └── incline_walk_1_up5_parsing.mat
│ │ │ │ ├── 08
│ │ │ │ │ ├── incline_walk_1_down5_parsing.mat
│ │ │ │ │ └── incline_walk_1_up5_parsing.mat
│ │ │ │ ├── 09
│ │ │ │ │ ├── incline_walk_1_down5_parsing.mat
│ │ │ │ │ └── incline_walk_1_up5_parsing.mat
│ │ │ │ ├── 10
│ │ │ │ │ ├── incline_walk_1_down5_parsing.mat
│ │ │ │ │ └── incline_walk_1_up5_parsing.mat
│ │ │ │ ├── 11
│ │ │ │ │ ├── incline_walk_1_down5_parsing.mat
│ │ │ │ │ └── incline_walk_1_up5_parsing.mat
│ │ │ │ ├── 12
│ │ │ │ │ ├── incline_walk_1_down5_parsing.mat
│ │ │ │ │ └── incline_walk_1_up5_parsing.mat
│ │ │ │ └── 13
│ │ │ │ ├── incline_walk_1_down5_parsing.mat
│ │ │ │ └── incline_walk_1_up5_parsing.mat
│ │ │ ├── normal_walk_0_6
│ │ │ │ ├── 01
│ │ │ │ │ └── normal_walk_1_0-6_parsing.mat
│ │ │ │ ├── 02
│ │ │ │ │ └── normal_walk_1_0-6_parsing.mat
│ │ │ │ ├── 03
│ │ │ │ │ └── normal_walk_1_0-6_parsing.mat
│ │ │ │ ├── 05
│ │ │ │ │ └── normal_walk_1_0-6_parsing.mat
│ │ │ │ ├── 06
│ │ │ │ │ └── normal_walk_1_0-6_parsing.mat
│ │ │ │ ├── 08
│ │ │ │ │ └── normal_walk_1_0-6_parsing.mat
│ │ │ │ ├── 09
│ │ │ │ │ └── normal_walk_1_0-6_parsing.mat
│ │ │ │ ├── 10
│ │ │ │ │ └── normal_walk_1_0-6_parsing.mat
│ │ │ │ ├── 11
│ │ │ │ │ └── normal_walk_1_0-6_parsing.mat
│ │ │ │ ├── 12
│ │ │ │ │ └── normal_walk_1_0-6_parsing.mat
│ │ │ │ └── 13
│ │ │ │ └── normal_walk_1_0-6_parsing.mat
│ │ │ ├── normal_walk_1_2
│ │ │ │ ├── 01
│ │ │ │ │ └── normal_walk_1_1-2_parsing.mat
│ │ │ │ ├── 02
│ │ │ │ │ └── normal_walk_1_1-2_parsing.mat
│ │ │ │ ├── 03
│ │ │ │ │ └── normal_walk_1_1-2_parsing.mat
│ │ │ │ ├── 05
│ │ │ │ │ └── normal_walk_1_1-2_parsing.mat
│ │ │ │ ├── 06
│ │ │ │ │ └── normal_walk_1_1-2_parsing.mat
│ │ │ │ ├── 08
│ │ │ │ │ └── normal_walk_1_1-2_parsing.mat
│ │ │ │ ├── 09
│ │ │ │ │ └── normal_walk_1_1-2_parsing.mat
│ │ │ │ ├── 10
│ │ │ │ │ └── normal_walk_1_1-2_parsing.mat
│ │ │ │ ├── 11
│ │ │ │ │ └── normal_walk_1_1-2_parsing.mat
│ │ │ │ ├── 12
│ │ │ │ │ └── normal_walk_1_1-2_parsing.mat
│ │ │ │ └── 13
│ │ │ │ └── normal_walk_1_1-2_parsing.mat
│ │ │ ├── normal_walk_1_8
│ │ │ │ ├── 01
│ │ │ │ │ └── normal_walk_1_1-8_parsing.mat
│ │ │ │ ├── 02
│ │ │ │ │ └── normal_walk_1_1-8_parsing.mat
│ │ │ │ ├── 03
│ │ │ │ │ └── normal_walk_1_1-8_parsing.mat
│ │ │ │ ├── 05
│ │ │ │ │ └── normal_walk_1_1-8_parsing.mat
│ │ │ │ ├── 06
│ │ │ │ │ └── normal_walk_1_1-8_parsing.mat
│ │ │ │ ├── 08
│ │ │ │ │ └── normal_walk_1_1-8_parsing.mat
│ │ │ │ ├── 09
│ │ │ │ │ └── normal_walk_1_1-8_parsing.mat
│ │ │ │ ├── 10
│ │ │ │ │ └── normal_walk_1_1-8_parsing.mat
│ │ │ │ ├── 11
│ │ │ │ │ └── normal_walk_1_1-8_parsing.mat
│ │ │ │ ├── 12
│ │ │ │ │ └── normal_walk_1_1-8_parsing.mat
│ │ │ │ └── 13
│ │ │ │ └── normal_walk_1_1-8_parsing.mat
│ │ │ ├── stairs
│ │ │ │ ├── 01
│ │ │ │ │ ├── stairs_1_10_down_parsing.mat
│ │ │ │ │ ├── stairs_1_1_up_parsing.mat
│ │ │ │ │ ├── stairs_1_2_down_parsing.mat
│ │ │ │ │ ├── stairs_1_3_up_parsing.mat
│ │ │ │ │ ├── stairs_1_4_down_parsing.mat
│ │ │ │ │ ├── stairs_1_5_up_parsing.mat
│ │ │ │ │ ├── stairs_1_6_down_parsing.mat
│ │ │ │ │ ├── stairs_1_7_up_parsing.mat
│ │ │ │ │ ├── stairs_1_8_down_parsing.mat
│ │ │ │ │ └── stairs_1_9_up_parsing.mat
│ │ │ │ ├── 02
│ │ │ │ │ ├── stairs_1_10_down_parsing.mat
│ │ │ │ │ ├── stairs_1_11_up_parsing.mat
│ │ │ │ │ ├── stairs_1_12_down_parsing.mat
│ │ │ │ │ ├── stairs_1_1_up_parsing.mat
│ │ │ │ │ ├── stairs_1_2_down_parsing.mat
│ │ │ │ │ ├── stairs_1_3_up_parsing.mat
│ │ │ │ │ ├── stairs_1_4_down_parsing.mat
│ │ │ │ │ ├── stairs_1_5_up_parsing.mat
│ │ │ │ │ ├── stairs_1_5_up_segmented.mat
│ │ │ │ │ ├── stairs_1_6_down_parsing.mat
│ │ │ │ │ ├── stairs_1_7_up_parsing.mat
│ │ │ │ │ ├── stairs_1_8_down_parsing.mat
│ │ │ │ │ └── stairs_1_9_up_parsing.mat
│ │ │ │ ├── 03
│ │ │ │ │ ├── stairs_1_10_down_parsing.mat
│ │ │ │ │ ├── stairs_1_1_up_parsing.mat
│ │ │ │ │ ├── stairs_1_2_down_parsing.mat
│ │ │ │ │ ├── stairs_1_3_up_parsing.mat
│ │ │ │ │ ├── stairs_1_4_down_parsing.mat
│ │ │ │ │ ├── stairs_1_5_up_parsing.mat
│ │ │ │ │ ├── stairs_1_6_down_parsing.mat
│ │ │ │ │ ├── stairs_1_7_up_parsing.mat
│ │ │ │ │ ├── stairs_1_8_down_parsing.mat
│ │ │ │ │ └── stairs_1_9_up_parsing.mat
│ │ │ │ ├── 05
│ │ │ │ │ ├── stairs_1_10_down_parsing.mat
│ │ │ │ │ ├── stairs_1_1_up_parsing.mat
│ │ │ │ │ ├── stairs_1_2_down_parsing.mat
│ │ │ │ │ ├── stairs_1_3_up_parsing.mat
│ │ │ │ │ ├── stairs_1_4_down_parsing.mat
│ │ │ │ │ ├── stairs_1_5_up_parsing.mat
│ │ │ │ │ ├── stairs_1_6_down_parsing.mat
│ │ │ │ │ ├── stairs_1_7_up_parsing.mat
│ │ │ │ │ ├── stairs_1_8_down_parsing.mat
│ │ │ │ │ └── stairs_1_9_up_parsing.mat
│ │ │ │ ├── 06
│ │ │ │ │ ├── stairs_1_10_down_parsing.mat
│ │ │ │ │ ├── stairs_1_1_up_parsing.mat
│ │ │ │ │ ├── stairs_1_2_down_parsing.mat
│ │ │ │ │ ├── stairs_1_3_up_parsing.mat
│ │ │ │ │ ├── stairs_1_4_down_parsing.mat
│ │ │ │ │ ├── stairs_1_5_up_parsing.mat
│ │ │ │ │ ├── stairs_1_6_down_parsing.mat
│ │ │ │ │ ├── stairs_1_7_up_parsing.mat
│ │ │ │ │ ├── stairs_1_8_down_parsing.mat
│ │ │ │ │ └── stairs_1_9_up_parsing.mat
│ │ │ │ ├── 07
│ │ │ │ │ ├── stairs_1_10_down_parsing.mat
│ │ │ │ │ ├── stairs_1_1_up_parsing.mat
│ │ │ │ │ ├── stairs_1_2_down_parsing.mat
│ │ │ │ │ ├── stairs_1_3_up_parsing.mat
│ │ │ │ │ ├── stairs_1_4_down_parsing.mat
│ │ │ │ │ ├── stairs_1_5_up_parsing.mat
│ │ │ │ │ ├── stairs_1_6_down_parsing.mat
│ │ │ │ │ ├── stairs_1_7_up_parsing.mat
│ │ │ │ │ ├── stairs_1_8_down_parsing.mat
│ │ │ │ │ └── stairs_1_9_up_parsing.mat
│ │ │ │ ├── 08
│ │ │ │ │ ├── stairs_1_10_down_parsing.mat
│ │ │ │ │ ├── stairs_1_1_up_parsing.mat
│ │ │ │ │ ├── stairs_1_2_down_parsing.mat
│ │ │ │ │ ├── stairs_1_3_up_parsing.mat
│ │ │ │ │ ├── stairs_1_4_down_parsing.mat
│ │ │ │ │ ├── stairs_1_5_up_parsing.mat
│ │ │ │ │ ├── stairs_1_6_down_parsing.mat
│ │ │ │ │ ├── stairs_1_7_up_parsing.mat
│ │ │ │ │ ├── stairs_1_8_down_parsing.mat
│ │ │ │ │ └── stairs_1_9_up_parsing.mat
│ │ │ │ ├── 09
│ │ │ │ │ ├── stairs_1_10_down_parsing.mat
│ │ │ │ │ ├── stairs_1_1_up_parsing.mat
│ │ │ │ │ ├── stairs_1_2_down_parsing.mat
│ │ │ │ │ ├── stairs_1_3_up_parsing.mat
│ │ │ │ │ ├── stairs_1_4_down_parsing.mat
│ │ │ │ │ ├── stairs_1_5_up_parsing.mat
│ │ │ │ │ ├── stairs_1_6_down_parsing.mat
│ │ │ │ │ ├── stairs_1_7_up_parsing.mat
│ │ │ │ │ ├── stairs_1_8_down_parsing.mat
│ │ │ │ │ └── stairs_1_9_up_parsing.mat
│ │ │ │ ├── 10
│ │ │ │ │ ├── stairs_1_10_down_parsing.mat
│ │ │ │ │ ├── stairs_1_1_up_parsing.mat
│ │ │ │ │ ├── stairs_1_2_down_parsing.mat
│ │ │ │ │ ├── stairs_1_3_up_parsing.mat
│ │ │ │ │ ├── stairs_1_4_down_parsing.mat
│ │ │ │ │ ├── stairs_1_5_up_parsing.mat
│ │ │ │ │ ├── stairs_1_6_down_parsing.mat
│ │ │ │ │ ├── stairs_1_7_up_parsing.mat
│ │ │ │ │ ├── stairs_1_8_down_parsing.mat
│ │ │ │ │ └── stairs_1_9_up_parsing.mat
│ │ │ │ ├── 11
│ │ │ │ │ ├── stairs_1_10_down_parsing.mat
│ │ │ │ │ ├── stairs_1_1_up_parsing.mat
│ │ │ │ │ ├── stairs_1_2_down_parsing.mat
│ │ │ │ │ ├── stairs_1_3_up_parsing.mat
│ │ │ │ │ ├── stairs_1_4_down_parsing.mat
│ │ │ │ │ ├── stairs_1_5_up_parsing.mat
│ │ │ │ │ ├── stairs_1_6_down_parsing.mat
│ │ │ │ │ ├── stairs_1_7_up_parsing.mat
│ │ │ │ │ ├── stairs_1_8_down_parsing.mat
│ │ │ │ │ └── stairs_1_9_up_parsing.mat
│ │ │ │ ├── 12
│ │ │ │ │ ├── stairs_1_10_down_parsing.mat
│ │ │ │ │ ├── stairs_1_11_up_parsing.mat
│ │ │ │ │ ├── stairs_1_12_down_parsing.mat
│ │ │ │ │ ├── stairs_1_1_up_parsing.mat
│ │ │ │ │ ├── stairs_1_2_down_parsing.mat
│ │ │ │ │ ├── stairs_1_3_up_parsing.mat
│ │ │ │ │ ├── stairs_1_4_down_parsing.mat
│ │ │ │ │ ├── stairs_1_5_up_parsing.mat
│ │ │ │ │ ├── stairs_1_6_down_parsing.mat
│ │ │ │ │ ├── stairs_1_7_up_parsing.mat
│ │ │ │ │ ├── stairs_1_8_down_parsing.mat
│ │ │ │ │ └── stairs_1_9_up_parsing.mat
│ │ │ │ └── 13
│ │ │ │ ├── stairs_1_10_down_parsing.mat
│ │ │ │ ├── stairs_1_1_up_parsing.mat
│ │ │ │ ├── stairs_1_2_down_parsing.mat
│ │ │ │ ├── stairs_1_3_up_parsing.mat
│ │ │ │ ├── stairs_1_4_down_parsing.mat
│ │ │ │ ├── stairs_1_5_up_parsing.mat
│ │ │ │ ├── stairs_1_6_down_parsing.mat
│ │ │ │ ├── stairs_1_7_up_parsing.mat
│ │ │ │ ├── stairs_1_8_down_parsing.mat
│ │ │ │ └── stairs_1_9_up_parsing.mat
│ │ │ ├── turn_and_step_left
│ │ │ │ ├── 01
│ │ │ │ │ └── turn_and_step_1_left-turn_parsing.mat
│ │ │ │ ├── 02
│ │ │ │ │ └── turn_and_step_1_left-turn_parsing.mat
│ │ │ │ ├── 03
│ │ │ │ │ └── turn_and_step_1_left-turn_parsing.mat
│ │ │ │ ├── 05
│ │ │ │ │ └── turn_and_step_1_left-turn_parsing.mat
│ │ │ │ ├── 06
│ │ │ │ │ └── turn_and_step_1_left-turn_parsing.mat
│ │ │ │ ├── 07
│ │ │ │ │ └── turn_and_step_1_left-turn_parsing.mat
│ │ │ │ ├── 08
│ │ │ │ │ └── turn_and_step_1_left-turn_parsing.mat
│ │ │ │ ├── 09
│ │ │ │ │ └── turn_and_step_1_left-turn_parsing.mat
│ │ │ │ ├── 10
│ │ │ │ │ └── turn_and_step_1_left-turn_parsing.mat
│ │ │ │ ├── 11
│ │ │ │ │ └── turn_and_step_1_left-turn_parsing.mat
│ │ │ │ ├── 12
│ │ │ │ │ └── turn_and_step_1_left-turn_parsing.mat
│ │ │ │ └── 13
│ │ │ │ └── turn_and_step_1_left-turn_parsing.mat
│ │ │ └── turn_and_step_right
│ │ │ ├── 01
│ │ │ │ └── turn_and_step_1_right-turn_parsing.mat
│ │ │ ├── 02
│ │ │ │ └── turn_and_step_1_right-turn_parsing.mat
│ │ │ ├── 03
│ │ │ │ └── turn_and_step_1_right-turn_parsing.mat
│ │ │ ├── 05
│ │ │ │ └── turn_and_step_1_right-turn_parsing.mat
│ │ │ ├── 06
│ │ │ │ └── turn_and_step_1_right-turn_parsing.mat
│ │ │ ├── 07
│ │ │ │ └── turn_and_step_1_right-turn_parsing.mat
│ │ │ ├── 08
│ │ │ │ └── turn_and_step_1_right-turn_parsing.mat
│ │ │ ├── 09
│ │ │ │ └── turn_and_step_1_right-turn_parsing.mat
│ │ │ ├── 10
│ │ │ │ └── turn_and_step_1_right-turn_parsing.mat
│ │ │ ├── 11
│ │ │ │ └── turn_and_step_1_right-turn_parsing.mat
│ │ │ ├── 12
│ │ │ │ └── turn_and_step_1_right-turn_parsing.mat
│ │ │ └── 13
│ │ │ └── turn_and_step_1_right-turn_parsing.mat
│ │ ├── stairs_combined
│ │ │ ├── AB01_stairs_combined.csv
│ │ │ ├── AB02_stairs_combined.csv
│ │ │ ├── AB03_stairs_combined.csv
│ │ │ ├── AB05_stairs_combined.csv
│ │ │ ├── AB06_stairs_combined.csv
│ │ │ ├── AB07_stairs_combined.csv
│ │ │ ├── AB08_stairs_combined.csv
│ │ │ ├── AB09_stairs_combined.csv
│ │ │ ├── AB10_stairs_combined.csv
│ │ │ ├── AB11_stairs_combined.csv
│ │ │ ├── AB12_stairs_combined.csv
│ │ │ └── AB13_stairs_combined.csv
│ │ └── turn_and_step
│ │ ├── turn_left
│ │ │ ├── AB01_turn_and_step_1_left-turn_angle.csv
│ │ │ ├── AB02_turn_and_step_1_left-turn_angle.csv
│ │ │ ├── AB03_turn_and_step_1_left-turn_angle.csv
│ │ │ ├── AB05_turn_and_step_1_left-turn_angle.csv
│ │ │ ├── AB06_turn_and_step_1_left-turn_angle.csv
│ │ │ ├── AB07_turn_and_step_1_left-turn_angle.csv
│ │ │ ├── AB08_turn_and_step_1_left-turn_angle.csv
│ │ │ ├── AB09_turn_and_step_1_left-turn_angle.csv
│ │ │ ├── AB10_turn_and_step_1_left-turn_angle.csv
│ │ │ ├── AB11_turn_and_step_1_left-turn_angle.csv
│ │ │ ├── AB12_turn_and_step_1_left-turn_angle.csv
│ │ │ └── AB13_turn_and_step_1_left-turn_angle.csv
│ │ └── turn_right
│ │ ├── AB01_turn_and_step_1_right-turn_angle.csv
│ │ ├── AB02_turn_and_step_1_right-turn_angle.csv
│ │ ├── AB03_turn_and_step_1_right-turn_angle.csv
│ │ ├── AB05_turn_and_step_1_right-turn_angle.csv
│ │ ├── AB06_turn_and_step_1_right-turn_angle.csv
│ │ ├── AB07_turn_and_step_1_right-turn_angle.csv
│ │ ├── AB08_turn_and_step_1_right-turn_angle.csv
│ │ ├── AB09_turn_and_step_1_right-turn_angle.csv
│ │ ├── AB10_turn_and_step_1_right-turn_angle.csv
│ │ ├── AB11_turn_and_step_1_right-turn_angle.csv
│ │ ├── AB12_turn_and_step_1_right-turn_angle.csv
│ │ └── AB13_turn_and_step_1_right-turn_angle.csv
│ ├── logs
│ └── sensor_data
│ ├── arduino2_2026_03_23.csv
│ ├── arduino_2026_03_23.csv
│ ├── data_input_2025_12_17.csv
│ ├── data_input_filtered_2026_01_09.csv
│ ├── data_kinematics_2026_02_16.csv
│ ├── data_raw_2025_12_17.xlsx
│ └── look_up_table_2026_02_25.csv
├── docs
│ ├── UML_hip_controller_2026_03_10.json
│ └── paper.pdf
├── scripts
│ ├── compare_all.py
│ ├── compare_matlab.py
│ ├── compare_matlab_module.py
│ ├── csv_converter.py
│ ├── csv_utils.py
│ ├── evaluation_matplotlib.py
│ ├── evaluation_record.py
│ ├── live_comparison_plot.py
│ ├── main.py
│ ├── mat_to_csv.py
│ ├── normalize_output_time.py
│ ├── reference_versus_calculated.py
│ ├── script.py
│ └── simulator.py
├── src
│ └── hip_controller
│ ├── control
│ │ ├── gait_phase_control
│ │ │ ├── gait_controller.py
│ │ │ ├── motion_state_machine.py
│ │ │ ├── steady_state_tracker.py
│ │ │ └── stride_event_detector.py
│ │ ├── motor_reference_control
│ │ │ ├── amplitude_modulation.py
│ │ │ ├── motor_reference_controller.py
│ │ │ └── pid_controller.py
│ │ ├── signal_processing
│ │ │ ├── drift_removal.py
│ │ │ ├── sensor_preprocessor.py
│ │ │ └── velocity_estimation.py
│ │ ├── __init__.py
│ │ └── app.py
│ ├── filters
│ │ ├── discrete_derivative_filter.py
│ │ ├── kalman_filter.py
│ │ ├── notch_filter.py
│ │ ├── second_order_low_pass_filter.py
│ │ └── sogi_fll_filter.py
│ ├── plotter
│ │ ├── csv_player.py
│ │ └── live_phase_portrait.py
│ ├── utils
│ │ ├── math_utils.py
│ │ ├── state_space.py
│ │ └── utils.py
│ ├── __init__.py
│ ├── __main__.py
│ └── definitions.py
├── tests
│ ├── controller_test
│ │ ├── assistance_testing
│ │ │ ├── amplitude_test.py
│ │ │ └── mid_level_test.py
│ │ ├── gait_phase_testing
│ │ │ ├── high_level_test.py
│ │ │ ├── motion_state_machine_test.py
│ │ │ └── stride_event_detector_test.py
│ │ ├── pre_process_testing
│ │ │ ├── drift_removal_test.py
│ │ │ ├── filtering_test.py
│ │ │ ├── kalman_test.py
│ │ │ └── second_order_lpf_test.py
│ │ ├── testing_data
│ │ │ ├── amplitude_modulation_2026_03_03.csv
│ │ │ ├── extrema_2026_01_26.csv
│ │ │ ├── filtering_2026_03_19.csv
│ │ │ ├── gait_phase_left_2026_03_03.csv
│ │ │ ├── look_up_table_2026_02_25.csv
│ │ │ ├── reference_motion_2026_03_05.csv
│ │ │ ├── reference_motion_2026_03_06.csv
│ │ │ ├── second_order_lpf_2026_03_06.csv
│ │ │ ├── stride_event_detector_2026_02_26.csv
│ │ │ ├── valid_trigger_left_2026_01_15.csv
│ │ │ └── zero_crossing_left_2026_01_09.csv
│ │ └── app_test.py
│ ├── utils_test
│ │ ├── csv_player_test.py
│ │ ├── math_utils_test.py
│ │ └── utils_test.py
│ ├── __init__.py
│ └── conftest.py
├── .darglint
├── .dockerignore
├── .gitignore
├── .pre-commit-config.yaml
├── .python-version
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE
├── Makefile
├── README.md
├── pyproject.toml
├── repo_tree.py
└── uv.lock
Contributing
Please see CONTRIBUTING.md for guidelines on contributing to this project.
License
This project is licensed under the terms specified in LICENSE.
Authors
- Tsmorz (tony.smoragiewicz@tum.de)
- Zhongge Lin (zg.lin@outlook.com)
Acknowledgments
Developed at TUM-Aries-Lab as part of research on exoskeleton control systems.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hip_controller-0.1.1.tar.gz.
File metadata
- Download URL: hip_controller-0.1.1.tar.gz
- Upload date:
- Size: 48.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c7022eb2ebdf71a0cbfec39cd3c464643ce14f296f3e4137ca88c24969950343
|
|
| MD5 |
3703f6106c95120a8b58cf3c38aafb49
|
|
| BLAKE2b-256 |
e3ea4f7a57c169b2eb0d9937252e46bd8d4e96f51961116dace825dbae546849
|
Provenance
The following attestation bundles were made for hip_controller-0.1.1.tar.gz:
Publisher:
pypi-publish.yml on TUM-Aries-Lab/hip-controller
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hip_controller-0.1.1.tar.gz -
Subject digest:
c7022eb2ebdf71a0cbfec39cd3c464643ce14f296f3e4137ca88c24969950343 - Sigstore transparency entry: 1524639072
- Sigstore integration time:
-
Permalink:
TUM-Aries-Lab/hip-controller@d4e2b16c97cd7efd08e1b833ce2916514b340e5a -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/TUM-Aries-Lab
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@d4e2b16c97cd7efd08e1b833ce2916514b340e5a -
Trigger Event:
push
-
Statement type:
File details
Details for the file hip_controller-0.1.1-py3-none-any.whl.
File metadata
- Download URL: hip_controller-0.1.1-py3-none-any.whl
- Upload date:
- Size: 53.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6e61227b1b2133a029ab27342feae5b199cddfb134b27811723f3486fb63d266
|
|
| MD5 |
f8db2e00bdf93859323078de34b329a9
|
|
| BLAKE2b-256 |
f9cc94c9baffb2b2473b3ebb3201c6d102f83f0fcb52f8d42cc51271891b7635
|
Provenance
The following attestation bundles were made for hip_controller-0.1.1-py3-none-any.whl:
Publisher:
pypi-publish.yml on TUM-Aries-Lab/hip-controller
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hip_controller-0.1.1-py3-none-any.whl -
Subject digest:
6e61227b1b2133a029ab27342feae5b199cddfb134b27811723f3486fb63d266 - Sigstore transparency entry: 1524639084
- Sigstore integration time:
-
Permalink:
TUM-Aries-Lab/hip-controller@d4e2b16c97cd7efd08e1b833ce2916514b340e5a -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/TUM-Aries-Lab
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@d4e2b16c97cd7efd08e1b833ce2916514b340e5a -
Trigger Event:
push
-
Statement type: