Source code for pySimBlocks.gui.blocks.controllers.pid
# ******************************************************************************
# pySimBlocks
# Copyright (c) 2026 Université de Lille & INRIA
# ******************************************************************************
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
# for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# ******************************************************************************
# Authors: see Authors.txt
# ******************************************************************************
from typing import Any, Dict
from pySimBlocks.gui.blocks.block_meta import BlockMeta
from pySimBlocks.gui.blocks.parameter_meta import ParameterMeta
from pySimBlocks.gui.blocks.port_meta import PortMeta
[docs]
class PIDMeta(BlockMeta):
"""Describe the GUI metadata of the discrete PID controller block."""
def __init__(self):
"""Initialize PID block metadata.
Args:
None.
Raises:
None.
"""
self.name = "PID"
self.category = "controllers"
self.type = "pid"
self.summary = "Discrete SISO PID controller."
self.description = (
"$$\n"
"u[k] = K_p e[k] + K_i x_i[k] + K_d \frac{e[k]-e[k-1]}{dt}\n"
"$$\n"
)
self.parameters = [
ParameterMeta(
name="controller",
type="enum",
required=True,
autofill=True,
default="PID",
enum=["P", "I", "PI", "PD", "PID"]
),
ParameterMeta(
name="Kp",
type="scalar",
autofill=True,
default=1.0,
description="Proportionnal gain."
),
ParameterMeta(
name="Ki",
type="scalar",
default=1.0,
description="Integral gain."
),
ParameterMeta(
name="Kd",
type="scalar",
default=1.0,
description="Derivative gain."
),
ParameterMeta(
name="integration_method",
type="enum",
default="euler forward",
enum=["euler forward", "euler backward"]
),
ParameterMeta(
name="u_min",
type="scalar"
),
ParameterMeta(
name="u_max",
type="scalar"
),
ParameterMeta(
name="sample_time",
type="float"
)
]
self.inputs = [
PortMeta(
name="e",
display_as="e",
shape=[1, 1],
description="Error signal."
)
]
self.outputs = [
PortMeta(
name="u",
display_as="u",
shape=[1, 1],
description="Control command."
)
]
# --------------------------------------------------------------------------
# Public Methods
# --------------------------------------------------------------------------
[docs]
def is_parameter_active(self, param_name: str, instance_params: Dict[str, Any]) -> bool:
"""Return whether a PID parameter is active for the selected controller mode.
Args:
param_name: Parameter name to test.
instance_params: Current instance parameter values.
Returns:
True if the parameter should be shown.
"""
if param_name == "Kp":
return instance_params["controller"] in ["P", "PI", "PD", "PID"]
elif param_name == "Ki":
return instance_params["controller"] in ["I", "PI", "PID"]
elif param_name == "Kd":
return instance_params["controller"] in ["PD", "PID"]
return super().is_parameter_active(param_name, instance_params)