<commit_before># -*- coding:utf-8 -*-

import time

import math
import rospy
from bitbots_common.pose.pypose import PyPose as Pose

from bitbots_common.pose.pypose import PyJoint as Joint

#todo translate old german comments to english

class Keyframe:
    '''
    Eine Pose, die vom Roboter innerhalb einer Animation zu einem
    Zeitpunkt :attr:`duration` Sekunden in der Zukunft eingenommen wird.
    Der Roboter hat zu diesem Zeitpunkt
    dann alle Gelenke auf den in der Zuordnung :attr:`goals` gespeicherten
    Werten. Beim Erreichen dieser Pose hält der Roboter für
    :attr:`pause` Sekunden inne. Es werden die P-Gains auf die entsprechenden
    p werte gesetzt, sodenn vorhanden.
    '''

    def __init__(self, goals, duration=1.0, pause=0.0, p={}):
        self.duration = float(duration)
        self.pause = float(pause)
        self.goals = goals
        self.p = p


class Animation:
    '''
    Eine Animation besteht aus einer Reihe von Zielposen (:class:`Keyframe`)
    für die einzelnen Gelenke des Roboters, die nacheinander
    abgefahren werden müssen. Zwischen den einzelnen Zielposen kann eine
    variable Zeit vergehen und der Roboter kann nach dem Erreichen einer
    Position für eine bestimmte Zeit in dieser verweilen, bevor
    die nächste Pose angefahren wird.

    Die Art, wie zwischen zwei Posen interpoliert wird, ist durch einen
    :class:`Interpolator` festgelegt. Jedem Gelenk kann dabei ein eigener
    :class:`Interpolator` zugeordnet werden. Ist keiner zugeordnet, so wird
    der Standardinterpolator für die Animation verwendet. Ist keiner
    festgelegt, wird eine einfache lineare Interpolation mittels
    des :class:`LinearInterpolator` verwendet.
    '''

    def __init__(self, name, keyframes, default_interpolator=None):
        self.name = name
        self.interpolators = {}
        self.keyframes = keyframes
        self.default_interpolator = default_interpolator or LinearInterpolator

    def get_interpolator(self, name):
        """ Gibt die Klasse des für das Gelenk *name* verwendeten
            Interpolators zurück. Ist für das Gelenk speziell keiner gesetzt,
            wird der Wert von :attr:`default_interpolator` zurück gegeben.
        """
        return self.interpolators.get(name, self.default_interpolator)

    def get_steps(self, nameb: bytes):
        """ Gibt ein Liste von :class:`Step` Objekten für das Gelenk *name*
            zurück.
        """
        name = nameb.decode()
        time = 0
        steps = []
        for keyframe in self.keyframes:
            # zeit immer berechnen sonst gibts bei in der mitte fehlenden
            # motoren komische bugs
            time += keyframe.duration
            if keyframe.duration < 0.001:
                rospy.logwarn_throttle(1, "Keyframe has very low duration, this may lead to errors.")

            if name not in keyframe.goals:
                # wenn das gelenk in diesem Keyframe nicht angesteuert wird
                # ignorieren wir es. Das bedeutet auch das die P-Gains dann
                # nicht gesetzt werden können (das würde problkeme mit einem
                # lehren step element geben)

                # wir müssen noch die pause hinzurechnen, sonst ist unsere
                # zwischenzeit eventuell etwas klein
                time += keyframe.pause
                continue

            # Keyframe anfahren

            steps.append(Step(
                time,
                keyframe.goals[name],
                keyframe.p.get(name, -1)
            ))

            if keyframe.pause > 0:
                # Pause beachten
                time += keyframe.pause
                steps.append(Step(time, keyframe.goals[name]))

        return steps


class Step:
    '''
    Einfache Klasse zum Speichern der Stützstellen und Stützwerte
    für die Interpolation.
    '''

    def __init__(self, time, value, p=-1):
        self.hold = False
        self.off = False
        self.time = time
        self.p = p

        if value == "off":
            self.off = True
        elif value == "hold":
            rospy.logwarn("'hold' noch nicht unterstützt!")
            self.hold = True
        else:
            raise ValueError("Ungültiger Wert fürs Ziel")

        # gegen einen anderen Wert ersetzten
        value = 0

        self.value = value

    def __repr__(self):
        return "<Step time=%1.2f, value=%1.2f, p=%d>" % (self.time, self.value, self.p)


class Interpolator:
    """
    Dies ist die Basisklasse für alle Interpolatoren. Ein Interpolator
    bekommt im Konstruktor eine Liste von :class:`Step`-Objekten.
    Der Konstruktor ruft die prepare() Methode auf, in der der
    Interpolator einmalige Vorbereitungen treffen kann.
    Ein kubischer Interpolator würde z.B. die Steigung der Tangenten
    berechnen.

    Danach können interpolierte Werte über die Funktion :func:`interpolate`
    erfragt werden.
    """

    def __init__(self, steps):
        self.steps = steps
        if not self.steps:
            raise ValueError("'steps' cannot be empty")

        # Den Wert für deaktivierte Stützstellen auf den Wert der vorigen
        # Stützstelle setzen
        for idx in range(1, len(self.steps)):
            next = self.steps[idx]
            prev = self.steps[idx - 1]
            if next.hold or next.off:<commit_msg>resolved wrong fix in animation (checking now if string again)<commit_after># -*- coding:utf-8 -*-

import time

import math
import rospy
from bitbots_common.pose.pypose import PyPose as Pose

from bitbots_common.pose.pypose import PyJoint as Joint

#todo translate old german comments to english

class Keyframe:
    '''
    Eine Pose, die vom Roboter innerhalb einer Animation zu einem
    Zeitpunkt :attr:`duration` Sekunden in der Zukunft eingenommen wird.
    Der Roboter hat zu diesem Zeitpunkt
    dann alle Gelenke auf den in der Zuordnung :attr:`goals` gespeicherten
    Werten. Beim Erreichen dieser Pose hält der Roboter für
    :attr:`pause` Sekunden inne. Es werden die P-Gains auf die entsprechenden
    p werte gesetzt, sodenn vorhanden.
    '''

    def __init__(self, goals, duration=1.0, pause=0.0, p={}):
        self.duration = float(duration)
        self.pause = float(pause)
        self.goals = goals
        self.p = p


class Animation:
    '''
    Eine Animation besteht aus einer Reihe von Zielposen (:class:`Keyframe`)
    für die einzelnen Gelenke des Roboters, die nacheinander
    abgefahren werden müssen. Zwischen den einzelnen Zielposen kann eine
    variable Zeit vergehen und der Roboter kann nach dem Erreichen einer
    Position für eine bestimmte Zeit in dieser verweilen, bevor
    die nächste Pose angefahren wird.

    Die Art, wie zwischen zwei Posen interpoliert wird, ist durch einen
    :class:`Interpolator` festgelegt. Jedem Gelenk kann dabei ein eigener
    :class:`Interpolator` zugeordnet werden. Ist keiner zugeordnet, so wird
    der Standardinterpolator für die Animation verwendet. Ist keiner
    festgelegt, wird eine einfache lineare Interpolation mittels
    des :class:`LinearInterpolator` verwendet.
    '''

    def __init__(self, name, keyframes, default_interpolator=None):
        self.name = name
        self.interpolators = {}
        self.keyframes = keyframes
        self.default_interpolator = default_interpolator or LinearInterpolator

    def get_interpolator(self, name):
        """ Gibt die Klasse des für das Gelenk *name* verwendeten
            Interpolators zurück. Ist für das Gelenk speziell keiner gesetzt,
            wird der Wert von :attr:`default_interpolator` zurück gegeben.
        """
        return self.interpolators.get(name, self.default_interpolator)

    def get_steps(self, nameb: bytes):
        """ Gibt ein Liste von :class:`Step` Objekten für das Gelenk *name*
            zurück.
        """
        name = nameb.decode()
        time = 0
        steps = []
        for keyframe in self.keyframes:
            # zeit immer berechnen sonst gibts bei in der mitte fehlenden
            # motoren komische bugs
            time += keyframe.duration
            if keyframe.duration < 0.001:
                rospy.logwarn_throttle(1, "Keyframe has very low duration, this may lead to errors.")

            if name not in keyframe.goals:
                # wenn das gelenk in diesem Keyframe nicht angesteuert wird
                # ignorieren wir es. Das bedeutet auch das die P-Gains dann
                # nicht gesetzt werden können (das würde problkeme mit einem
                # lehren step element geben)

                # wir müssen noch die pause hinzurechnen, sonst ist unsere
                # zwischenzeit eventuell etwas klein
                time += keyframe.pause
                continue

            # Keyframe anfahren

            steps.append(Step(
                time,
                keyframe.goals[name],
                keyframe.p.get(name, -1)
            ))

            if keyframe.pause > 0:
                # Pause beachten
                time += keyframe.pause
                steps.append(Step(time, keyframe.goals[name]))

        return steps


class Step:
    '''
    Einfache Klasse zum Speichern der Stützstellen und Stützwerte
    für die Interpolation.
    '''

    def __init__(self, time, value, p=-1):
        self.hold = False
        self.off = False
        self.time = time
        self.p = p

        if isinstance(value, str):
            if value == "off":
                self.off = True
            elif value == "hold":
                rospy.logwarn("'hold' noch nicht unterstützt!")
                self.hold = True
            else:
                raise ValueError("Ungültiger Wert fürs Ziel:" + str(value))

            # gegen einen anderen Wert ersetzten
            value = 0

        self.value = value

    def __repr__(self):
        return "<Step time=%1.2f, value=%1.2f, p=%d>" % (self.time, self.value, self.p)


class Interpolator:
    """
    Dies ist die Basisklasse für alle Interpolatoren. Ein Interpolator
    bekommt im Konstruktor eine Liste von :class:`Step`-Objekten.
    Der Konstruktor ruft die prepare() Methode auf, in der der
    Interpolator einmalige Vorbereitungen treffen kann.
    Ein kubischer Interpolator würde z.B. die Steigung der Tangenten
    berechnen.

    Danach können interpolierte Werte über die Funktion :func:`interpolate`
    erfragt werden.
    """

    def __init__(self, steps):
        self.steps = steps
        if not self.steps:
            raise ValueError("'steps' cannot be empty")

        # Den Wert für deaktivierte Stützstellen auf den Wert der vorigen
        # Stützstelle setzen
        for idx in range(1, len(self.steps)):
            next = self.steps[idx]
            prev = self.steps[idx - 1]
            if next.hold or next.off:
{'fraction_non_alphanumeric': 0.07197180485995178, 'fraction_numerical': 0.0038953811908736783, 'mean_word_length': 2.2488701416089185, 'pattern_counts': {'":': 4, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4333081', 'n_tokens_mistral': 3241, 'n_tokens_neox': 3224, 'n_words': 1064}