class ControllerPlugin(GiskardBehavior):
    def __init__(self, name):
        super(ControllerPlugin, self).__init__(name)
        self.path_to_functions = self.get_god_map().safe_get_data(
            identifier.data_folder)
        self.nWSR = self.get_god_map().safe_get_data(identifier.nWSR)
        self.soft_constraints = None
        self.qp_data = {}
        self.get_god_map().safe_set_data(
            identifier.qp_data,
            self.qp_data)  # safe dict on godmap and work on ref

    def initialise(self):
        super(ControllerPlugin, self).initialise()
        self.init_controller()

    def setup(self, timeout=0.0):
        return super(ControllerPlugin, self).setup(5.0)

    def init_controller(self):
        new_soft_constraints = self.get_god_map().safe_get_data(
            identifier.soft_constraint_identifier)
        if self.soft_constraints is None or set(
                self.soft_constraints.keys()) != set(
                    new_soft_constraints.keys()):
            self.soft_constraints = copy(new_soft_constraints)
            self.controller = SymEngineController(
                self.get_robot(),
                u'{}/{}/'.format(self.path_to_functions,
                                 self.get_robot().get_name()),
                self.get_god_map().safe_get_data(identifier.symengine_backend),
                self.get_god_map().safe_get_data(
                    identifier.symengine_opt_level))
            self.controller.set_controlled_joints(
                self.get_robot().controlled_joints)
            self.controller.update_soft_constraints(self.soft_constraints)
            # p = Process(target=self.controller.compile)
            # p.start()
            # while p.is_alive():
            #     sleep(0.05)
            # p.join()
            self.controller.compile()

            self.qp_data[identifier.weight_keys[-1]], \
            self.qp_data[identifier.b_keys[-1]], \
            self.qp_data[identifier.bA_keys[-1]], \
            self.qp_data[identifier.xdot_keys[-1]] = self.controller.get_qpdata_key_map()

    def update(self):
        last_cmd = self.get_god_map().safe_get_data(identifier.cmd)
        self.get_god_map().safe_set_data(identifier.last_cmd, last_cmd)

        expr = self.controller.get_expr()
        expr = self.god_map.get_values(expr)

        next_cmd, \
        self.qp_data[identifier.H[-1]], \
        self.qp_data[identifier.A[-1]], \
        self.qp_data[identifier.lb[-1]], \
        self.qp_data[identifier.ub[-1]], \
        self.qp_data[identifier.lbA[-1]], \
        self.qp_data[identifier.ubA[-1]], \
        self.qp_data[identifier.xdot_full[-1]] = self.controller.get_cmd(expr, self.nWSR)
        self.get_god_map().safe_set_data(identifier.cmd, next_cmd)

        return Status.RUNNING
예제 #2
0
class TestController(object):
    """docstring for TestController"""
    def __init__(self, urdf_string):
        super(TestController, self).__init__()

        # Roboter aus URDF erzeugen
        self.robot = Robot(urdf_string)
        self.robot.parse_urdf()

        # Regler fuer den Roboter anlegen
        self.controller = SymEngineController(self.robot, '.controller_cache/')

        # Transformation vom Greifer zur Basis des Roboters erzeugen
        gripper_pose = self.robot.get_fk_expression('base_link',
                                                    'hand_palm_link')

        # Parameterisierbaren Punkt erzeugen
        self.point_input = Point3Input(to_expr, 'goal')

        # Mathematischen Punkt vom Punkt-Input erzeugen lassen
        goal_point = self.point_input.get_expression()

        # Distanz zwischen Zielpunkt und Greiferposition
        d = norm(goal_point - position_of(gripper_pose))

        a = dot(unitX, gripper_pose * unitZ)

        c_dist_angular = SoftConstraint(1 - a, 1 - a, 1, a)

        # Constraint, der die Distanz Richtung 0 zwingt
        c_dist = SoftConstraint(-d, -d, 1, d)

        free_symbols = configure_controller(self.controller, self.robot, {
            'dist': c_dist,
            'dist_angular': c_dist_angular
        })

        # Dictionary fuer die derzeitige Variablenbelegung. Initial sind alle Variablen 0
        self.cur_subs = {s: 0 for s in free_symbols}

        # Publisher fuer Kommandos
        self.pub_cmd = rospy.Publisher('/hsr/commands/joint_velocities',
                                       JointStateMsg,
                                       queue_size=1)

        # Abonent fuer Zielpunkt
        self.sub_point = rospy.Subscriber('/goal_point',
                                          PointMsg,
                                          self.cb_point,
                                          queue_size=1)

        # Abonent fuer Gelenkpositionen
        self.sub_js = rospy.Subscriber('/hsr/joint_states',
                                       JointStateMsg,
                                       self.cb_js,
                                       queue_size=1)

    def cb_point(self, msg):
        # Werte der Nachricht in Variablenbelegung uebertragen
        self.cur_subs[self.point_input.x] = msg.x
        self.cur_subs[self.point_input.y] = msg.y
        self.cur_subs[self.point_input.z] = msg.z

    def cb_js(self, msg):
        # Map von Jointnamen auf Variablen
        robot_joint_symbols = self.robot.joint_to_symbol_map

        # ueber alle Felder iterieren
        for x in range(len(msg.name)):
            # Wenn Joint tatsaechlich im Roboter definiert ist
            if msg.name[x] in robot_joint_symbols:
                # Variablenwert aktualisieren mit neuer Position
                self.cur_subs[robot_joint_symbols[
                    msg.name[x]]] = msg.position[x]

        # Kommandos generieren lassen. Variablenbelegung muss als {str: float} erfolgen.
        cmd = self.controller.get_cmd(
            {str(s): p
             for s, p in self.cur_subs.items()})

        # Kommandonachricht anlegen
        cmd_msg = JointStateMsg()

        # Kommandozeitstempel setzen
        cmd_msg.header.stamp = rospy.Time.now()

        # Positionen und Kraefte auf 0 setzen
        cmd_msg.position = [0] * len(cmd)
        cmd_msg.effort = [0] * len(cmd)

        # Kommando in Nachricht schreiben
        for j, v in cmd.items():
            cmd_msg.name.append(j)
            cmd_msg.velocity.append(v)

        # Kommando abschicken
        self.pub_cmd.publish(cmd_msg)