

# Generated by the protocol buffer compiler.  DO NOT EDIT!
# sources: blickfeld/percept_pipeline/config/background_subtraction.proto, blickfeld/percept_pipeline/config/classification.proto, blickfeld/percept_pipeline/config/clustering.proto, blickfeld/percept_pipeline/config/data_source.proto, blickfeld/percept_pipeline/config/disqualification.proto, blickfeld/percept_pipeline/config/history.proto, blickfeld/percept_pipeline/config/object_class.proto, blickfeld/percept_pipeline/config/object_size.proto, blickfeld/percept_pipeline/config/perception.proto, blickfeld/percept_pipeline/config/point_cloud_filter.proto, blickfeld/percept_pipeline/config/tracking.proto, blickfeld/percept_pipeline/config/zone_algorithm.proto
# plugin: python-betterproto
from dataclasses import dataclass
from typing import List

import blickfeld_qb2.betterproto as betterproto
import blickfeld_qb2.betterproto.lib.google.protobuf as betterproto_lib_google_protobuf

from ...base import (
    config as __base_config__,
    geometry as __base_geometry__,
)


class ObjectSize(betterproto.Enum):
    """The size of an object"""

    OBJECT_SIZE_UNSPECIFIED = 0
    """The zero value should not be used"""

    OBJECT_SIZE_SMALL = 1
    """Small object size: small animals, birds, etc"""

    OBJECT_SIZE_MEDIUM = 2
    """Medium object size: free standing human, single human, etc"""

    OBJECT_SIZE_LARGE = 3
    """Large object size: cars, group of people, large animals, etc"""


class ObjectClassTlsVehicle(betterproto.Enum):
    """
    Vehicle classification according to "Technische Lieferbedingungen für
    Streckenstationen " (TLS 2012) defined by the German regulatory
    "Bundesanstalt für Straßen- und Verkehrswesen" (bast).   The enum values
    directly reflect the class of the 8+1 classification.
    """

    TLS_VEHICLE_UNSPECIFIED = 0
    """The zero value should not be used."""

    TLS_VEHICLE_MOTORBIKE = 10
    """Motorbike (Krad)."""

    TLS_VEHICLE_CAR = 7
    """Standard passenger car (Pkw)."""

    TLS_VEHICLE_VAN = 11
    """Van (Lfw)."""

    TLS_VEHICLE_TRUCK = 3
    """Standard truck (Lkw)."""

    TLS_VEHICLE_TRUCK_WITH_TRAILER = 8
    """Truck towing a trailer (LkwA)."""

    TLS_VEHICLE_SEMI_TRAILER_TRUCK = 9
    """Semitrailer truck (Sattel-Kfz)."""

    TLS_VEHICLE_BUS = 5
    """Bus."""

    TLS_VEHICLE_CAR_WITH_TRAILER = 2
    """Car with trailer (PkwA)."""

    TLS_VEHICLE_OTHER = 6
    """Other or uncategorized object (nk Kfz)."""


class ClassificationModelType(betterproto.Enum):
    """Machine learning model types."""

    TYPE_UNSPECIFIED = 0
    """The zero value should not be used"""

    TYPE_SVM = 1
    """Support Vector Machine Model"""


class ClassificationModelFeatureGenerator(betterproto.Enum):
    """
    Enum specifying which feature generation method to use for ML model
    predictions.
    """

    FEATURE_GENERATOR_UNSPECIFIED = 0
    """The zero value should not be used"""

    FEATURE_GENERATOR_EIGVALS_DIMS = 1
    """
    Generate features from:  - Eigenvalues (λ1, λ2, λ3) of the 3D covariance
    matrix of the object’s point cloud.  - Object dimensions: height, width,
    and length. Resulting feature vector: [λ1, λ2, λ3, height, width, length]
    """

    FEATURE_GENERATOR_EIGVALS_DIMS_WITH_VARIANCE = 2
    """
    Generate features from:  - Eigenvalues (λ1, λ2, λ3) of the 3D covariance
    matrix.  - Object dimensions: height, width, and length.  - Per-axis
    variance: var_x, var_y, var_z. Resulting feature vector: [λ1, λ2, λ3,
    height, width, length, var_x, var_y, var_z]
    """


@dataclass(eq=False, repr=False)
class Clustering(betterproto.Message):
    """
    Algorithms for detecting objects as clustered points in the foreground
    scene.
    """

    db_scan: "ClusteringDbScan" = betterproto.message_field(1, group="clustering_type")
    """Use db-scan for clustering the foreground"""

    disable_percentile_bounding_boxes: bool = betterproto.bool_field(2)
    """
    Disabling the percentiles will lead to the dimensions being determined by
    the min and max points in each dimension.
    """


@dataclass(eq=False, repr=False)
class ClusteringDbScan(betterproto.Message):
    """
    Density-based spatial clustering algorithm using the euclidean distance
    between points
    """

    min_points: int = betterproto.uint32_field(1)
    """
    Minimum amount of points required to define an object-cluster   Reasonable
    default: 10
    """

    radius: float = betterproto.float_field(2)
    """
    Controls how far away points belonging to the same object-cluster can be.
    Reasonable default: 0.2
    """

    distance_dependent_radius: float = betterproto.float_field(3)
    """
    Multiply the given radius with the range of a point and add it to the
    radius. This significantly improves the clustering for close-range scenes.
    Reasonable default: 0.025
    """


@dataclass(eq=False, repr=False)
class BackgroundSubtraction(betterproto.Message):
    """
    Algorithms seperating the input point cloud into foreground and background.
    """

    mixture_of_gaussians: "BackgroundSubtractionMixtureOfGaussians" = (
        betterproto.message_field(1, group="background_subtraction_type")
    )
    """Use mixture of gaussians for foreground/background detection"""

    static: "BackgroundSubtractionStatic" = betterproto.message_field(
        3, group="background_subtraction_type"
    )
    """Use a static tree structure for foreground/background detection."""


@dataclass(eq=False, repr=False)
class BackgroundSubtractionMixtureOfGaussians(betterproto.Message):
    """
    Dynamic background subtraction using a mixture of gaussians. The algorithm
    automatically slowly updates the background model if the scene changes. The
    update rate is controlled via 'exponential_decay'.
    """

    num_initialization_frames: int = betterproto.uint32_field(1)
    """
    The amount of initially received frames which are used to build the
    background.   Reasonable default: 10
    """

    exponential_decay: float = betterproto.float_field(2)
    """
    Controls how fast objects switch between foreground and background.
    Exponential decay factor.   Reasonable default: 0.005
    """

    min_weight_threshold_for_background: float = betterproto.float_field(3)
    """
    Controls how much noise the background/foreground is expected to have.
    Reasonable default: 0.25
    """

    object_awareness: "BackgroundSubtractionMixtureOfGaussiansObjectAwareness" = (
        betterproto.message_field(5)
    )
    """Configure the object awareness of the background subtraction."""


@dataclass(eq=False, repr=False)
class BackgroundSubtractionMixtureOfGaussiansObjectAwareness(betterproto.Message):
    """
    The dynamic model update can depend on the detected objects. If enabled,
    the model update is freezed for areas around detected objects.   This can
    be very helpful to avoid that stalled objects, which stay in the scene for
    a while (e.g. parked cars) or objects which are following similar paths
    (e.g. persons in a hallway), cause the generation of an invalid background
    model. The dynamic model update is though still enabled for small objects
    or noise points (e.g. caused by vegetation).   To still allow the merging
    of objects into the scene background, simple rules are available which
    automatically re-initialize the background model for the area around a
    stall object. Also, objects can be explicitly merged into the background
    via separate API commands.
    """

    enabled: bool = betterproto.bool_field(1)
    """Enable object awareness"""

    auto_merge_object_duration: float = betterproto.float_field(2)
    """
    After an object has been tracked for the given duration, the area of the
    object is reinitialized.   If 0, the auto merging is disabled.   Reasonable
    default: 10 minutes
    """

    sizes: List["ObjectSize"] = betterproto.enum_field(3)
    """
    Only enable the object awareness for the given object sizes.   If empty, it
    is enabled for all sizes.   Reasonable default: OBJECT_SIZE_MEDIUM,
    OBJECT_SIZE_LARGE.
    """

    disable_for_in_background_objects: bool = betterproto.bool_field(4)
    """
    Disable for objects which are marked with the in_background property.
    This can be beneficial in scenes where the continuous background model
    update works better than the one-shot auto-merge re-initialization. Please
    note that the shadow detection will not work as expected when this is
    disabled.
    """


@dataclass(eq=False, repr=False)
class BackgroundSubtractionStatic(betterproto.Message):
    """
    Uses the first received frames to build a static background map of the
    environment. The algorithm requires the scene to only contain the static
    parts of the scene on the start of the processing. The background model is
    not updated automatically afterwards. The ResetBackground grpc method
    allows to update the static map of the environment.
    """

    num_initialization_frames: int = betterproto.uint32_field(1)
    """
    How many frames of the first received frames are used to build the
    background   Reasonable default: 10
    """

    voxel_size: float = betterproto.float_field(3)
    """
    Size of voxels used for voxelization of the background during
    initialization.   Default: 0.05 m
    """

    min_distance: float = betterproto.float_field(4)
    """
    Minimum spatial distance to background to detect points as foreground
    Default: 0.15 m
    """


@dataclass(eq=False, repr=False)
class ObjectClass(betterproto.Message):
    """ObjectClass represents classification types of detected objects."""

    tls_vehicle: "ObjectClassTlsVehicle" = betterproto.enum_field(1, group="type")
    """bast TLS 2012 vehicle classification 8+1"""


@dataclass(eq=False, repr=False)
class Classification(betterproto.Message):
    """
    Algorithms for classifying object into small, medium, large or predicting
    class of the object using machine learning models.
    """

    size: "ClassificationSize" = betterproto.message_field(1, group="type")
    """Rule-based classification using object size thresholds."""

    model: "ClassificationModel" = betterproto.message_field(2, group="type")
    """Model-based classification using a trained machine learning model."""


@dataclass(eq=False, repr=False)
class ClassificationSize(betterproto.Message):
    """
    The minimum size limits of the bounding box area used for classification.
    """

    bounding_box_surface: "ClassificationSizeBoundingBoxSurface" = (
        betterproto.message_field(1, group="type")
    )
    """Use object surface size for object classification."""


@dataclass(eq=False, repr=False)
class ClassificationSizeBoundingBoxSurface(betterproto.Message):
    """
    The maximum surface area between the bounding box's OXZ and OYZ planes is
    used to classify objects based on the limits specified in this message.
    """

    small_min_size: float = betterproto.float_field(1)
    """
    The surface area of the objects bounding box should be larger than this
    value to be considered a small object.
    """

    medium_min_size: float = betterproto.float_field(2)
    """
    The surface area of the objects bounding box should be larger than this
    value to be considered a medium object.
    """

    large_min_size: float = betterproto.float_field(3)
    """
    The surface area of the objects bounding box should be larger than this
    value to be considered a large object.
    """


@dataclass(eq=False, repr=False)
class ClassificationModel(betterproto.Message):
    """Configuration for model-based classification."""

    weights: bytes = betterproto.bytes_field(1)
    """Serialized model weights."""

    type: "ClassificationModelType" = betterproto.enum_field(2)
    """The type of the model."""

    normalization: "ClassificationModelNormalization" = betterproto.message_field(3)
    """The normalization parameters used to preprocess input features."""

    feature_generator: "ClassificationModelFeatureGenerator" = betterproto.enum_field(4)
    """The feature generator method used."""

    object_category: "ObjectClass" = betterproto.message_field(5)
    """The subset of classes to use."""

    metadata: "betterproto_lib_google_protobuf.Struct" = betterproto.message_field(100)
    """
    Arbitrary metadata storage about model training, containing information
    about data used for training and optimal hyperparameters.
    """


@dataclass(eq=False, repr=False)
class ClassificationModelNormalization(betterproto.Message):
    """
    Configuration for feature normalization before feeding them into the model.
    """

    mean_coeffs: List[float] = betterproto.float_field(1)
    """
    The mean coefficients used to normalize each input feature. For each input
    feature: (x - mean) / std
    """

    std_coeffs: List[float] = betterproto.float_field(2)
    """The standard deviation coefficients used for normalization."""


@dataclass(eq=False, repr=False)
class DataSource(betterproto.Message):
    """
    The configuration storing the sources to retrieve the point cloud data for
    further processing.
    """

    qb2_setup: "DataSourceQb2Setup" = betterproto.message_field(
        3, group="data_source_type"
    )
    """Use Qb2 lidars to retrieve point clouds"""

    geolocation_of_map: "__base_config__.Geolocation" = betterproto.message_field(4)
    """
    Geolocation of data source. This references the map coordinate system of
    this data source to the world. Individual lidars are referenced to the map
    coordinate system via their `map_from_lidar` transform.   [NOTE] If the
    map_from_lidar transform is not an identity transformation, this is not the
    geolocation of an individual sensor.
    """

    swarm: bool = betterproto.bool_field(5)
    """
    Experimental mode which enables configuration synchronization and
    distributed processing.   All processing-related configuration, e.g. scan
    pattern and zones, are automatically synchronized between all members in
    the sensor setup. Also the sensor setup itself is replicated on all
    sensors.   The object lists of all sensors are fused and tracked on every
    member in the swarm. Thus, also all object-based security zones are
    evaluated on every sensor. This leads to a high availablity and redundancy
    without requiring a master processing unit would be a single point of
    failure.
    """

    allow_unavailable_lidars: bool = betterproto.bool_field(6)
    """
    Allow that devices in the setup are temporarily not available or failed.
    Re-connection attempts are performed continously. A warning with the list
    of unavailable sensors is raised. If all sensors are unavailable, the
    pipeline will fail.
    """


@dataclass(eq=False, repr=False)
class DataSourceQb2(betterproto.Message):
    """Configuration for retrieving point clouds from a Qb2"""

    fqdn: str = betterproto.string_field(1)
    """
    The fully qualified domain name of the Qb2 device. For on-device
    processing/configuration, 'fqdn' can be set to an empty string to request
    the data of the current device.
    """

    port: int = betterproto.uint32_field(5)
    """
    The gRPC port of the Qb2 device. If unset the default gRPC ports 50051
    (unencrypted) or 55551 (TLS) will be used.
    """

    map_from_lidar: "__base_geometry__.Transform" = betterproto.message_field(2)
    """
    Transformation from the lidar frame to the map frame. If this transform is
    not set, this will be interpreted as identify transformation. Transforming
    all point cloud topics into the map frame results in a globally consistent
    combined point cloud in map frame.
    """

    application_key: str = betterproto.string_field(3)
    """
    Application key with authorized access level. If set, the field
    serial_number has to be set as well. This field is required if user-
    management is enabled on externally connected devices.
    """

    serial_number: str = betterproto.string_field(4)
    """
    Serial number. If set, the connection will be secured with TLS. This field
    is required if user-management is enabled on externally connected devices.
    """

    disabled: bool = betterproto.bool_field(6)
    """
    Disable fetching data from this sensor, setting this flag to `true`
    disables the evaluation of the entire sensor point cloud
    """

    metadata: "betterproto_lib_google_protobuf.Struct" = betterproto.message_field(100)
    """Arbitrary metadata storage for client applications"""


@dataclass(eq=False, repr=False)
class DataSourceTrigger(betterproto.Message):
    """
    Configuration of Trigger Mode. In trigger mode the processing pipeline will
    reduce the frequency at which point clouds and state lists are getting
    computed to reduce the amount of data transmitted between the processing
    device and configured 'lidars'.
    """

    frequency: float = betterproto.float_field(1)
    """
    The frequency at which data is getting requested from the lidars and
    outputs are generated.
    """


@dataclass(eq=False, repr=False)
class DataSourceQb2Setup(betterproto.Message):
    """The configuration of a Qb2 setup of the LiDAR devices"""

    lidars: List["DataSourceQb2"] = betterproto.message_field(1)
    """the qb2 lidars to get the point clouds from"""

    trigger: "DataSourceTrigger" = betterproto.message_field(2)
    """
    If the field is set trigger mode is enabled. If the field is not set, the
    pipeline outputs are computed with the frequency of configured lidars, i.e.
    the scan pattern configured on those.
    """


@dataclass(eq=False, repr=False)
class Disqualification(betterproto.Message):
    """
    Algorithm for detecting disqualifying effects for the sensor e.g. fog.
    """

    disabled: bool = betterproto.bool_field(1)
    """Disable disqualification checking."""

    fog_photon_count_threshold: float = betterproto.float_field(2)
    """
    Threshold for the detection of fog.   If the difference in photon count
    mean between the current frame and the background divided by the background
    mean exceeds this threshold, a disqualification alarm is raised.   Default:
    0.35
    """


@dataclass(eq=False, repr=False)
class History(betterproto.Message):
    """
    Configuration message for the event and motion replay history module.
    """

    disable: bool = betterproto.bool_field(1)
    """Disable non-volatile history."""


@dataclass(eq=False, repr=False)
class PointCloudFilter(betterproto.Message):
    """Algorithm for filtering point clouds"""

    radius_outlier: "PointCloudFilterRadiusOutlier" = betterproto.message_field(
        1, group="point_cloud_filter_type"
    )
    """Use radius outlier filter for noise reduction on point clouds"""


@dataclass(eq=False, repr=False)
class PointCloudFilterRadiusOutlier(betterproto.Message):
    """Filter points based on the number of neighbors in a certain radius"""

    min_neighbor_points: int = betterproto.uint32_field(1)
    """Minimum number of neighbors a point has to have to be retained"""

    neighbor_radius: float = betterproto.double_field(2)
    """All points within this radius are considered neighbors of a point"""


@dataclass(eq=False, repr=False)
class Tracking(betterproto.Message):
    """Algorithms for tracking the objects generated from the clustering"""

    disable: bool = betterproto.bool_field(4)
    """Disable tracking. On by default."""

    sensitivity: float = betterproto.float_field(1)
    """
    Higher sensitivity will make the tracker confirm the object faster
    Reasonable default: 0.85
    """

    acceleration_noise: float = betterproto.float_field(2)
    """
    The acceptance range of accelerations for the object to be tracked
    Reasonable default: 0.5
    """

    survival_probability: float = betterproto.float_field(3)
    """
    Higher probability will allow the object to be followed longer in the
    absence of observations   Reasonable default: 1
    """

    path_resolution: float = betterproto.float_field(5)
    """
    The distance between saved object positions in the track path history
    Default value: 1 meter
    """


@dataclass(eq=False, repr=False)
class Perception(betterproto.Message):
    """
    The configuration of perception algorithms used to run e.g. security zones
    """

    background_subtraction: "BackgroundSubtraction" = betterproto.message_field(1)
    """Extract the foreground point cloud of the scene"""

    foreground_point_cloud_filters: List["PointCloudFilter"] = (
        betterproto.message_field(2)
    )
    """Filter the foreground point cloud"""

    clustering: "Clustering" = betterproto.message_field(8)
    """Segment the foreground point cloud into clusters"""

    tracking: "Tracking" = betterproto.message_field(9)
    """Track the objects generated from the clustering"""

    classification: "Classification" = betterproto.message_field(10)
    """Classify object into small, medium and large objects"""

    history: "History" = betterproto.message_field(11)
    """Keep a history of perception results"""

    disqualification: "Disqualification" = betterproto.message_field(12)
    """Detect disqualifying effects in the point cloud caused by weather"""


@dataclass(eq=False, repr=False)
class ZoneAlgorithm(betterproto.Message):
    """An algorithm that monitors the area within and around a zone."""

    name: str = betterproto.string_field(1)
    """The user readable zone algorithm name"""

    uuid: str = betterproto.string_field(2)
    """The uuid of the zone algorithm (uuid4)"""

    shape: "__base_geometry__.Shape" = betterproto.message_field(3)
    """
    Geometric shape (usually a Box) in which the algorithm detects certain
    behaviors/scenarios
    """

    disabled: bool = betterproto.bool_field(13)
    """
    Disable this zone, setting this flag to `true` disables the evaluation of
    the zone
    """

    geolocation: "ZoneAlgorithmGeolocation" = betterproto.message_field(15)
    """
    Geolocation of the zone.   This field is read only and only set when the
    geolocation is configured in the data source.
    """

    metadata: "betterproto_lib_google_protobuf.Struct" = betterproto.message_field(100)
    """Arbitrary metadata storage for client applications"""

    volume: "ZoneAlgorithmVolume" = betterproto.message_field(9, group="algorithm_type")
    """Run volume monitoring within the zone"""

    security: "ZoneAlgorithmSecurity" = betterproto.message_field(
        7, group="algorithm_type"
    )
    """Run alarm detection within the zone"""

    exclusion: "ZoneAlgorithmExclusion" = betterproto.message_field(
        10, group="algorithm_type"
    )
    """Run exclusion zone"""

    object_based_security: "ZoneAlgorithmObjectBasedSecurity" = (
        betterproto.message_field(11, group="algorithm_type")
    )
    """Run object-based alarm detection within the zone"""

    occupancy: "ZoneAlgorithmOccupancy" = betterproto.message_field(
        12, group="algorithm_type"
    )
    """Run occupancy zone"""

    traversal_security: "ZoneAlgorithmTraversalSecurity" = betterproto.message_field(
        14, group="algorithm_type"
    )
    """Run traversal zone"""

    traffic_lane: "ZoneAlgorithmTrafficLane" = betterproto.message_field(
        16, group="algorithm_type"
    )
    """Run traffic monitoring within the zone"""


@dataclass(eq=False, repr=False)
class ZoneAlgorithmGeolocation(betterproto.Message):
    """The geolocation of the zone based on the map and the zone position."""

    center: "__base_config__.Geolocation" = betterproto.message_field(1)
    """The geolocation of the center of the zone."""

    corners: List["__base_config__.Geolocation"] = betterproto.message_field(2)
    """The geolocation of the corners of the zone."""


@dataclass(eq=False, repr=False)
class ZoneAlgorithmVolume(betterproto.Message):
    """
    Algorithm that measure the volume of a zone   The volume of a zone is
    approximated by computing a 'volume map' from the input point clouds. The
    volume map discretize the zone into 'tiles' in the xy-plane with a side-
    length of 'resolution'. Each tile contains the height information about the
    points that fall into this tile. The volume of the volume map can be
    calculated by adding up the volumes of the tiles in the volume map.
    """

    resolution: float = betterproto.float_field(1)
    """
    Grid resolution per tile used to measure the volume.   Reasonable default:
    0.1
    """

    empty_volume: float = betterproto.float_field(2)
    """
    The measured volume while area covered by the zone is considered 'empty'.
    The value can be set using TareVolume method while the area of the zone is
    empty.   Reasonable default: 0
    """

    disable_when_occupied_zone_uuids: List[str] = betterproto.string_field(4)
    """
    Link volume zone to occupancy zones (by uuid).   Disables the volume zone
    state when one of the occupancy zones is occupied.
    """

    angle_of_repose: float = betterproto.float_field(5)
    """
    Angle of repose.   Steepest angle of descent when the measured material is
    piled. See https://en.wikipedia.org/wiki/Angle_of_repose.
    """

    minimum_coverage: float = betterproto.float_field(6)
    """
    Minimum coverage value for zone.   When the estimated coverage is below the
    configured threshold, the state output will be disabled.   This can be used
    to automatically disable zones when the viewport to the zone area is
    blocked or the sensor is temporarily failed.   Default: 0
    """


@dataclass(eq=False, repr=False)
class ZoneAlgorithmSecurity(betterproto.Message):
    """
    Algorithm that triggers an alarm if movement was detected in the zone
    """

    min_points: int = betterproto.uint32_field(1)
    """
    Minimum number of (foreground) points in the security zone to trigger the
    alarm. Reasonable default: 10
    """

    max_points: int = betterproto.uint32_field(2)
    """
    Maximum number of (foreground) points in the security zone that still
    triggers an alarm. More points will disable the alarm. This logic can be
    disabled by setting max_points to '0'. Default: 0
    """

    minimum_intruding_duration: float = betterproto.float_field(3)
    """
    Minimum active intrusion duration before alarm is triggered.   Default: 0
    """

    minimum_intrusion_confidence: float = betterproto.float_field(4)
    """
    Minimum intrusion confidence before alarm is triggered.   Only applicable
    when the minimum intruding duration is configured.   Default: 1
    """

    hold_duration: float = betterproto.float_field(5)
    """
    Alarm is kept active for the given duration to reduce jitter.   Default: 0
    """

    disable_when_occupied_zone_uuids: List[str] = betterproto.string_field(6)
    """
    Link security zone to occupancy zones (by uuid).   Disables the security
    zone state and alarms when one of the occupancy zones is occupied.
    """


@dataclass(eq=False, repr=False)
class ZoneAlgorithmObjectBasedSecurity(betterproto.Message):
    """
    Algorithm that triggers an alarm when an object of one of the selected
    sizes is in the zone
    """

    alarm_sizes: List["ObjectSize"] = betterproto.enum_field(1)
    """
    Selection of sizes which trigger an alarm. Each size in the array will only
    trigger an alarm for the interval of that size.
    """

    minimum_intruder_lifetime: float = betterproto.float_field(6)
    """Minimum lifetime of object before alarm is triggered.   Default: 0"""

    minimum_intruder_track_length: float = betterproto.float_field(7)
    """
    Minimum track length of object before alarm is triggered.   Default: 0
    """

    minimum_intruding_duration: float = betterproto.float_field(8)
    """
    Minimum active intrusion duration before alarm is triggered.   Default: 0
    """

    objects_in_background: bool = betterproto.bool_field(4)
    """
    Trigger alarm for objects with the "in_background" property.   Enabling
    this might increase the false alarm rate.
    """

    minimum_intrusion_confidence: float = betterproto.float_field(9)
    """
    Minimum intrusion confidence before alarm is triggered.   Only applicable
    when the minimum intruding duration is configured.   Default: 1
    """

    hold_duration: float = betterproto.float_field(10)
    """
    Alarm is kept active for the given duration to reduce jitter.   Default: 0
    """

    intrusion_on_partial_entry: bool = betterproto.bool_field(11)
    """
    Detect an object as intruder if any part of it enters the zone. Only the
    center point of the object is considered when disabled.   Enabling this
    might increase the false alarm rate.
    """

    disable_when_occupied_zone_uuids: List[str] = betterproto.string_field(12)
    """
    Link security zone to occupancy zones (by uuid).   Disables the security
    zone state and alarms when one of the occupancy zones is occupied.
    """


@dataclass(eq=False, repr=False)
class ZoneAlgorithmExclusion(betterproto.Message):
    """Algorithm that excludes points from the input point cloud"""

    pass


@dataclass(eq=False, repr=False)
class ZoneAlgorithmOccupancy(betterproto.Message):
    """Algorithm that detects if a zone is occupied"""

    min_points: int = betterproto.uint32_field(1)
    """
    Minimum number of points to mark the zone as occupied.   Reasonable
    default: 10
    """

    adaptive_baseline_time_constant: float = betterproto.float_field(2)
    """
    If set, the min_points is not compared against zero but against an adaptive
    baseline. The baseline is calculated with an exponential filter with the
    zone point count as input.   The given time constant is used to calculate
    the alpha for the exponential filter. After a restart, the baseline is
    initialized with the current zone point count.   Reasonable default: 3600s
    (1 hour)
    """

    voxel_size: float = betterproto.float_field(3)
    """
    The point cloud inside the zone is down sampled with a voxel grid. This is
    done to achieve a distance-independent parametrization. The size of a voxel
    cell can be configured with this parameter.   Default: 0.05m
    """

    invert: bool = betterproto.bool_field(4)
    """
    Invert the state of the zone   This might be useful in situations where
    e.g. a static crane should be detected in its home position.
    """


@dataclass(eq=False, repr=False)
class ZoneAlgorithmTraversalSecurity(betterproto.Message):
    """Algorithm that detects if objects are traversing through the zone."""

    alarm_sizes: List["ObjectSize"] = betterproto.enum_field(1)
    """
    Selection of sizes which trigger an alarm.  An alarm will only be triggered
    by objects of sizes specified in the array.
    """

    hold_duration: float = betterproto.float_field(2)
    """
    Alarm is kept active for the given duration to reduce jitter.   Default: 0
    """

    disable_when_occupied_zone_uuids: List[str] = betterproto.string_field(3)
    """
    Link security zone to occupancy zones (by uuid).   Disables the security
    zone state and alarms when one of the occupancy zones is occupied.
    """


@dataclass(eq=False, repr=False)
class ZoneAlgorithmTrafficLane(betterproto.Message):
    """Algorithm that monitors traffic moving through the zone."""

    expected_velocity: float = betterproto.float_field(1)
    """Expected velocity of the objects inside the traffic zone."""
