From cda718002392d28edd06ec6307ae21e01ce81b16 Mon Sep 17 00:00:00 2001
From: m-guberina <gubi.guberina@gmail.com>
Date: Tue, 31 Oct 2023 14:49:58 +0100
Subject: [PATCH] wrote todos, put the reference dmp code in place

---
 TODOS                                         |  23 ++
 clik/.robotiq_gripper.py.swp                  | Bin 16384 -> 0 bytes
 dmp/DMP.m                                     | 128 ++++++
 dmp/dmp_node                                  | 140 +++++++
 dmp/matlab/DMP.m                              | 128 ++++++
 dmp/matlab/NoTemporalCoupling.m               |  19 +
 dmp/matlab/TemporalCoupling.m                 | 109 ++++++
 dmp/matlab/TemporalCouplingNoPotentials.m     | 100 +++++
 dmp/matlab/main.m                             |  55 +++
 dmp/matlab/plot_result.m                      | 110 ++++++
 dmp/matlab/run_simulation.m                   |  65 ++++
 dmp/matlab/trajectories/g.mat                 | Bin 0 -> 1937 bytes
 dmp/matlab/trajectories/omega.mat             | Bin 0 -> 10525 bytes
 dmp/matlab/trajectories/psi.mat               | Bin 0 -> 3893 bytes
 dmp/matlab/trajectories/s.mat                 | Bin 0 -> 3204 bytes
 dmp/matlab/trajectories/z.mat                 | Bin 0 -> 2094 bytes
 dmp/motion_planning/__init__.py               |   0
 dmp/motion_planning/dmp/__init__.py           |   2 +
 dmp/motion_planning/dmp/__init__.pyc          | Bin 0 -> 314 bytes
 dmp/motion_planning/dmp/dmp.py                | 166 ++++++++
 dmp/motion_planning/dmp/dmp.pyc               | Bin 0 -> 6785 bytes
 dmp/motion_planning/dmp/temporal_coupling.py  |  80 ++++
 dmp/motion_planning/dmp/temporal_coupling.pyc | Bin 0 -> 3407 bytes
 .../online_traj_scaling/__init__.py           |   2 +
 .../online_traj_scaling/__init__.pyc          | Bin 0 -> 315 bytes
 .../__pycache__/gmr_oa.cpython-36.pyc         | Bin 0 -> 11530 bytes
 .../online_traj_scaling/example.yaml          |  38 ++
 .../online_traj_scaling/gmr_oa.py             | 363 ++++++++++++++++++
 .../online_traj_scaling/gmr_oa.pyc            | Bin 0 -> 14523 bytes
 .../trajectory_generator.py                   |  93 +++++
 .../trajectory_generator.pyc                  | Bin 0 -> 3744 bytes
 dmp/msg/DMPState.msg                          |   8 +
 dmp/msg/TrajGenState.msg                      |   6 +
 dmp/todos.md                                  |   2 +-
 dmp/traj_scaling_node                         | 113 ++++++
 35 files changed, 1749 insertions(+), 1 deletion(-)
 create mode 100644 TODOS
 delete mode 100644 clik/.robotiq_gripper.py.swp
 create mode 100644 dmp/DMP.m
 create mode 100755 dmp/dmp_node
 create mode 100644 dmp/matlab/DMP.m
 create mode 100644 dmp/matlab/NoTemporalCoupling.m
 create mode 100644 dmp/matlab/TemporalCoupling.m
 create mode 100644 dmp/matlab/TemporalCouplingNoPotentials.m
 create mode 100644 dmp/matlab/main.m
 create mode 100644 dmp/matlab/plot_result.m
 create mode 100644 dmp/matlab/run_simulation.m
 create mode 100644 dmp/matlab/trajectories/g.mat
 create mode 100644 dmp/matlab/trajectories/omega.mat
 create mode 100644 dmp/matlab/trajectories/psi.mat
 create mode 100644 dmp/matlab/trajectories/s.mat
 create mode 100644 dmp/matlab/trajectories/z.mat
 create mode 100644 dmp/motion_planning/__init__.py
 create mode 100644 dmp/motion_planning/dmp/__init__.py
 create mode 100644 dmp/motion_planning/dmp/__init__.pyc
 create mode 100644 dmp/motion_planning/dmp/dmp.py
 create mode 100644 dmp/motion_planning/dmp/dmp.pyc
 create mode 100644 dmp/motion_planning/dmp/temporal_coupling.py
 create mode 100644 dmp/motion_planning/dmp/temporal_coupling.pyc
 create mode 100644 dmp/motion_planning/online_traj_scaling/__init__.py
 create mode 100644 dmp/motion_planning/online_traj_scaling/__init__.pyc
 create mode 100644 dmp/motion_planning/online_traj_scaling/__pycache__/gmr_oa.cpython-36.pyc
 create mode 100644 dmp/motion_planning/online_traj_scaling/example.yaml
 create mode 100644 dmp/motion_planning/online_traj_scaling/gmr_oa.py
 create mode 100644 dmp/motion_planning/online_traj_scaling/gmr_oa.pyc
 create mode 100755 dmp/motion_planning/online_traj_scaling/trajectory_generator.py
 create mode 100644 dmp/motion_planning/online_traj_scaling/trajectory_generator.pyc
 create mode 100644 dmp/msg/DMPState.msg
 create mode 100644 dmp/msg/TrajGenState.msg
 create mode 100755 dmp/traj_scaling_node

diff --git a/TODOS b/TODOS
new file mode 100644
index 0000000..2efde79
--- /dev/null
+++ b/TODOS
@@ -0,0 +1,23 @@
+IMPORTANT
+-------------
+1. urdf
+- understand how it works (read the docs)
+- use the calibration data from the robot and put it in the urdf
+- ensure that gripper urdf makes sense
+- do test to see if the calibration is ok
+- recalibrate if necessary
+
+NICE TO HAVE
+---------------
+1. other inverse kinematics algorithms
+- standard list of them, for fun and to practise eigen and pinocchio a bit
+
+2. (ur) simulation
+- put the gripper on the robot in ursim
+- possibly fiddle to get communication with it in the sim to work
+
+FUTURE PROSPECTS, CURRENT URGENCY ZERO
+--------------------------------------
+3. hooking up with a real simulator, ex. mujoco
+
+
diff --git a/clik/.robotiq_gripper.py.swp b/clik/.robotiq_gripper.py.swp
deleted file mode 100644
index 6f387ee01160141069385d952c68d35d5a67715d..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 16384
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
K2Pw8<U;qFa2#}Ki

diff --git a/dmp/DMP.m b/dmp/DMP.m
new file mode 100644
index 0000000..176c3fd
--- /dev/null
+++ b/dmp/DMP.m
@@ -0,0 +1,128 @@
+classdef DMP
+    properties
+        % State
+        x % [z; y; s]
+        tau
+        tauDot
+        % Settings
+        K
+        D
+        alpha_s
+        n_kernel
+        n
+        g
+        y0
+        nominal_tau
+        x0
+        mu
+        std_dev
+        w
+        demo_traj
+    end
+    
+    methods
+        function obj = DMP(dmp_params,demo_traj)
+            obj.K = dmp_params.K;
+            obj.D = dmp_params.D;
+            obj.alpha_s = dmp_params.alpha_s;
+            obj.n_kernel = dmp_params.n_kernel;
+            obj.demo_traj = demo_traj;
+            obj = obj.fit();
+        end
+        
+        function obj = init(obj)
+            obj.x = obj.x0;
+            obj.tau = obj.nominal_tau;
+            obj.tauDot = 0;
+        end
+        
+        function obj = step(obj,tauDot,dt)
+            xDot = [obj.h();obj.z();-obj.s()]/obj.tau;
+            obj.x = obj.x + xDot*dt;
+            obj.tau = obj.tau + tauDot*dt;
+            obj.tauDot = tauDot;
+        end
+        
+        function ref_pos_val = ref_pos(obj)
+            ref_pos_val = obj.y();
+        end
+        
+        function ref_pos_val = ref_vel(obj)
+            ref_pos_val = obj.z()/obj.tau;
+        end
+        
+        function ref_pos_val = ref_acc(obj)
+            ref_pos_val = (obj.h() - obj.tauDot*obj.z()) / obj.tau^2;
+        end
+                
+        function yVal = y(obj)
+            yVal = obj.x(obj.n+1:2*obj.n);
+        end
+        
+        function zVal = z(obj)
+            zVal = obj.x(1:obj.n);
+        end
+        
+        function sVal = s(obj)
+            sVal = obj.x(end);
+        end
+        
+        function hVal = h(obj)
+            psi = exp(-1./(2*obj.std_dev.^2).*(obj.s()-obj.mu).^2);
+            hVal = obj.K*(obj.g-obj.y()) - obj.D*obj.z() + obj.w*psi' ./ max(sum(psi),1e-8) .* (obj.g-obj.y0)*obj.s();
+        end
+        
+        function traj = rollout(obj,dt)
+            dmp = obj.init();
+            traj.t = 0;
+            traj.pos = dmp.y();
+            traj.vel = dmp.z()/dmp.nominal_tau;
+            traj.acc = dmp.h()/dmp.nominal_tau^2;
+            traj.s = dmp.s();
+            while norm(abs(dmp.y()-dmp.g)) > 1e-2
+                dmp = dmp.step(0,dt);
+                traj.t = [traj.t traj.t(end)+dt];
+                traj.pos = [traj.pos dmp.ref_pos()];
+                traj.vel = [traj.vel dmp.ref_vel()];
+                traj.acc = [traj.acc dmp.ref_acc()];
+                traj.s = [traj.s dmp.s()];
+            end
+        end
+       
+       function obj = fit(obj)
+
+            psi = @(s,c,d) exp(-1./(2*d.^2).*(s-c).^2); % Basis function
+            obj.n = size(obj.demo_traj.pos,1);
+            obj.y0 = obj.demo_traj.pos(:,1);
+            obj.g = obj.demo_traj.pos(:,end);
+            obj.x0 = [zeros(obj.n,1); obj.y0; 1];
+            obj.nominal_tau = obj.demo_traj.t(end);
+
+            lastKernel = 1*obj.nominal_tau; % Time of last kernel center
+            ct = (0:lastKernel/(obj.n_kernel-1):lastKernel); % Time means of basis functions
+            obj.mu = exp(-obj.alpha_s/obj.nominal_tau*ct); % Phase means of basis functions
+            obj.std_dev  = abs((diff(obj.mu)));
+            obj.std_dev  = [obj.std_dev obj.std_dev(end)]; % Standard deviation of basis functions
+
+            svec = exp(-obj.alpha_s/obj.nominal_tau*obj.demo_traj.t);
+            obj.w = zeros(obj.n,obj.n_kernel);
+            for varNr = 1:obj.n
+                if abs(obj.g(varNr)-obj.y0(varNr)) < 0.001
+                    continue;
+                end
+                fGain = svec*(obj.g(varNr)-obj.y0(varNr));
+                f_target = obj.nominal_tau^2*obj.demo_traj.acc(varNr,:) - obj.K*(obj.g(varNr)-obj.demo_traj.pos(varNr,:)) + obj.D*obj.nominal_tau*obj.demo_traj.vel(varNr,:);
+                for i = 1:obj.n_kernel
+                    Gamma_i = diag(psi(svec,obj.mu(i),obj.std_dev(i)));
+                    if fGain*Gamma_i*fGain' < 1e-8
+                        obj.w(varNr,i) = 0;
+                    else
+                        obj.w(varNr,i) = fGain*Gamma_i*f_target'/(fGain*Gamma_i*fGain');
+                    end
+                end
+            end
+       end
+        
+    end
+end
+
diff --git a/dmp/dmp_node b/dmp/dmp_node
new file mode 100755
index 0000000..9a72514
--- /dev/null
+++ b/dmp/dmp_node
@@ -0,0 +1,140 @@
+#!/usr/bin/env python
+
+from motion_planning.dmp import DMP, TCVelAccConstrained, NoTC
+import numpy as np
+import rospy
+from robot_ctrl.msg import CtrlTarget
+from std_msgs.msg import Float64, String
+from motion_planning.msg import DMPState
+
+
+class DMPNode:
+    def __init__(self):
+        self.dmp_active = False
+        self.rate = None
+        self.dt = None
+        self.dmp = DMP()
+        self.tc = None
+
+        # Load target trajectory and fit DMP
+        self.load_trajectory()
+
+        # Load parameters from server
+        self.load_params()
+
+        # Setup ros topics
+        self.target_pub = rospy.Publisher("robot_ctrl/command", CtrlTarget, queue_size=1)
+        self.dmp_state = rospy.Publisher("motion_planning/dmp_state", DMPState, queue_size=1)
+        rospy.Subscriber("motion_planning/command", String, self.command_parser)
+
+        # Go into spin
+        self.spin()
+
+    def load_trajectory(self):
+        if rospy.has_param('motion_planning/trajectory_loadpath'):
+            # Set demo trajectory
+            trajectory_loadpath = rospy.get_param('motion_planning/trajectory_loadpath')
+            data = np.genfromtxt(trajectory_loadpath, delimiter=',')
+            t_demo = data[:, 0]
+            path_demo = np.array(data[:, 1:]).T
+            self.dmp.fit(path_demo, t_demo)
+            rospy.set_param("motion_planning/init_pos", np.squeeze(self.dmp.y0).tolist())
+        else:
+            rospy.logerr("Could not load trajectory. Parameter " + rospy.get_namespace() +
+                         "motion_planning/trajectory_loadpath not found")
+
+    def load_params(self):
+        # Load parameters from server
+        update_rate = rospy.get_param('motion_planning/update_rate', 125)
+        tc_type = rospy.get_param('motion_planning/tc/type', 0)
+        if rospy.has_param('motion_planning/tau0'):
+            self.dmp.tau0 = rospy.get_param('motion_planning/tau0')
+
+        # Set temporal coupling
+        if tc_type == 0:
+            self.tc = NoTC()
+        elif tc_type == 1:
+            gamma_nominal = rospy.get_param('motion_planning/tc/gamma_nominal', 1)
+            gamma_a = rospy.get_param('motion_planning/tc/gamma_a', 0.5)
+            v_max = np.array(rospy.get_param('motion_planning/tc/v_max', np.inf))
+            a_max = np.array(rospy.get_param('motion_planning/tc/a_max', np.inf))
+            eps = np.array(rospy.get_param('motion_planning/tc/eps', 0.001))
+            self.tc = TCVelAccConstrained(gamma_nominal, gamma_a, v_max, a_max, eps)
+        # Set rate for ros spin
+        self.rate = rospy.Rate(update_rate)
+        self.dt = 1.0 / update_rate
+
+    def command_parser(self, msg):
+        if msg.data == 'start':
+            self.dmp_active = True
+        elif msg.data == 'stop':
+            self.dmp_active = False
+        elif msg.data == 'reset':
+            self.dmp.reset()
+            self.dmp_active = False
+            rospy.loginfo("Reset motion_planner.")
+        elif msg.data == 'step':
+            self.dmp.step(self.dt)
+        elif msg.data == 'load_params':
+            self.load_params()
+            rospy.loginfo("Reloaded motion_planner parameters.")
+        elif msg.data == 'load_trajectory':
+            self.load_trajectory()
+            rospy.loginfo("Reloaded motion_planner trajectory.")
+        else:
+            rospy.loginfo("Invalid command string for motion planner.")
+
+    # spin -----------------------------------------------------
+    # -----------------------------------------------------------
+    def spin(self):
+        print_flag = True
+        while (not rospy.is_shutdown()):
+
+            if self.dmp_active:
+                # Step DMP
+                self.dmp.step(self.dt)
+                # Step temporal coupling
+                tau = self.dmp.tau + self.tc.update(self.dmp, self.dt) * self.dt
+                self.dmp.set_tau(tau)
+                # Send target trajectory state command
+                pub_msg = CtrlTarget()
+                pub_msg.header.stamp = rospy.Time.now()
+                pub_msg.acceleration = self.dmp.acc
+                pub_msg.velocity = self.dmp.vel
+                pub_msg.position = self.dmp.pos
+                self.target_pub.publish(pub_msg)
+            else:
+                print_flag = True
+
+            # Publish DMP state command
+            pub_msg = DMPState()
+            pub_msg.header.stamp = rospy.Time.now()
+            pub_msg.acceleration = self.dmp.acc
+            pub_msg.velocity = self.dmp.vel
+            pub_msg.position = self.dmp.pos
+            pub_msg.theta = self.dmp.theta
+            pub_msg.s = self.dmp.s()
+            pub_msg.tau = self.dmp.tau
+            self.dmp_state.publish(pub_msg)
+
+            # Notify when DMP trajectory is finished
+            if print_flag and self.dmp.theta > 1:
+                rospy.loginfo("DMP trajectory finished.")
+                print_flag = False
+
+            # Sleep
+            self.rate.sleep()
+
+
+# --------------------------------------------------------------------
+# Here is the main entry point
+if __name__ == '__main__':
+    try:
+        # Init the node:
+        rospy.init_node('DMPNode')
+
+        # Initializing and continue running the main class:
+        DMPNode()
+
+    except rospy.ROSInterruptException:
+        pass
diff --git a/dmp/matlab/DMP.m b/dmp/matlab/DMP.m
new file mode 100644
index 0000000..176c3fd
--- /dev/null
+++ b/dmp/matlab/DMP.m
@@ -0,0 +1,128 @@
+classdef DMP
+    properties
+        % State
+        x % [z; y; s]
+        tau
+        tauDot
+        % Settings
+        K
+        D
+        alpha_s
+        n_kernel
+        n
+        g
+        y0
+        nominal_tau
+        x0
+        mu
+        std_dev
+        w
+        demo_traj
+    end
+    
+    methods
+        function obj = DMP(dmp_params,demo_traj)
+            obj.K = dmp_params.K;
+            obj.D = dmp_params.D;
+            obj.alpha_s = dmp_params.alpha_s;
+            obj.n_kernel = dmp_params.n_kernel;
+            obj.demo_traj = demo_traj;
+            obj = obj.fit();
+        end
+        
+        function obj = init(obj)
+            obj.x = obj.x0;
+            obj.tau = obj.nominal_tau;
+            obj.tauDot = 0;
+        end
+        
+        function obj = step(obj,tauDot,dt)
+            xDot = [obj.h();obj.z();-obj.s()]/obj.tau;
+            obj.x = obj.x + xDot*dt;
+            obj.tau = obj.tau + tauDot*dt;
+            obj.tauDot = tauDot;
+        end
+        
+        function ref_pos_val = ref_pos(obj)
+            ref_pos_val = obj.y();
+        end
+        
+        function ref_pos_val = ref_vel(obj)
+            ref_pos_val = obj.z()/obj.tau;
+        end
+        
+        function ref_pos_val = ref_acc(obj)
+            ref_pos_val = (obj.h() - obj.tauDot*obj.z()) / obj.tau^2;
+        end
+                
+        function yVal = y(obj)
+            yVal = obj.x(obj.n+1:2*obj.n);
+        end
+        
+        function zVal = z(obj)
+            zVal = obj.x(1:obj.n);
+        end
+        
+        function sVal = s(obj)
+            sVal = obj.x(end);
+        end
+        
+        function hVal = h(obj)
+            psi = exp(-1./(2*obj.std_dev.^2).*(obj.s()-obj.mu).^2);
+            hVal = obj.K*(obj.g-obj.y()) - obj.D*obj.z() + obj.w*psi' ./ max(sum(psi),1e-8) .* (obj.g-obj.y0)*obj.s();
+        end
+        
+        function traj = rollout(obj,dt)
+            dmp = obj.init();
+            traj.t = 0;
+            traj.pos = dmp.y();
+            traj.vel = dmp.z()/dmp.nominal_tau;
+            traj.acc = dmp.h()/dmp.nominal_tau^2;
+            traj.s = dmp.s();
+            while norm(abs(dmp.y()-dmp.g)) > 1e-2
+                dmp = dmp.step(0,dt);
+                traj.t = [traj.t traj.t(end)+dt];
+                traj.pos = [traj.pos dmp.ref_pos()];
+                traj.vel = [traj.vel dmp.ref_vel()];
+                traj.acc = [traj.acc dmp.ref_acc()];
+                traj.s = [traj.s dmp.s()];
+            end
+        end
+       
+       function obj = fit(obj)
+
+            psi = @(s,c,d) exp(-1./(2*d.^2).*(s-c).^2); % Basis function
+            obj.n = size(obj.demo_traj.pos,1);
+            obj.y0 = obj.demo_traj.pos(:,1);
+            obj.g = obj.demo_traj.pos(:,end);
+            obj.x0 = [zeros(obj.n,1); obj.y0; 1];
+            obj.nominal_tau = obj.demo_traj.t(end);
+
+            lastKernel = 1*obj.nominal_tau; % Time of last kernel center
+            ct = (0:lastKernel/(obj.n_kernel-1):lastKernel); % Time means of basis functions
+            obj.mu = exp(-obj.alpha_s/obj.nominal_tau*ct); % Phase means of basis functions
+            obj.std_dev  = abs((diff(obj.mu)));
+            obj.std_dev  = [obj.std_dev obj.std_dev(end)]; % Standard deviation of basis functions
+
+            svec = exp(-obj.alpha_s/obj.nominal_tau*obj.demo_traj.t);
+            obj.w = zeros(obj.n,obj.n_kernel);
+            for varNr = 1:obj.n
+                if abs(obj.g(varNr)-obj.y0(varNr)) < 0.001
+                    continue;
+                end
+                fGain = svec*(obj.g(varNr)-obj.y0(varNr));
+                f_target = obj.nominal_tau^2*obj.demo_traj.acc(varNr,:) - obj.K*(obj.g(varNr)-obj.demo_traj.pos(varNr,:)) + obj.D*obj.nominal_tau*obj.demo_traj.vel(varNr,:);
+                for i = 1:obj.n_kernel
+                    Gamma_i = diag(psi(svec,obj.mu(i),obj.std_dev(i)));
+                    if fGain*Gamma_i*fGain' < 1e-8
+                        obj.w(varNr,i) = 0;
+                    else
+                        obj.w(varNr,i) = fGain*Gamma_i*f_target'/(fGain*Gamma_i*fGain');
+                    end
+                end
+            end
+       end
+        
+    end
+end
+
diff --git a/dmp/matlab/NoTemporalCoupling.m b/dmp/matlab/NoTemporalCoupling.m
new file mode 100644
index 0000000..bec7d37
--- /dev/null
+++ b/dmp/matlab/NoTemporalCoupling.m
@@ -0,0 +1,19 @@
+classdef NoTemporalCoupling
+    properties
+       v_max
+       a_max
+    end
+    
+    methods
+        
+        function obj = NoTemporalCoupling(params)
+            obj.v_max = params.v_max;
+            obj.a_max = params.a_max;
+        end
+        
+        function tau_dot_val = tau_dot(obj,dmp,dt)
+            tau_dot_val = 0;
+        end
+    end
+end
+
diff --git a/dmp/matlab/TemporalCoupling.m b/dmp/matlab/TemporalCoupling.m
new file mode 100644
index 0000000..68caf44
--- /dev/null
+++ b/dmp/matlab/TemporalCoupling.m
@@ -0,0 +1,109 @@
+classdef TemporalCoupling
+    properties
+        % Settings
+        v_max
+        a_max
+        nominal_tau
+        gamma_nominal
+        gamma_a
+        eps
+    end
+    
+    methods
+        function obj = TemporalCoupling(params)
+            obj.nominal_tau = params.nominal_tau;
+            obj.v_max = params.v_max;
+            obj.a_max = params.a_max;
+            obj.gamma_nominal = params.gamma_nominal;
+            obj.gamma_a = params.gamma_a;
+            obj.eps = params.eps;
+        end
+      
+        function tau_dot_val = tau_dot(obj,dmp,dt)
+            % DMP prediction step
+            dmp_next = dmp.step(0,dt);
+            
+            % Formulate matrices
+            [A,B,C,D] = obj.tc_mtrcs(dmp);
+            [A_next,~,C_next,~] = obj.tc_mtrcs(dmp_next);
+
+            % Compute bounds
+            tau_dot_min_a = obj.tau_dot_min_a(A,B,C,dmp.tau);
+            tau_dot_max_a = obj.tau_dot_max_a(A,B,C,dmp.tau);
+            tau_dot_min_v = obj.tau_dot_min_v(A_next,D,dmp.tau,dt);
+            tau_dot_min_f = obj.tau_dot_min_f(A_next,B,C_next,dmp.tau,dt);
+            tau_dot_min_nominal = obj.tau_dot_min_nominal(dmp.tau,dt);
+            
+            % Base update law
+            tau_dot_val = obj.gamma_nominal*(obj.nominal_tau-dmp.tau) + dmp.tau*obj.sigma(dmp);
+            
+            % Saturate
+            tau_dot_min = max([tau_dot_min_a,tau_dot_min_v,tau_dot_min_f,tau_dot_min_nominal]);
+            if tau_dot_val > tau_dot_max_a
+                tau_dot_val = tau_dot_max_a;
+            end
+            if tau_dot_val < tau_dot_min
+                tau_dot_val = tau_dot_min;
+            end
+        end
+        
+        function [A,B,C,D] = tc_mtrcs(obj,dmp)
+            A = [-dmp.z(); 
+                dmp.z()];
+            B = [-obj.a_max;
+                 -obj.a_max];
+            C = [dmp.h();
+                 -dmp.h()];
+            D = [-obj.v_max;
+                 -obj.v_max];
+        end
+        
+        function minVal = tau_dot_min_a(obj,A,B,C,tau)
+            i = A < 0;
+            minVal = max(-(B(i)*tau^2+C(i))./A(i));
+        end
+        
+        function maxVal = tau_dot_max_a(obj,A,B,C,tau)
+            i = A > 0;
+            maxVal = min(-(B(i)*tau^2+C(i))./A(i));
+        end
+        
+        function minVal = tau_dot_min_f(obj,A,B,C,tau,dt)
+            Ais = A(A<0);
+            Ajs = A(A>0);
+            Bis = B(A<0);
+            Bjs = B(A>0);
+            Cis = C(A<0);
+            Cjs = C(A>0);
+            tauNextMin = -inf;
+            for i=1:length(Ais)
+                for j = 1:length(Ajs)
+                    num = Cis(i)*abs(Ajs(j))+Cjs(j)*abs(Ais(i));
+                    den = abs(Bis(i)*Ajs(j))+abs(Bjs(j)*Ais(i));
+                    if num > 0
+                        if sqrt(num/den) > tauNextMin
+                            tauNextMin = sqrt(num/den);
+                        end
+                    end
+                end
+            end
+            minVal = (tauNextMin-tau)/dt;
+        end
+        
+        function minVal = tau_dot_min_v(obj,A,D,tau,dt)
+            tauNextMax = max(-A./D);
+            minVal = (tauNextMax-tau)/dt;
+        end
+        
+        function minVal = tau_dot_min_nominal(obj,tau,dt)
+            minVal = (obj.nominal_tau-tau)/dt;
+        end
+                        
+        function sigmaVal = sigma(obj,dmp)
+            a_normalized = dmp.h()./(dmp.tau^2*obj.a_max);          
+            sigmaVal = obj.gamma_a*sum(a_normalized.^2./max(1-a_normalized.^2,obj.gamma_a*obj.eps));
+        end
+
+    end
+end
+
diff --git a/dmp/matlab/TemporalCouplingNoPotentials.m b/dmp/matlab/TemporalCouplingNoPotentials.m
new file mode 100644
index 0000000..de4002e
--- /dev/null
+++ b/dmp/matlab/TemporalCouplingNoPotentials.m
@@ -0,0 +1,100 @@
+classdef TemporalCouplingNoPotentials
+    properties
+        % Settings
+        v_max
+        a_max
+        nominal_tau
+        gamma_nominal
+    end
+    
+    methods
+        function obj = TemporalCouplingNoPotentials(params)
+            obj.nominal_tau = params.nominal_tau;
+            obj.v_max = params.v_max;
+            obj.a_max = params.a_max;
+            obj.gamma_nominal = params.gamma_nominal;
+        end
+      
+        function tau_dot_val = tau_dot(obj,dmp,dt)
+            % DMP prediction step
+            dmp_next = dmp.step(0,dt);
+            
+            % Formulate matrices
+            [A,B,C,D] = obj.tc_mtrcs(dmp);
+            [A_next,~,C_next,~] = obj.tc_mtrcs(dmp_next);
+
+            % Compute bounds
+            tau_dot_min_a = obj.tau_dot_min_a(A,B,C,dmp.tau);
+            tau_dot_max_a = obj.tau_dot_max_a(A,B,C,dmp.tau);
+            tau_dot_min_v = obj.tau_dot_min_v(A_next,D,dmp.tau,dt);
+            tau_dot_min_f = obj.tau_dot_min_f(A_next,B,C_next,dmp.tau,dt);
+            tau_dot_min_nominal = obj.tau_dot_min_nominal(dmp.tau,dt);
+            
+            % Base update law
+            tau_dot_val = obj.gamma_nominal*(obj.nominal_tau-dmp.tau);
+            
+            % Saturate
+            tau_dot_min = max([tau_dot_min_a,tau_dot_min_v,tau_dot_min_f,tau_dot_min_nominal]);
+            if tau_dot_val > tau_dot_max_a
+                tau_dot_val = tau_dot_max_a;
+            end
+            if tau_dot_val < tau_dot_min
+                tau_dot_val = tau_dot_min;
+            end
+        end
+        
+        function [A,B,C,D] = tc_mtrcs(obj,dmp)
+            A = [-dmp.z(); 
+                dmp.z()];
+            B = [-obj.a_max;
+                 -obj.a_max];
+            C = [dmp.h();
+                 -dmp.h()];
+            D = [-obj.v_max;
+                 -obj.v_max];
+        end
+        
+        function minVal = tau_dot_min_a(obj,A,B,C,tau)
+            i = A < 0;
+            minVal = max(-(B(i)*tau^2+C(i))./A(i));
+        end
+        
+        function maxVal = tau_dot_max_a(obj,A,B,C,tau)
+            i = A > 0;
+            maxVal = min(-(B(i)*tau^2+C(i))./A(i));
+        end
+        
+        function minVal = tau_dot_min_f(obj,A,B,C,tau,dt)
+            Ais = A(A<0);
+            Ajs = A(A>0);
+            Bis = B(A<0);
+            Bjs = B(A>0);
+            Cis = C(A<0);
+            Cjs = C(A>0);
+            tauNextMin = -inf;
+            for i=1:length(Ais)
+                for j = 1:length(Ajs)
+                    num = Cis(i)*abs(Ajs(j))+Cjs(j)*abs(Ais(i));
+                    den = abs(Bis(i)*Ajs(j))+abs(Bjs(j)*Ais(i));
+                    if num > 0
+                        if sqrt(num/den) > tauNextMin
+                            tauNextMin = sqrt(num/den);
+                        end
+                    end
+                end
+            end
+            minVal = (tauNextMin-tau)/dt;
+        end
+        
+        function minVal = tau_dot_min_v(obj,A,D,tau,dt)
+            tauNextMax = max(-A./D);
+            minVal = (tauNextMax-tau)/dt;
+        end
+        
+        function minVal = tau_dot_min_nominal(obj,tau,dt)
+            minVal = (obj.nominal_tau-tau)/dt;
+        end
+
+    end
+end
+
diff --git a/dmp/matlab/main.m b/dmp/matlab/main.m
new file mode 100644
index 0000000..56e6400
--- /dev/null
+++ b/dmp/matlab/main.m
@@ -0,0 +1,55 @@
+clearvars
+clc
+close all 
+
+% Create demonstration trajectory
+load('trajectories/g')
+% load('trajectories/omega')
+% load('trajectories/z')
+% load('trajectories/s')
+% load('trajectories/psi')
+
+% Nominal trajectory functions
+dmp_params.D = 20;
+dmp_params.K = dmp_params.D^2/4;
+dmp_params.n_kernel = 100;
+dmp_params.alpha_s = 1;
+dmp = DMP(dmp_params,demo_traj);
+
+% Simulation setup
+sim_params.dt = 1/1000;
+sim_params.T_max = 100;
+sim_params.kv = 10;
+sim_params.kp = sim_params.kv^2/4;
+
+nominalTraj = dmp.rollout(sim_params.dt);
+sim_params.a_max = 0.5*[max(abs(nominalTraj.acc(1,:))); max(abs(nominalTraj.acc(2,:)))];
+sim_params.v_max = inf*[1 1]';
+sim_params.s_v_max_online = 0.65;
+sim_params.v_max_online = [inf;0.15];
+% sim_params.v_max_online = inf*[1 1]';
+
+% Scaling parameters
+tc_params.nominal_tau = dmp.nominal_tau;
+tc_params.eps = 1e-3;
+tc_params.gamma_nominal = 1;
+tc_params.gamma_a = 0.5;
+tc_params.a_max = sim_params.a_max; 
+tc_params.v_max = sim_params.v_max;
+
+% Create temporal coupling objects
+tc = {};
+tc{1} = TemporalCoupling(tc_params);
+tc{2} = NoTemporalCoupling(tc_params);
+tc{3} = TemporalCouplingNoPotentials(tc_params);
+
+% Simulate
+nSim = length(tc);
+res = cell(length(tc),1);
+for d = 1:nSim
+    disp(['Running simulation ' num2str(d) '/' num2str(length(tc)) '...']);
+    res{d} = run_simulation(dmp,tc{d},sim_params);   
+end
+
+% Plot result
+plot_result
diff --git a/dmp/matlab/plot_result.m b/dmp/matlab/plot_result.m
new file mode 100644
index 0000000..50571b3
--- /dev/null
+++ b/dmp/matlab/plot_result.m
@@ -0,0 +1,110 @@
+close all
+
+
+figure('Name','Velocity')
+
+subplot(2,1,1)
+plot(res{1}.s,res{1}.ref_vel(1,:),'b-','LineWidth',1.5), hold on
+plot(res{2}.s,res{2}.ref_vel(1,:),'k--','LineWidth',1.5)
+plot(res{3}.s,res{3}.ref_vel(1,:),'m-.','LineWidth',1.5)
+plot([0 sim_params.s_v_max_online],[sim_params.v_max_online(1) sim_params.v_max_online(1)],'r:','LineWidth',1)
+plot([0 sim_params.s_v_max_online],-[sim_params.v_max_online(1) sim_params.v_max_online(1)],'r:','LineWidth',1)
+yticks([])
+xticks([round(min([res{1}.s res{2}.s res{3}.s]),2) sim_params.s_v_max_online 0.9 1])
+xlim([min([res{1}.s res{2}.s res{3}.s]) 1])
+xlabel('$s$', 'Interpreter','latex','Fontsize',30)
+ylim([min([res{2}.ref_vel(1,:) res{2}.ref_vel(2,:)]) max([res{2}.ref_vel(1,:) res{2}.ref_vel(2,:)])])
+ylabel('$\dot{y}_1$', 'Interpreter','latex','Fontsize',30)
+set(gca,'XDir','reverse')
+set(gca,'FontSize',16)
+
+subplot(2,1,2)
+plot(res{1}.s,res{1}.ref_vel(2,:),'b-','LineWidth',1.5), hold on
+plot(res{2}.s,res{2}.ref_vel(2,:),'k--','LineWidth',1.5)
+plot(res{3}.s,res{3}.ref_vel(2,:),'m-.','LineWidth',1.5)
+plot([0 sim_params.s_v_max_online],[sim_params.v_max_online(2) sim_params.v_max_online(2)],'r:','LineWidth',1)
+plot([0 sim_params.s_v_max_online],-[sim_params.v_max_online(2) sim_params.v_max_online(2)],'r:','LineWidth',1)
+yticks([-sim_params.v_max_online(2) 0 sim_params.v_max_online(2)])
+set(gca, 'YTickLabel', {'-v_{max}','0','v_{max}'},'FontSize',16);
+xticks([round(min([res{1}.s res{2}.s res{3}.s]),2) sim_params.s_v_max_online 0.9 1])
+xlim([min([res{1}.s res{2}.s res{3}.s]) 1])
+xlabel('$s$', 'Interpreter','latex','Fontsize',30)
+ylim([min([res{2}.ref_vel(1,:) res{2}.ref_vel(2,:)]) max([res{2}.ref_vel(1,:) res{2}.ref_vel(2,:)])])
+ylabel('$\dot{y}_2$', 'Interpreter','latex','Fontsize',30)
+set(gca,'XDir','reverse')
+
+figure('Name','Acceleration')
+subplot(2,1,1)
+plot(res{1}.s,res{1}.ref_acc(1,:),'b-','LineWidth',1.5), hold on
+plot(res{2}.s,res{2}.ref_acc(1,:),'k--','LineWidth',1.5)
+plot(res{3}.s,res{3}.ref_acc(1,:),'m-.','LineWidth',1.5)
+plot([res{3}.s(1) res{3}.s(end)],[sim_params.a_max(1) sim_params.a_max(1)],'r:','LineWidth',1)
+plot([res{3}.s(1) res{3}.s(end)],-[sim_params.a_max(1) sim_params.a_max(1)],'r:','LineWidth',1)
+plot([res{1}.s(1) res{1}.s(end)],[sim_params.a_max(1) sim_params.a_max(1)],'r:','LineWidth',1)
+plot([res{1}.s(1) res{1}.s(end)],-[sim_params.a_max(1) sim_params.a_max(1)],'r:','LineWidth',1)
+xticks([round(min([res{1}.s res{2}.s res{3}.s]),2) sim_params.s_v_max_online 0.9 1])
+yticks([-sim_params.a_max(1) 0 sim_params.a_max(1)])
+set(gca, 'YTickLabel', {'-a_{max}','0','a_{max}'},'FontSize',16);
+xlim([min([res{1}.s res{2}.s res{3}.s]) 1])
+xlabel('$s$', 'Interpreter','latex','Fontsize',30)
+ylim([min([res{2}.ref_acc(1,:) res{2}.ref_acc(2,:)]) max([res{2}.ref_acc(1,:) res{2}.ref_acc(2,:)])])
+ylabel('$\ddot{y}_1$', 'Interpreter','latex','Fontsize',30)
+set(gca,'XDir','reverse')
+
+subplot(2,1,2)
+plot(res{1}.s,res{1}.ref_acc(2,:),'b-','LineWidth',1.5), hold on
+plot(res{2}.s,res{2}.ref_acc(2,:),'k--','LineWidth',1.5)
+plot(res{3}.s,res{3}.ref_acc(2,:),'m-.','LineWidth',1.5)
+plot([res{3}.s(1) res{3}.s(end)],[sim_params.a_max(2) sim_params.a_max(2)],'r:','LineWidth',1)
+plot([res{3}.s(1) res{3}.s(end)],-[sim_params.a_max(2) sim_params.a_max(2)],'r:','LineWidth',1)
+plot([res{1}.s(1) res{1}.s(end)],[sim_params.a_max(2) sim_params.a_max(2)],'r:','LineWidth',1)
+plot([res{1}.s(1) res{1}.s(end)],-[sim_params.a_max(2) sim_params.a_max(2)],'r:','LineWidth',1)
+xticks([round(min([res{1}.s res{2}.s res{3}.s]),2) sim_params.s_v_max_online 0.9 1])
+yticks([-sim_params.a_max(2) 0 sim_params.a_max(2)])
+set(gca, 'YTickLabel', {'-a_{max}','0','a_{max}'},'FontSize',16);
+xlim([min([res{1}.s res{2}.s res{3}.s]) 1])
+xlabel('$s$', 'Interpreter','latex','Fontsize',30)
+ylim([min([res{2}.ref_acc(1,:) res{2}.ref_acc(2,:)]) max([res{2}.ref_acc(1,:) res{2}.ref_acc(2,:)])])
+ylabel('$\ddot{y}_2$', 'Interpreter','latex','Fontsize',30)
+set(gca,'XDir','reverse')
+
+% Path
+figure('Name','Path')
+clf
+tmp = 200;
+plot(res{1}.ref_pos(1,1:tmp:end),res{1}.ref_pos(2,1:tmp:end),'g*','LineWidth',8), hold on
+plot(res{1}.sys_pos(1,:),res{1}.sys_pos(2,:),'b-','LineWidth',2.5)
+plot(res{2}.sys_pos(1,:),res{2}.sys_pos(2,:),'k--','LineWidth',2.5)
+plot(res{3}.sys_pos(1,:),res{3}.sys_pos(2,:),'m-.','LineWidth',2.5)
+xlabel('$\xi_{1}$', 'Interpreter','latex','Fontsize',30)
+ylabel('$\xi_{2}$', 'Interpreter','latex','Fontsize',30)
+xticks([])
+yticks([])
+
+% Tau
+figure('Name','Tau')
+plot(res{1}.s,res{1}.tau,'b','LineWidth',2.5), hold on
+plot(res{2}.s,res{2}.tau,'k--','LineWidth',2.5)
+plot(res{3}.s,res{3}.tau,'m-.','LineWidth',2.5)
+xticks([round(min([res{1}.s res{2}.s res{3}.s]),2) sim_params.s_v_max_online 0.9 1])
+yticks([])
+set(gca,'FontSize',16)
+xlim([min([res{1}.s res{2}.s res{3}.s]) 1])
+ylim([0.9*dmp.nominal_tau 1.05*max(res{1}.tau)])
+xlabel('$s$', 'Interpreter','latex','Fontsize',30)
+ylabel('$\tau$', 'Interpreter','latex','Fontsize',30)
+set(gca,'XDir','reverse')
+
+
+% s
+figure('Name','s')
+plot(res{1}.t,res{1}.s,'b','LineWidth',2.5), hold on
+plot(res{2}.t,res{2}.s,'k--','LineWidth',2.5)
+plot(res{3}.t,res{3}.s,'m-.','LineWidth',2.5)
+yticks([round(min([res{1}.s res{2}.s res{3}.s]),2) sim_params.s_v_max_online 0.9 1])
+set(gca,'FontSize',20)
+xlim([0 1.05*max([res{1}.t(end) res{2}.t(end) res{3}.t(end)])])
+ylim([0.9*res{1}.s(end) 1.05])
+xlabel('$t$', 'Interpreter','latex','Fontsize',40)
+ylabel('$s$', 'Interpreter','latex','Fontsize',40)
+
diff --git a/dmp/matlab/run_simulation.m b/dmp/matlab/run_simulation.m
new file mode 100644
index 0000000..1ce873a
--- /dev/null
+++ b/dmp/matlab/run_simulation.m
@@ -0,0 +1,65 @@
+function res = run_simulation(dmp,tmp_couple,params)
+
+% Parameters
+dt = params.dt;
+T_max = params.T_max;
+kp = params.kp;
+kv = params.kv;
+a_max = params.a_max;
+v_max = params.v_max;
+s_v_max_online = params.s_v_max_online;
+v_max_online = params.v_max_online;
+
+% Initialize
+dmp = dmp.init();
+t = 0;
+k = 1;
+sys.pos = dmp.ref_pos();
+sys.vel = 0*sys.pos;
+sys.acc = 0*sys.pos;
+
+while t < T_max
+    % Store values
+    res.t(k) = t;
+    res.s(k) = dmp.s();
+    res.ref_pos(:,k) = dmp.ref_pos();
+    res.ref_vel(:,k) = dmp.ref_vel();
+    res.ref_acc(:,k) = dmp.ref_acc();
+    res.sys_pos(:,k) = sys.pos;
+    res.sys_vel(:,k) = sys.vel;
+    res.sys_acc(:,k) = sys.acc;
+    res.tau(k) = dmp.tau;
+
+    % Final position convergence condition
+    if norm(dmp.ref_pos()-dmp.g) < 1e-2
+        break;
+    end
+
+    % Perform one time step
+    k = k + 1;
+    t = t + dt;
+    
+    % Add velocity limit online
+    if dmp.s() < s_v_max_online
+        v_max = v_max_online;
+        tmp_couple.v_max= v_max_online;
+    end
+
+    % Step trajectory generator
+    tau_dot = tmp_couple.tau_dot(dmp,dt);
+    dmp = dmp.step(tau_dot,dt); 
+
+    % Controller
+    sys_acc_ctrl = dmp.ref_acc() + kv*(dmp.ref_vel()-sys.vel) + kp*(dmp.ref_pos()-sys.pos);
+    % Saturate acceleration
+    sys_acc_ctrl = min(max(sys_acc_ctrl,-a_max),a_max);
+    % Velocity integration
+    vel_prev = sys.vel;
+    sys.vel = sys.vel + sys_acc_ctrl*dt;
+    % Saturate velocity
+    sys.vel = min(max(sys.vel,-v_max),v_max);
+    sys.acc = (sys.vel-vel_prev)/dt;
+    % Position integration
+    sys.pos = sys.pos + sys.vel*dt;
+
+end
\ No newline at end of file
diff --git a/dmp/matlab/trajectories/g.mat b/dmp/matlab/trajectories/g.mat
new file mode 100644
index 0000000000000000000000000000000000000000..e03f71a1b5d2900da911de5751cec75588386db4
GIT binary patch
literal 1937
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
ZYQ5*2?fzW<E9SyZGuD5MDw_kp0|2w3u`>Vw

literal 0
HcmV?d00001

diff --git a/dmp/matlab/trajectories/omega.mat b/dmp/matlab/trajectories/omega.mat
new file mode 100644
index 0000000000000000000000000000000000000000..8cd3b2b1561142fbc2ee4b9bd768e1773333c6bd
GIT binary patch
literal 10525
zcmeZu4DoSvQZUssQ1EpO(M`+DN!3vZ$Vn_o%P-2cQV4Jk_w+L}(NS<NN=+<DO;O0t
zvr-7jC{=JtO;#{8S1>fOGPbZXF;y@!Ffvde5-`93qo*%F0|UcU4F-maIdi60T7+J_
z{heRZxPM|=pq8eK(Vgg%AyOWmUWYt2KF??gSi;lUF=?TOsN}2-XM){jKEIJE_IM`r
z>D_1R=d$a*SIw)RSG%tE?dO}>Z@0et{jcu&)^E>L1vu)z32@~6n96KFlk-dS)Pp|%
z&!6m^A9n4!?3viPx;g*-?Zy7M=RZI0AO5GLq(E^;^lf1s9bL{nCTYL-Ki>RT{BgMP
zI+kNHH~znCk^k3t{_MNjPUc^x%sN3feSGq#6F;OY)Jp_Z>cpJc5zl7azr#=a{>qds
z*BcsUH~Ahn>Abj}@yPu>uCF3f-2SVbs95#$?L!aa$2-FUII}a~-oA3KVjpu>?Ygh;
zt#2QdST60ee*K>>^%qV{^fP^azv`o$$gv$E0rjFsbza;)FHz6XlySI&-{_fS%dUvb
zxYK(SkJTJj5Hf82FP(VCnoIoSy`92~dw$j*@V37--_T9wvBAqqr>@f9EXwmZEgq<}
zo&Pgg@Vd&6OS@u!9PP;GVk_8HTihl1Tx7%PRd&XgW~Uvo=G~pTEuehO?8GCs%<3O6
zPG?V-_;|kQ^fkkz!|jo7a>W9>H`*y*&F`CdUZ&>g;;%M_=TBtIX($yIu}O<b{M2RW
zUa<c2wT-N9^Y$mQuf2Z!eoxK+0~@#Qs?TcrXYlDCGhfaY264%s`c5Xsxefb!tp2q6
z{}=1pTK_loN;2oJ|7B|@YQ!X6NtF!CJiG98&o7<kCpl3bGf#3Y_S0VQTYHL#_TT=%
z_4Nt%?+&EffA0_69@-&cncOjTozW}z16Iq0zg&MMWKbo`d4px`Z)+yE_3Dhj-HV$!
zgx%I_3m@y>9`@TH@yjox#M>E9r4tUlC`~&i@^OXGmzjoDduJNHeVFW2zImo$)!mtf
z!mE{B)i;_-?ERN*5FHh<{dz))?6m~D>6yIQ2D{{RZXAw_Iv8oNOHU_4=xv!Ex7+o0
z*54OAwFR`@u6K%Rn=e#7*LCr0($QNPdGe`8U+mhLXrJ+Ne#+q&zcwa%_dXSy`7=i%
z*4?a!eZTbPiL#4dpX|$B<STum?_z1{@o$njE4Ij{AAj+yD53qM#yN?igp#?I8;q-b
z=6smRy!iFmM#0rFWhZkU9(l2=IBA}HChNl^FMbs#Ell0gU}?CE|5{S#mM!Pj9DPw2
z(Y<&1+Gp#t4R`5ZOHwttbFB5^--E5DwRhXB8@Lz$ZsC?b6xuuE(V-W0508o2ZPKos
z|M=L8eGiXW6l~IZbnL~yhsUm6KBacF`C{#n=C>2g`|Tx;HDCODq&f4#ve{1$zS#HZ
zsNegmuO6B`J^JF`qoX>;pFf_cFx+*%!f<=6iSmcUlKmeO%P(g-eM~I5|1q)ff23QD
z#NGNoHzH@rRR5H;dvg4YvUs8E56QYG$8)4IWPeKTdvaVRb9z=?oBdD2_5XFa>)QNT
zH#D%D9Of|iqt$SCxofWGfe&jL#C#{)x-~qEXVeLtuQrF_@NuRarv+vyF!9)PCq-__
z{KjciquWutZ0cpN2@mrf*M!UtlW=T1&$=<+aZ3xUWS#htS()E{sh{|;SKwOn>MhZ6
z9S`djb6yk_$4=TRkSxoQIC+c7qZWzRjvT*zC-<rxi4b>^sJ$+5EaSJI*!TMV?+yNo
z|L&8&7a!PIHf5pd|DE29y7}A9w_2<&J#VPL_FH4r&b|ZMM~zJ4C&k!wZ(eb1=Y$o^
zsT!x$9^AJ$SKixXDl_HOg$-`y?-b7UPD?tsd+O;6obyF@$IZ!q(WSTivCdELa$ogx
z-v0ORe>l8zzfr-|V|86$efxe?JpJqzu3lKTJ9pO4H}{OT%(AMlSC%^;a=ymB-9=I<
zZT=nEzT)s5=Wm?88T6%B<n6ynolMqdGuaK7PG7XO?3Lo>Y>fkYJIwREmWj-L8uD`D
zqXh><{Xa6M{uV0nP5yp_OP_VeC7rY91-mCcnz(k|oJS%WU!LB1vwJ&-ZAg#i*GbC`
zxIg{OmbE8duvMw1CaRN(ZJx?OZGL;DdObt=Y+J59arXW<ZqIJc+H&c4>RF8s<u4zl
z{{I`9G5@Ek+T+(E8QO-Ca)sv{>Q|qW&fnw7cqwLW=6W|SD_e<I73LF|;**Wf=RWpv
zcz@yEk`@6jmDwKF&#u}#-MN0&eC~e##&fZpPrc^9Q_kdEottH$+?>Dq_Of>iN-pa%
z|6C{%FnLz#e)9+2|1$DKG7nhZxOdd)%6;j|*|kZ*9E%S)YRxa5+94h#A<<ti;K%6g
z?mAidY1|9*!YiG>W-u`=<+rH*TO-g|QR40(#M-u=oogoFPsNu%u9Z)X6q#V6Z9hv(
zvZc&w=aW4v7d3?c2wwF3;O~r|N8T@e?ksXcZS(#6k1|z0$<475-ZYKt(f6kIPfSSy
z{>L@mKVj55^7re;>y{H5{3d*znz}BiaZljK{>F3MC70Odc6%;qn&R+ni+h}w)vf;r
zbl1-1`gs0Nv2V|1!H1<qAHSFW{ZM_r_};wInH`qTzs_jRwEt0DxW-quzW*7|6*lAf
z-<khEx&7?Hyqqgi(#xxIcgTy~t*iAvdEW8C^d-rP)(l_Es%~H3^>pD|_dA@^W7r-X
zauiH0+t=Sw@N#y;<>QPNLOS=PUjF8ky?)`x&bmT|X-{0Q&7NN4)*8KL`Bpx@L&Cei
zCfxYPT05KFnRC121-{zM$e5p^OQQ=t`}WGW?Dksv>E1-v7gzfhFaBfC=D6Qc<#60y
zfrYo1zYW{Q!}v6F*1vP_TQkbF=bv($tXSc~YbJMH%jw=}5vR+C6+Z~tY&fZ~lB0B=
zt%_KXA<MeQ#j}^}>b~%-xBGPSX=i~auXL-+cX3#1a?OvkG2q!W)2+@e*VW^4d6CQA
zN(nK!C+1u4YC7GH;bos%-1hL3{^9SNC%1N#a(}P-w*T;g3HBCibVE9}`7b+t`en}n
z>#mHX+vnG>c>PBD_?sVsFM@gBZQA{nbz=YP*Qd_+9yl-P_j%eS|BQe$`~OUTs9|Hs
zty-&h(tTbjd(NcKZi)>$6MtRM7w^?unWXr--r?=Sv~Nb=_+Py0O?+s+z20GI|I4{^
zm%hKCRqESw<N$xc*58xvZ8K;7nG(LGOIDKkE_di|?RCo);@Xv-)psUuh^Tnc{`lYW
zj5dGQ{Oe~VbneRXDdqFJPyg2wCTMc(VQbjMU5@tdPXu4fAAD)fx9Xx{rnZ-zLZwNy
z!<WYv5^mF%+x!vcbo#ztP5N8EbK<)FZ~DVI4}7gV@xtITOH1^7bMa1}#@UM2N3B}b
z6z+!n{FoGHRrCDc1c7aJOeH05xp86pTBXi^cVWHAxxs4p!}D80&0M6fYhT~&-@sL`
zU74uB-lOc!_u8+QIdqcs$Bt0D7catA%H~V7`>TdroO01WVW0b#CmX*MO89&#epUF3
zYrg+!!}iL)!#PaT&wcVz<f-FdW3kSXFI7F+tTRird1JrhM~=@HPwdN9eB;(>wBOA<
z-&eG+vDdBj;??y_6(rwm`n}?`#EfGy`wB7^@NB86**bGuzoW>_N|U06GVeS?=G*)I
zWBi!IdTjP`?FVmO-F?_=XYX(!>G0Xssy~12dv+)6zQTVaZuPG|^-Wx#_MZE@TD|ws
zu}h*!3u;V{h#i|1S0LHi9R7Xkq4ul`&o({G7L{gwZXMYF|HBoBZx)%63kz7@&G^mf
zBDb<pSoxl4xL*H(D{;rCNH5QBc(lf5>3JI_)y``^-=}6JoZrwM>G{dvM-i(_#`%!u
zWlwf|j6It;A-YqHkAF>@bF8Y{_3HKql`8eOzMs^x_@6n^`VjYjz8iYePt`8qGBW;N
z)yB>1xHBVl$&IC69n0U{l>J^NAauTx^-jsU2HQ5BGhS8A1%E#o=ii(CR6)7s(!1{`
z7_R7kTo7BADv)9;yR@jD;nefGA1durn$A4CYu_r$zF=v4cG!bT&WaTpe6i9m+Jz5p
z-=(s;+wp{dXo|)<`Atn7j;VK!Ce+<>t@;>azvcK*yAx8{O`ngM=LMR5W1e4k`C`mO
zC68|fmn+TvS|8u%*3wTAYYM9JY^~%J&D$WR_gqYb>1Joe%72og7Dwx<Wh~-Y-rh~>
ztSetpkaef_{bFMdrn^l3)^`^)&2MvicvAal!Ip1t{`7f=yhxt-(YksE%Z<ptMv?x(
z3om}Z?C01U<nhQ>=HD|7(Qnr7b@Q+4Gv8M|{aR~Ph(Uff@3c)C?T<ZQ_WQqC?sO|N
zoBi`_(F4&R3by96i-tWF+gETb<j~q#x<PYhubiM`b7k}ASW%DPCVPIXdbQqo*<sZF
zC@Uap@6UI_@}hY={raYaUvFTYeLL9RPwT{L>s3FeUTZ4%d|S&bruD}l{&}tGW9b_;
z6NFRM0vglZRDVr3=lsXFDm*4;*?~*j<Ydd9T4lU?AO9%&$oKB2`)}q<v5L6%NAJ3c
zf8(Ey0}XQP-(Pq<<J*^OJp1IA+26Q-Dv&?wy2q*0lSL{jtBMv!y4cPskh5Q5>BlH)
zd+<%^9A1OXH$7uZTbSJ59os5hDz)H2x`My_zqu=4$4z|l^ghGOwsWga?fvm@+gX)r
z#r=%CzTY$xwEpndAok*kgdL2Z!lm{dF%MSAe{Lr(A7{j}{ImSr)yo}HCV%|AwJ2r9
zgZ+0)UQ4sS`hD#R=c`E%zdo9o&i>)=Tb6CdDmQCNe!FXY_I{)r<LVWT2UD|+cv9{x
zXHn#8`6QR%y-mION%+*IE10-mlxWEZ7AYJ))&BYR`}&0rqR-nWyp&E!xOhM2?f;of
zr|fp0I{x9`oBhUJ`j2&1TwY^W*vpeItk<>n!JUOC%I?hcXj`uy?6G@)P{Z!6=T?8=
zlHA2^_T%cK$M54enJ1d5JIgG88y(`p`2FyHk*)d@9B-!lyD~qCYmHEF=;Lz}AHG=s
zLn+%PPF?q+(lX-|h0Qq=V%IHjczb>MwsOCT3lqY2Sni(1^orLyX1m0MM2~+<x9ZQ^
zzkA{Fdw#Y?Pg0hO%&1%5Q26ej_RU)<AC7Unl$gmRbc%KQvc3rqYxgI{)d{oC<2-t&
zVufeh%$M(PYej23cpG$Ho*`wz#qDc8W-VsO-{s-6(n`|odXfE$tmOxK_Rr{8Cnb4j
z)9&171+{$r5;KZcPI`FY-E_t!eq38bc(-kqQ)=G(Rjzcm-k-m#=1tlV-^!zJb*uDt
zL0#p88Ez*Wjc%xPJnJY6c6hNqmD~E9wa~irZ;#%5;PY~QNvhEv=Xct-3-c}-@N7F6
zna3&{cX0mvq`Nld66x1x?OC<n;yg?F-;g7ghN`*CMbGUz`{>>(i}dv~JtB`hz9@6o
zF0IA*^I`AXd5_m@eR82h_<8lDGasb;?TfYM7)w8Qb?p=mv)G<@uGXk`b5YT(RMUCu
z69Y;%YRSnzlq!qkdVW9JbHCh!J?DOUPUerBe{iXUNzdm)GiLfZYqQ2}?f-x2(C6M&
zD`Rdp8DFe9^GWpF@pGabmXE%^eb;^SNb~jO-=0sNp>*eb=04j8ZN@j$B|krybNI@!
zEA7S?J+kh)#?0R-U-h%9qW0&pb!>aGmo)sjGWAo;oatXh%MBjCDKvcfG%bd|xk%Su
zIOhI!CgH`37V`UxYwdP7G97v*@-lKx@U|mgK0I2ZwtUAorgiC8Co0&p*ZkFaZ@DbI
z>2uUqhK*@=^dpTAX9h{7e3+D%5p=lnT5{qay>l)`+1YNg^X51Gzrt}YnbAE|r68^H
zm)awZchff>e*QzrQ=}s|_l(z}o4)FQxx~-?zx;mM|Nj9J9?|vIKJ053^`-wx;d9xg
z!<!uKzj#Nsc)ZI;u0=b(*>mZ#wRK$S-I6CO?sWXOep~k&n_iKaJLj(C3c9FluU@>Z
zoi`xnPF3I9s2Y!lp(_?-KM-7!u%+?!6aBC)Rm*#SPv68dp>MIdo<F-uOx%WB`#)}H
zTJ)lS_Rrg8PUVe%_BbxHU$bgm0^?h&2NP>oJ^Jazb42rQ@9odGm@dh$@=aN{?C^)5
zY3Fa+m}{8p7VeSzBDiB|cctFs=EQ#f*$;bn7)kJjZTM>?#%sgORhhi6^g#al_@xKG
zG2Pi;uwr&xM%$(ZT!(%?E&1?1W%c$a?^;%_+LDn~C$>jdmCrurKKp6M=QCULo;le^
zs;oZV#uc-sb@`{X&x)ak&-}dgvu;N2?wDse-vn(URi&*<e<@Bc{?NI)P)_6B?TXg-
z2BJaR)>W4#R-65hnRn*<%Xh6U$*G!?%GN({E3M%*FIG?S)3aB7b+mEilb4CS+tWUD
z+h<Q*{g%I2*@^x5{A-O(ua>M}yq&m3D>ZOs{X!lOL$_mD@@oTJnpPa&#r?D5?~x_n
z=dc?1)kN%Dt;pN)?;*c#QvRVs(=?}<eKimWpDn)sqaD+)%KO5$+wZspy2gCAymwwP
z|4`n4sjJIZv~5YPo_RQX$Ej<ltG+$Sp7Ky_{ggGcxMlYIw|kv`!uc;R)1;MgtO<W>
z-d}M%tF%Pz>=#A*l_F_5wYp1xpS}=t^Qi9fXIcxBgDZ{;zRsHRVs}_@?M^Y7Emu9K
z`+9VI^(v_Ic~s7^`OkxMLc#q^atY1pYElcHRQ>rZS7)><)uTeWZlmC#L$B7od7j~7
zTzA)1Q`7gr>n}f31M-xuJS482`hSBby-B=h?KLyS=lh#jHt*KmaPHC6=eKvdT?s$<
z#rjV?_m9<w{Pj<}J-MSSy32Kes7=xB-23y?7q52VKe+UgScUlYu&9gC{p-ZakJsG1
z%Jkht_Dstn506qSgPjMrNnZPZrXpt3I<~)6Ro?sA=kNE6S>*MnmUY(SM_fMg*)6)K
zw_lrfSKC$IHkMcQi_}5;Tm4UjJ0@tf_e@M<-6wZ_^1h#Sf18Z5EYG(`O?r6w^v;dm
zbw5|!+H95OFp1~-)i>8`%l<c%J-vU!>Yxu>`fS!pwc9>d3|C)2yQz(5`H%ROZZ^Jd
z>sE8lUp(bRLEoa;g%3S7gdQgv^E#y%+}iH><IP46fvO2JvqNrhJi4~NFY8=-L*()e
z=faMr{jqkxvNrsc@|)6sRz-7{iaxnr|9`J`2vgrLajW?CTO40s_;~H}kLtDYnnHH}
zb~D!qEqib8rFc;Hy$bL5XL=WG4h43IoG>`GIIsTJTK2U5CH}X4%^PzgdggnE>G$-=
zWasR<$aOxrsVscvcSipMlOC>AfBRsufcT!1JNakSt?88CbB9y%d6`o8$G97%+iq8`
zSit>*`EI@F*6$3<)&-U7uaw^B+s-9tcZqjm{?(sq*S;K3xSjHEo$cHOUP{$@^Io)R
zt>xc(^J4A=zb>xH1+Uw<8rO9hf1kB5+i_FWu6^7suiwPy-*;*2_`EvbwY<!+z3yXH
zVZE-!Cl$@N{qI_qd<u!Q`)X8hKK9(b1NS)(AG&1udA9u_zvHo+zb9EMI4@Yf-`bY*
z+fm(^+0)-MC<@J<@AWA;B~i|JQ|2mJCSC0|(YDQkw;$!(eZ5vz;o+<PNk-FUlkKHP
zr~kfv@V_bPbMXS6wcj7E<b3doVZH1^-hPd%8a4eBY$LZa$A!$e8GmM-^F`-NT!m_~
z2kIuznW*UP_VrHq6n(k34CVe!wM-j1uZlz*d)>e7aHe<m|B&TkQ`Ussve~y<c2;W2
z>Q7T{UpOhSe75rcD9202+sqW!%9aYnZ1IoDWsG~+V0FD;R%1os{IB-w)eJQEKY#G#
za_6~%BU)_IkABy^d(7+<6YH_>fm%}1U%uHp+@374-F1QOa=Y-X*Vzk7FO<D0Wxn@s
z+51n^*BM2WRVlvKx!N0&s=AMZMf5=I?rF#W=ank&eZBPil(_VRlg|9ITC-c)_0(67
zkW3e*hp&<x_NMV$EfFtW`6XEBSMM{`)kW18c;A1JdFWi}@!)`}AMe#Tl}lG{exA9V
z<?Y1hXTD^<a4ixpnl!s)^@TmbpD$Z&wtJ$@mY%voWy||xX8hg#wJ!t}Ke>j)F>ktO
zw?9^IJAdxe%e$tQuM!k|B=jVD%C8H(NBkM5uJX-Top<sf&(^pphq7GGe#~|XV@ua)
zkJ=qLM<lVzbs48-)$SQKg0G!6^`AZ#6(T(`Bzeh&xQTpURO}wLve^CGwPnKfq`PZ9
zo;jy}UA(sR#Uw@X8F%yCYK3iX?{Qi!@Za^N5dS~7EtdO2zTG;Uv_zrC(8+bD+}ym+
zcO$DTxlbOk^R}<pB*y#Z-PD~4G8|{x)qXvy(Vj5l{ld!6lYc&#bF1#bryxTm>9!wV
z+NU;uJGS5D_uu${EncTz^sxxN*$~nYayBO9?;7W-Ze2+;mfB5O#^;=-UF3gNqcnTL
zzt7h$RBrY8VrQVVtzd_wSoX}h?$eAWTtAwB{^#VV1pjv9_Mfv$p3Hcynr(2E$#?U|
z{*t@#ia)<UoH?gk_rd2I<-2Mvc{%mm)NX}tb2xmDeJ5+sN)6xH=S!Otxdr5=-@JKl
zkHaC6wewFUo}Hk%^17_$SDw8m1;3uzagF7??&fzJzaLYqo>cek5s%~&`Hgp0?f)Th
za&~9Yp3B(`@7iJyyPLZz3QhhgF4$|eL4I#U$YX)VDXF*GRJLR<d|5Pk$21p~SAP;t
zdP%Kjnz~=InLkPC!rhzMUhaIMhvr!vereq|Q6uW{gp$P$tb20ewnod#wK5q;Kic`^
zlw*z78UHp_sm=|ldxb7*Gv~3MlInYNT%+pe&I_z7gCzbbPOf)S6I;2%`0U>LK%Pen
z_bg>kPoDVVo2GB>ai@xxb)MT+sf#U575?JCriQ7Nc@MAR?W924W6N$Xn8-b~yRGXb
zm!Zad-Qu(Ja^F8JmdK3VbTHXu`iez=F8@?LBlh-0otA8`+4>jjRDP&CEju~?jo?KM
zlY>czMdgJURW?7X_IfU-@TIr)yv<?mBYW-Z)V0`@SX-sd?56iEnzM86^Lr{gm7F3B
zy{GnQE9E7}1#n+=GCrLu`*`bifs4n!^c?1tj<^!C<%89;{zpkCPVtu8Dol1()_oAe
zpjB7?XyP|D`yXq5bbU{)V&D>1KL4chKI7t)e|NWDWYlo~>vDchg~5s?CNf4BxgECu
zx1Ah(tB^m2sma2&>aU>TwzM33u12-q_dDHn{|Kt=kI$LQ-|F*kqRdG?`<9^fb}wJ;
z;P+i9^)LME-wPjNUgu1$mhi9_o6J$Vqt_u%etU)Xzk3J1oY^+NLU`fNT?NykzdKkt
zxNo<=&b;?c&svF{vK(AT&hPaTTlXUMgkt~s$#o7d3V1hdE^=DU-e^?yTWyWrCr<fI
z`};(ut!#IVzN66h%O>Z~OkO3Gsjcy<mQ6dtv!3mlD5^BKTu@=(Rz|01YMlMIrwcAz
z+a5WyMAE}3GWK<<ub`*3(!QsQ1qDp*o@dXoYVP27-S_>?C5E5(FV~d*`|&%qx67g6
ztlyFXcj?K=*PRMCEn8pr<dxE-vvJoii%$)_^Y@?qth982Oy*e|OKx>_+<2e<Qc7GP
zbJ3ztQ|0UhzV^$MaqRC2yT0_)xyZMytg{#1a?<m5c@!?VbP~VQo%fIKt3|Jw*tDeO
zN%wDwBX=cE9K6-((RluFYDfUL$I{Mwdaukp9y)o7bcVBgJU^-uc`n|0HJi}QE9_MQ
z>G7YP!w!laT^lX1XIcf1h}!;gq1gptS37pDOJ`7-e8b884ByH19lqaH<}`$E{q)?d
zt}LVUK}`0m?#T{St`jmUliEENi0AHmFLK0ie({OQjP^%zy6<kkY$<khJ0YudZl}<C
z>tw%&_YF7Qal8F?LQ|D%SgzK+Jgdz3uV=+3_UJ4X7ykHd`J`9YdbgDx-96$h<hVTH
z>X#$0wVSUC1kTv}t5x#eJJpryg%72aHcr_n?)g|IzTkuJQr=1D1*fZBpVzYE)fV&J
zsW}24gVH{kAD#SRKLZ29|Np6zDosSYq>lPZI<-#9JLG!Gr_Jf>+$ohOdQ-eyL;_QG
zwCNeCBwJ0~$)o73lHB%Q;d4QXkCKx}kxcQF>(TH3eg77<f9v&o|KI6`R~H<zJ|Sm4
z$KS5I_fmVVQ1ZE%{AD}#s%g2{uVLq8E!y?^QQ3?Dy)9D@tY(*$6<nUScYR`e-P5u^
zuCX2yE>3J0i@xLP>>PZ=&H3<;+cPu&J^z2Tuip4>epH?F@BH(hr0dOQ{lDziy5ZWQ
zFs@_Yqb{B8iAeHVn0Ec#90QZjQm4M!F6h3yXOY%)-Zz1J`$`nnywT_i^!Gpd{kG$;
zudC1cTDdnEKDYeMo2ajG!+uHi?(Zx$v0t{Y594fIaOq~0q$}@?UHSrsn_f#6%v6`Y
zEfRT<;r2|g<sXW6M15`geA0fOfVps_++qi|?dRjmvgJFO^{p01uNOLg@ciNJYSXtf
z6s<nZv*(tk!I~*g9v^jRI$^y^OqFl;1T&eM6^qsh*KNARI_1|z;a|~~@5R%2ojkY3
znP+PmKRl8vF>#*-+nd0u_42-(g`S<99jF;A{NTe&?Va};dKDH;+3};OTIfdWJG0+i
z8w4t3lE2u8)w4;hJ13YIZ`HK-Z1m(yJH89dnX7Le<ipx$#<w)*tdhZ=>lSLp0bQb+
zN)zpm{JwDOw{!T+mqyn#Wd2V2oG4@)KTFfZ^WwyFKO{bQ8k|*{yH39QKw?@@{HDx$
zujl4A!qLm$&OhT7WgcQ<8gA6N{*d$iMh5AVF|LcxWhOD$hDv^Y{WsDhWbKbY#fw5y
z1Z^g1Wgl|5B$lTA@Z^eCHolGWkMBj_xZrp7v!r^n*Uj$%yun)EJf_8;H>u>WUn^&9
zeEVNl%xz(P*|&DhEwR2Y#GkL%khK1}+4iOMnKWrNeL?XL?jLr%X?m?BvETUqfA`x$
z=j3i*oc3}*&qnh;*LMd)?_AtjaHpt%)g$e@@A*9uhrjdY9Q>uIePQusk>EGGy7sm`
zd;a_8^u|L0a~DnB+Hy#3*1N{tD;L<TnDX$Lzhmd&oS36?L=;S(__|5e9{u}eX-?hF
zVub~dr}~G@I^a{ZeZzyR>kk;6&-}RSEwkE*APKg+%N=exZhLX%wb_~TUGkHJ<e0ZA
zh;3)QWyA4i?&gaeZy6cGBK4~tF_^^exb3>%Ui#9qq*d$p&S+_R_q?mTBzi)M{x<!%
z5<V7DKVzHI(k_n=Fr7+e=W@~BaN2{XC*hgmea7Uyt{pdOPliAJtr6Fsbm!$pr^ZVW
zpJac2>yKDd9?<&v64Mqj%{l6_QchECIdyMpZr)(4yy5@UczLn?7w#wDG36Cx=kxp!
z^Y+li>CxLB<^*q;QQU93d@bYc?;hLY9?xTG`ox*b`(G#|#(<ssq-Mgl{U0VRi{rYK
z6qTWsn|{FKp{BE>Fz223HL6w*Y-X^BOR{HwZ?3VL+Ievv7w?q~&rS2y7QDzjI#+jM
zXos)Wi_Z}Sa{mHDCsnQ3%(#~`Zu#uUl>xHF`<}g>>bs!sLFu#85lx8;pH2Rz82#Xd
zW_^=lHK)b<f|uWO@(<oso&WP%fz}(p6G~I}-D!IJ^Pj9}k;sf>n~yfZxx!(qUmd&o
z?wrF@zKgyumzBPFBcy(6H9zyqko9wY9&kz2)GxMkIoEWSCFx7nTctnFCZ1gjzCC2U
zKYRDNjpv<oO)dWPycGGj<;Bgdf3sxP{rS5!(5`|}TQB1DD&O+PXY-ZJ`^t14Z|;|#
zzgd`T!au2cZ<p6>v!<Mon)tW6KyU3s$F7U|XDpTn9lmGTawvLd=<m8q6VC1St@^Xk
zuthj<*5~J@FFl<9-hK9JKih}YcMoa~^Hl|P7ys$pcEN7W#fSZZPZp|woO8i$d))12
zt~>k^*>7HWOl)?Pw_iDN;?Zpx6At)#TY1i@U2yx87<<QFwRX$x7kdN_yge1%lDhBD
zIo|Z`1$F<fygWB)`G<FZ%`UpUVHaB}JALK!)h(Q>Bm29blz!ndt$VY7v)DYl)Ctd{
zBb{g8oma#hy#Bz4&fXuJ?nqgwSW2EgpPD>xC4=<og`s<1Eq*89{?g&)?>T3Z+)kgE
zd02ZxK{d;EX{Pu!_VGtf|9qWzOnh14%7U#AudTJ5v$WScR3pY=VuILHhq;<HpOzlF
z=bOaoDq3duu*$5<tK{sRKik6$cK7KxPm(xrY`)|=&ysA5<FBIfZr$v4dCgYG+g}>;
z!CGwo_4|EBku{0Gzx_YpwDxLJaktr&s70bezczH<+a^}@ZsFS(m61nW|Go2<N!&2$
z-^%-)yVXN}OW*r*NLuLbGHDm1U3-N#`taX#OBH>#?~(ue50CEc-*YG<!$b0u^?6ah
z?+bgYN`DKhNeL-uPM)n~-tk+0U*);|-?&AatxS@3|Gs$gy5Whk4B@v^+jGoZtP3pG
zm(+dvsCCa`_NrBvpR&vUlK7^!UPs~h^7iD}`}S^Flofb$@i)oSOMQK1V$>B}-?ceU
zDpr2=_P@!MKZRl^c3*#fB>c9*hh4oQ$6H+$zP%Ek$Nz^Xx>`Om(pbOw(mmVXwd-oy
z4TJmYviF7Vuq`dv_3{tbhiU5tellNM&}13BY}y`9v8Kq$XSrTK*t2c=?$=zpj@qYh
zc3n@EUBhb=uzq&q0yDW!?ytU<dR%>4w46UxX+=auSBCETMq63_i2}!cPIwzj+1I9v
zs>CiadZs&*qfY(5&9k&EEIhH%cg%8lTG;1B3Eg*kuIPL~(Q5uDZntw>fy<fI4m_H5
zF0Smk=!vYoKHdrP4f{=Jc!@dfYYgs=aoZRyT;U(gopwTgVf1r7-L)^I3+{WSy<fcT
zfO})a{O>)Y7d9QSTpuaQ{oU#5*E)&o4LesonX}D2$*Xrt#gU&?0(_5)t#_<vpV{Ll
zwb9q~P)_c<O$TlV)_gqCVfnF=JLInBtcN|no7RZ`ziCmqN%Ym;O-kpv&O8o0Dd?7a
zTkVH{?Dgo9`AsX6X0h*=QEhArs{45^f~)98`D}?W(Sz$_dY}Aa|6K7Tao^ERZW3oU
zipEBk%{`XCj#u2iQ}APq_S?@zpCn$n%1$YZs%fj7?tL~jf_<XYoZSZ&Pi);h(Q*5)
z`Fjs5iWc7Wzx^}A_P~nmUw?;tN49oO2yZbxwys2ymAOLyf=4MA*N1a2XS)ltx_><3
zI9W0C_VO7ICOI8GVbU10?d|vC&oT{<UcF7y{K4vNb|t-~BKSc;?z^+hotGt!mM>dv
zr6$|**mZXNO8>=WjM1yES4jQI==R$;!J<|4ZOOIU_cuRSx1l3>-v^deU$Ua@_J=do
zZIRSJ_s_D;F-!8)$&ylmvYqzp{fam$H&6e0OMCVK^CXLJfv>D<mdsiqGvx-;BEh)A
z`s=2PaxVow^_KG$h@C(E)UKGmdU?&A$3Is0hy3IF7_EGBhneiDt^Vt!?zLP$e)gNa
z8}~fD(`(-Z-MDaZvsc)+L#n@j?cFKr8nE5}ug>>u;e^iofH{xOwXV3CRIgs{zhZVu
z<fWn$EaLN~%RLdP=g?3&oN+Taz<9=%GoLwHs`czFYug_yrZp=a(G}xSdt2pnajM}5
zAIH3$2sM@?aZ^g#<GES0wAY_q*C&v`zh2aSUZHqa_1e34ER7PsX9WFRyd`MLkJCTr
z+`L*+aXsbw@jw4eH*MADIoo32TzY-8P|Oc5=bf@gwyzF)5O!h8C9gcie_ayK6`!g%
zU0>I^&hchV&R>_!>x&<8W~58iOi!(C{C%c!X3v@AgC84`pDrsAGg~FZ9d@I0!>adl
zV`oojJQ%%ZtLbX~#FJH*jC@RaJ9ou|b~OcVu!);@WBJsscjhm*#qZ~0p0@0OtmwSX
zjH2)DGY>ufeL-7USZ3p6&Pm6k=1h9kykOVHbNPRy1uxsRy3W$N*ZhjX`IJ>XPf?!K
zu5aIeG^VY4#T-7>qvvf`Pv5EUjW1)XPPVKHFbOmD(2D-ha&Mki^z-YE5|cik$oV``
zdPiHpqH<Xdhj~UXEsB<K=ji-m*z@&Z_Dz17Q{8hG{5be`<<YrvGxmPXt}A(9HO1YY
zr#yCNZ++<I-L+r0x7L&d|28O=?Z27&+k9#C!HC6`eqSev&O5W|`-}ZqY)?-Iwj~R<
zNr<RzKJ0v!gYPSMacjg}xAogThpT&kUGQ$vn_er+zz3&ZKFt=hV}I**`qWx`Q$@QU
z%O>`oF4Wk+{rtuU8wFE7?D!oP`$zbS>(W!A&Sx9-%OX1~OZnYeLkw6$A{%dBPC0-3
zbC5*IV~)$OG^I1lIi!5V!kym#xzq5-`+7oa?rPPgeGPAA-U`~rd=pqw6!m-JK}#Qd
zImH)ms%0aVSkGzK&sf0N+@6y7i1)*(MH}tRR<ybw`L@Nc(!$}_ixsDjnai43)Ya%r
tJTAz0(Ys)V+AGD+lQy_Tbto_Kk1H}<{NnMZ{=07vpY8h~?-nJc0sxA9tY-iK

literal 0
HcmV?d00001

diff --git a/dmp/matlab/trajectories/psi.mat b/dmp/matlab/trajectories/psi.mat
new file mode 100644
index 0000000000000000000000000000000000000000..c1b6372952d1262d5ad2bc6ac09f37ceafd74776
GIT binary patch
literal 3893
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
ZkC>&?=Kfkd<JaY%@%#Sqy8Fi51OR?F@5ulF

literal 0
HcmV?d00001

diff --git a/dmp/matlab/trajectories/s.mat b/dmp/matlab/trajectories/s.mat
new file mode 100644
index 0000000000000000000000000000000000000000..6102e05dd231ec6bbc5abd5191e89a5242db05b5
GIT binary patch
literal 3204
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
ae@@!4Xa7{O=bH1a!~gsKV_x>Fa3cWcF@zle

literal 0
HcmV?d00001

diff --git a/dmp/matlab/trajectories/z.mat b/dmp/matlab/trajectories/z.mat
new file mode 100644
index 0000000000000000000000000000000000000000..09243cdc8e4d974bfd3bc1abade837cd672076b5
GIT binary patch
literal 2094
zcmeZu4DoSvQZUssQ1EpO(M`+DN!3vZ$Vn_o%P-2cQV4Jk_w+L}(NS<NN=+<DO;O0t
zvr-7jC{=JtO;#{8S1>fPGB&g_F;OrwFfvde5-`93qo*%F0|Ub{b_RxuIcvkX147)z
zWdAL2vEw@IF4nW|$ct5-4P7n2w{QtFcQ~?`T-4!GH7wl7lMoUj5GbN6birtcVYd?Z
zEDfuMADvqiI=U6k@EkTj!NBNl*u*4!Lagw2>G$fzQ`Dm0#hovHb>{89?|05KAM;e1
zR4FFZY533NX#c*JS%QzN&fBE@;OxI4@wM>FvkknDES>-K|I+;^+&kYlaK3kvvfbpC
zwbAO5?LTvBV{0CZA9;RbdCOA)*M!{(|C(!ey*FJj|LTO4XZ!!$nb7qy?8V*m%i9$e
zG}qo|?bEE*+cjs;`9JoDr*y47x_kTAjm7>CPF0Jm@%qUnJZDdgT$*<N*Q@v&dlO%L
zE4^rP^xy2e@{K!Q3B=n^U#`>Fa(n*gJdfxda_)~`7CTOydoupK`GbrY=W~^})@jT4
z7(dFWQGR!@w!J;ss@HPX@fK~H;)^TSoS3rs=b0Tp{F#}{WMmFs+>>m1U$Xy^?V&T4
zv;Ld<{rX%Nx&F6B->VG|<gQ2O^BHY=vO>;VZ-<BNGpF^cms5}aE%*|1E&FVk&wNw!
zm)#cYc~h_XJg>-$fAM?O?B~af_X_W5|NQ2knPoE5<=n%px5}lDtKTyCYj$Vp!$0+Z
zc3hlxHSx5isrs4O@>;21J$4?^X8few{U#!|Y|gV8m)q2h-$d4ayL0KS?Jve4_ORv5
z)Bitwy1#z;^AoR1pS;=oZRbq8l9W>aCuM#yfwFP-6P2rze|*||vHs${2cH)fK2<Dy
zT4YfWHoGQlHDlxQJxc$JmKc^U2|S)@)_US>{+VMJKEBerCz6nMIV0=x3dY&}^2r*B
zC*K&qKWn$Rv2MK-kLaF_Moi8h%pFp`#PBG_3ui>Vsc5)qe%&zY!L;3?ZEVNRdmqRU
z{rmArx0%7+w@nKh7tdavxZ)vil2pdd9fHosw+jS!KbIF~%sSy~dia7v_yZrFGuK0&
zu35Q@{ib|q(t{s+C#vn8`29dvgtQ9(l{d00UbgxES|?Gic>BoH`D%K14ca5Lf4up}
zu$X(&p*P>!ZvN$Xdhqt?rtSY(d{@>qo;6T?`Qyow$8!s&MhHt-%)3x-bCHp)W`}R@
zgn$~3#dGJbZ*R5!vqQEn%fh}yA^$}K*Sx%qe{;Lv#zxG1x=-u$UcN_cm$&mT+wO42
zNSH@e=S8&b{`^wmE4n3z0uHEpR!vmd%jk20(ejT`X<yl^IaLvVG8x@;kAzqyuW;Di
z=dQcsd&{n`E!PhAJnDOSRMs@$Li?xR6NLWg$$#5hvxDtU%;D!d+O%)l7+n9vICafD
zDG3YRxAwZBhh87aa=j-|xx((#gucmNx}PeAOY0pC==dWwzphG_$AtZ>IlE@#`)Bty
zRCU;u{`(yKd}_dv{_RTzxtMLanQUJ_kgePMYj)xU`SbUz6y9FRXXUS7I(vW6hx@E=
zqpO<pU#?7GH8jn*Ud6xeYgnVb;03<c_jPRxn^<>t&fD4f_Q5*4hJ{Q@{&)Edjr$T;
zBzWEu>EWArxx(t)eqY5xE5B>jp~sCo{=T=F_A&hL&W}d3MWd(uo1R;=e){~1ja%jR
z2|wLx!a47`yG!2V$XP|dj~Gt$?)&i1X-28_p_tGaok9C2KX2o^-*El&K0oJa%P-zA
z@BdlCe#I&6(d5l5LyflV*|N^|*A%BO>-pm?uUqaGTQc=a-G^cuIp0fhLC4eX30l-l
zdSIEfVy)QE8#_;*-aY-Ez)vNic(%o_1s@sy?Ra)R;SbNEf1f?vzC2&tal(FgZt>nO
zt!Y!I-~GJ1r?2`gSH=F#Jg!?spRJK{dEvMq>0#93=nUSA)v`0Ee1DT!v75`#R-=59
z&(mkIz3-|6_7y%C557F@j-%z1@4=S0tV&iZ6gJBE-mkoUSoO8qEyrJr9r!)=)hoW|
znSW-EyVjKx6&jC^{q>f)^hev}-NQ|95>mq?Pwn5Jbi+D8^Hp))$9tEgLz*Y4Ek0oL
zHgw9dFPkbi)+{~IKj*yg>!p8Bxn1|%%i1IFcxVsX$-fdRXS(nCi~g2&{8b<HX8*K5
zwgq8N*34J>f6xAh`QLbNmv!gAwH{?>zU04jgZ_i)VhtTNZ`Kg|dBsNmzc(?xsPSX$
zRd4q@mU{n|FZbWA)9#*^*lIs>L+RhOg3SxLEUNl`+0K@d*~g`k_)lN4@ulcD?aC{4
z8~;jf&A+K%Tkp0%etp)Lzj_~k)&IX!QCzy^j(gUJa~gGT`@j6~_}T3G;kS+Zli-v8
zvu@bfnXKvxR^Ycg`)dAzt4+_Bz6d;ZMtjy|+X-eD4W7T<aQlVwqxHfTJ5G7J9EqI#
zS>eT>)yiM%^H0|YD*h^d>shDrq+G4)UFV%l!~d@0*80vWu_e1tMAj+FDLq_zb;Y%^
zv{RRFRZTJP;{N%2&TMaGx$T|*4%%O=im(q@qq_G0x-XG?ja1GkW-~qASa$xGXvTEY
zz4~9=Kb$XmP|3af{`*j$Um10|fx7bpzt4-DP#1DQJ!p}*PGr6Fins+|ryr;jKNY!m
zL;E#$pY;{@+dp!#->PqvUs82*kC(%Y<KbuY&v-vrQ#X;js=c#;ZDR2LK6}+`r{8Hm
zP+Mn}nzng{|Bd;H)AD6kE*CYdePq+JZ{x2(;o0B6KL6&+b~~fS<$HMBF1sZkb=GK<
m_tuuhr)boR&fR~YwX(M=-tD9Pr`JE~vz==HGfD)pyaND_9vQd*

literal 0
HcmV?d00001

diff --git a/dmp/motion_planning/__init__.py b/dmp/motion_planning/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/dmp/motion_planning/dmp/__init__.py b/dmp/motion_planning/dmp/__init__.py
new file mode 100644
index 0000000..40b5f42
--- /dev/null
+++ b/dmp/motion_planning/dmp/__init__.py
@@ -0,0 +1,2 @@
+from dmp import DMP
+from temporal_coupling import TCVelAccConstrained, NoTC
\ No newline at end of file
diff --git a/dmp/motion_planning/dmp/__init__.pyc b/dmp/motion_planning/dmp/__init__.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..e776f2856a3618cc12f701c89327b4429c25b01a
GIT binary patch
literal 314
zcmZSn%*!=>t9E=c0~9bZFfceUFfbHrF)%QsFfgPrGUPBY<T5fuF)}cM_)H8rObofq
z3{lJsxhxD(EDVe(%nZRAEDQ_`ng9R)|F6Nwz`#(#%)r3l;v1j=GOk3Jfq@~!IV?5D
zF*(^eKd-o?C^0iHHKhck$1gv`*-wKNrY9x0APD4=5<!qiYHmS(QDRPfa(-z+PG(+u
z5XkHxkeM1FMF^rejDdkcKO;XkRX;H&DKk$$IX@*cFJ0d`$TK*;yjZ`uC|N%zF-bo+
zza%q1FTNlrF)t4!4-!WgOUW(JkB`sH%PfhH*DI(j;b353u*uC&Da}c>1KD2;vR{A^
E0E|0I8~^|S

literal 0
HcmV?d00001

diff --git a/dmp/motion_planning/dmp/dmp.py b/dmp/motion_planning/dmp/dmp.py
new file mode 100644
index 0000000..958441d
--- /dev/null
+++ b/dmp/motion_planning/dmp/dmp.py
@@ -0,0 +1,166 @@
+#!/usr/bin/env python
+
+import numpy as np
+
+
+class DMP:
+    def __init__(self, k=100, d=20, a_s=1, n_bfs=100):
+        # parameters
+        self.k = k
+        self.d = d
+        self.a_s = a_s
+        self.n_bfs = n_bfs
+
+        # for obstacle avoidance
+        self.g_obs = 1000.
+        self.b_obs = 20. / np.pi
+        self.a_obs = 0.2
+
+        # trajectory parameters
+        self.n = 0
+        self.y0 = None
+        self.tau0 = None
+        self.g = None
+        self.tau = None
+
+        # initialize basis functions for LWR
+        self.w = None
+        self.centers = None
+        self.widths = None
+
+        # state
+        self.x = None
+        self.theta = None
+        self.pos = None
+        self.vel = None
+        self.acc = None
+
+        # desired path
+        self.path = None
+
+    def reset(self):
+        self.x = np.vstack((np.zeros((self.n, 1)), self.y0, 1.))
+        self.tau = self.tau0
+        self.theta = 0
+        self.pos = self.y0
+        self.vel = 0 * self.y0
+        self.acc = 0 * self.y0
+
+    def z(self, x=None):
+        if x is None:
+            x = self.x
+        return x[0:self.n]
+
+    def y(self, x=None):
+        if x is None:
+            x = self.x
+        return x[self.n:2 * self.n]
+
+    def s(self, x=None):
+        if x is None:
+            x = self.x
+        return x[2 * self.n]
+
+    def set_goal(self, g):
+        self.g = g
+
+    def set_tau(self, tau):
+        self.tau = tau
+
+    def psi(self, s, i=None):
+        if i is not None and len(s) == 1:
+            return np.exp(-1 / (2 * self.widths[i] ** 2) * (s - self.centers[i]) ** 2)
+        if i is None:
+            return np.exp(-1 / (2 * self.widths ** 2) * (s - self.centers) ** 2)
+
+    def h(self, x=None):
+        if x is None:
+            x = self.x
+        psi = self.psi(self.s(x)).reshape((self.n_bfs, 1))
+        v = (self.w.dot(psi)) / np.maximum(np.sum(psi), 1e-8) * (self.g - self.y0) * self.s(x)
+        h = self.k * (self.g - self.y(x)) - self.d * self.z(x) + v
+        return h
+
+    def f(self, x=None):
+        if x is None:
+            x = self.x
+        return np.vstack((self.h(x), self.z(x), -self.a_s * self.s(x)))
+
+    def obstacle_avoidance(self):
+        p = np.zeros(self.pos.shape)
+
+        for obstacle in self.obstacles:
+            # calculate vector to object relative to body
+            o = np.squeeze(obstacle)
+            x = np.squeeze(self.pos)
+            v = np.squeeze(self.vel)
+            # if we're moving
+            if np.linalg.norm(self.vel) > 1e-8 and np.linalg.norm(o - x) < self.a_obs:
+                # print("Dist: " + str(np.linalg.norm(o - x)) + "at position: " + str(x))
+                phi = np.arccos( np.dot(o - x, v) / (np.linalg.norm(o - x) * np.linalg.norm(v)) )
+                dphi = self.g_obs * phi * np.exp(-self.b_obs * abs(phi))
+
+                r = np.cross(o - x, v)
+                r = r / np.linalg.norm(r)
+                R = np.array([[0,-r[2],r[1]], [r[2],0,r[0]], [-r[1],r[0],0]]) + np.outer(r,r)
+                pval = np.nan_to_num(np.dot(R, v) * dphi)
+
+                # check to see if the distance to the obstacle is further than
+                # the distance to the target, if it is, ignore the obstacle
+                if np.linalg.norm(o - x) > np.linalg.norm(self.g - self.pos):
+                    pval = p * 0.
+
+                p += pval.reshape(self.pos.shape)
+        return p
+
+    def step(self, dt):
+        # Update state
+        self.x = self.x + self.f() / self.tau * dt
+        self.theta = self.theta + 1 / self.tau * dt
+
+        # Extract trajectory state
+        vel_prev = self.vel
+        self.pos = self.y()
+        self.vel = self.z() / self.tau
+        self.acc = (self.vel - vel_prev) / dt
+
+    def fit(self, y_demo, t_demo):
+        # Set target trajectory parameters
+        t_demo = t_demo.reshape(1, len(t_demo))
+        self.n = y_demo.shape[0]
+        self.path = y_demo
+        self.y0 = y_demo[:, 0].reshape((self.n, 1))
+        self.g = y_demo[:, -1].reshape((self.n, 1))
+        self.tau0 = t_demo[0, -1]
+
+        # Set basis functions
+        t_centers = np.linspace(0, self.tau0, self.n_bfs, endpoint=True)
+        self.centers = np.exp(-self.a_s / self.tau0 * t_centers)
+        widths = np.abs((np.diff(self.centers)))
+        self.widths = np.concatenate((widths, [widths[-1]]))
+
+        # Calculate derivatives
+        yd_demo = (y_demo[:, 1:] - y_demo[:, :-1]) / (t_demo[0, 1:] - t_demo[0, :-1])
+        yd_demo = np.concatenate((yd_demo, np.zeros((self.n, 1))), axis=1)
+        ydd_demo = (yd_demo[:, 1:] - yd_demo[:, :-1]) / (t_demo[0, 1:] - t_demo[0, :-1])
+        ydd_demo = np.concatenate((ydd_demo, np.zeros((self.n, 1))), axis=1)
+
+        # Compute weights
+        s_seq = np.exp(-self.a_s / self.tau0 * t_demo)
+        self.w = np.zeros((self.n, self.n_bfs))
+        for i in range(self.n):
+            if abs(self.g[i] - self.y0[i]) < 1e-5:
+                continue
+            f_gain = s_seq * (self.g[i] - self.y0[i])
+            f_target = self.tau0 ** 2 * ydd_demo[i, :] - self.k * (
+                        self.g[i] - y_demo[i, :]) + self.d * self.tau0 * yd_demo[i, :]
+            for j in range(self.n_bfs):
+                psi_j = self.psi(s_seq, j)
+                num = f_gain.dot((psi_j * f_target).T)
+                den = f_gain.dot((psi_j * f_gain).T)
+                if abs(den) < 1e-6:
+                    continue
+                self.w[i, j] = num / den
+
+        # Reset state
+        self.reset()
diff --git a/dmp/motion_planning/dmp/dmp.pyc b/dmp/motion_planning/dmp/dmp.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..1bedeaf35b653fa33fa47689814842914482a17d
GIT binary patch
literal 6785
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
TI1SlA!qyHHjm4lu&BF`;N@MEc

literal 0
HcmV?d00001

diff --git a/dmp/motion_planning/dmp/temporal_coupling.py b/dmp/motion_planning/dmp/temporal_coupling.py
new file mode 100644
index 0000000..5d9107a
--- /dev/null
+++ b/dmp/motion_planning/dmp/temporal_coupling.py
@@ -0,0 +1,80 @@
+#!/usr/bin/env python
+
+import numpy as np
+
+
+class NoTC:
+    def update(self, dmp, dt):
+        return 0
+
+
+class TCVelAccConstrained:
+
+    def __init__(self, gamma_nominal, gamma_a, v_max, a_max, eps=0.001):
+        self.gamma_nominal = gamma_nominal
+        self.gamma_a = gamma_a
+        self.eps = eps
+        self.v_max = v_max.reshape((len(v_max), 1))
+        self.a_max = a_max.reshape((len(a_max), 1))
+
+    def generate_matrices(self, dmp, dt):
+        A = np.vstack((-dmp.z(), dmp.z()))
+        B = np.vstack((-self.a_max, -self.a_max))
+        C = np.vstack((dmp.h(), -dmp.h()))
+        D = np.vstack((-self.v_max, -self.v_max))
+        x_next = dmp.x + dmp.f(dmp.x) / dmp.tau * dt
+        A_next = np.vstack((-dmp.z(x_next), dmp.z(x_next)))
+        C_next = np.vstack((dmp.h(x_next), -dmp.h(x_next)))
+        return A, B, C, D, A_next, C_next
+
+    def update(self, dmp, dt):
+
+        A, B, C, D, A_next, C_next = self.generate_matrices(dmp, dt)
+
+        # Acceleration bounds
+        i = np.squeeze(A < 0)
+        if i.any():
+            taud_min_a = np.max(- (B[i] * dmp.tau ** 2 + C[i]) / A[i])
+        else:
+            taud_min_a = -np.inf
+        i = np.squeeze(A > 0)
+        if i.any():
+            taud_max_a = np.min(- (B[i] * dmp.tau ** 2 + C[i]) / A[i])
+        else:
+            taud_max_a = np.inf
+        # Velocity bounds
+        i = range(len(A_next))
+        tau_min_v = np.max(-A_next[i] / D[i])
+        taud_min_v = (tau_min_v - dmp.tau) / dt
+        # Feasibility bounds
+        ii = np.arange(len(A_next))[np.squeeze(A_next < 0)]
+        jj = np.arange(len(A_next))[np.squeeze(A_next > 0)]
+        tau_min_f = -np.inf
+        for i in ii:
+            for j in jj:
+                num = C_next[i] * abs(A_next[j]) + C_next[j] * abs(A_next[i])
+                if num > 0:
+                    den = abs(B[i] * A_next[j]) + abs(B[j] * A_next[i])
+                    tmp = np.sqrt(num / den)
+                    if tmp > tau_min_f:
+                        tau_min_f = tmp
+        taud_min_f = (tau_min_f - dmp.tau) / dt
+        # Nominal bound
+        taud_min_nominal = (dmp.tau0 - dmp.tau) / dt
+
+        taud_min = np.max((taud_min_a, taud_min_v, taud_min_f, taud_min_nominal))
+
+        # Base update law
+        ydd_bar = dmp.h() / (dmp.tau**2 * self.a_max)
+        if self.gamma_a > 0:
+            pot_a = self.gamma_a * np.sum(ydd_bar ** 2 / np.maximum(1 - ydd_bar ** 2, self.gamma_a * self.eps * np.ones((len(ydd_bar), 1))))
+        else:
+            pot_a = 0
+        #pot_a = self.gamma_a * np.amax(ydd_bar ** 2 / np.maximum(1 - ydd_bar ** 2, self.gamma_a * self.eps * np.ones((len(ydd_bar), 1))))
+        taud = self.gamma_nominal * (dmp.tau0 - dmp.tau) + dmp.tau * pot_a
+
+        # Saturate
+        taud = np.min((taud, taud_max_a))
+        taud = np.max((taud, taud_min))
+
+        return taud
diff --git a/dmp/motion_planning/dmp/temporal_coupling.pyc b/dmp/motion_planning/dmp/temporal_coupling.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..ad105c2dfe090b880329d78c3dd0cb0fe173a9ed
GIT binary patch
literal 3407
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

literal 0
HcmV?d00001

diff --git a/dmp/motion_planning/online_traj_scaling/__init__.py b/dmp/motion_planning/online_traj_scaling/__init__.py
new file mode 100644
index 0000000..1d15623
--- /dev/null
+++ b/dmp/motion_planning/online_traj_scaling/__init__.py
@@ -0,0 +1,2 @@
+from gmr_oa import GMRwOA
+from trajectory_generator import TrajectoryGenerator
\ No newline at end of file
diff --git a/dmp/motion_planning/online_traj_scaling/__init__.pyc b/dmp/motion_planning/online_traj_scaling/__init__.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..12e3377806349a16333dbb0e3992de92b9d20efc
GIT binary patch
literal 315
zcmZSn%*$nCbSXZW0ScHH7#JKF7#NCG7#J8*7#LC*8FCmHav2$-7#SErd?tn*CWc&Q
zhA3tR#uR3TU=0=q28PW4|NsBjU}RumC}Cq@U~u;hD))DU@P!!|7($8?vr>~w@{20n
zQ}a@b5=-)n{J{Fas?&3e;`0-OKn^Go0T}^T9iI+U9t1L51Ed5&6elq-Fz9FG=cei>
z<|Jk2=_lu>Wag#oI|q3N$CnrD7Z)Y#=jNAW=I6y1<Rs?hf#k4><>%#O=B37$6eVWG
q7bhp?fYimuXXa&=#K-FuRF-fsFfiEU=BJeAq}qX;Q49(r0Y(50Mo>`z

literal 0
HcmV?d00001

diff --git a/dmp/motion_planning/online_traj_scaling/__pycache__/gmr_oa.cpython-36.pyc b/dmp/motion_planning/online_traj_scaling/__pycache__/gmr_oa.cpython-36.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..1833879cf8567e520fb4534cbd3be33e2a81c347
GIT binary patch
literal 11530
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

literal 0
HcmV?d00001

diff --git a/dmp/motion_planning/online_traj_scaling/example.yaml b/dmp/motion_planning/online_traj_scaling/example.yaml
new file mode 100644
index 0000000..94f5fb3
--- /dev/null
+++ b/dmp/motion_planning/online_traj_scaling/example.yaml
@@ -0,0 +1,38 @@
+update_rate: 125
+x0: [-29.1, 114.9]
+s_end: 3.5
+priors: [0.2599, 0.1352, 0.1344, 0.1377, 0.0550, 0.1664, 0.1113]
+mu: [[-112.6856, 54.1569, -88.7499, -154.9200], [74.9928, -98.9324, 122.6443, 182.4869],
+    [22.6435, 1.4977, -102.7541, 2.7533], [-22.5173, -123.9775,  299.0837,  -48.8174],
+    [-64.5564, 98.1626, -160.4187, -170.3178], [78.6112, -17.0895, -101.3953, 115.8752],
+    [-123.0283, -63.0123, 174.2271, -279.1635]]
+sigma: [[[0.6009,  0.0300, -0.0491,  1.0150],
+       [0.0300,  1.9033, -3.1190,  1.1773],
+       [-0.0491, -3.1190,  5.9745, -2.1668],
+       [1.0150,  1.1773, -2.1668,  3.1809]],
+       [[0.6290,  0.1268, -1.2774,  1.5296],
+        [0.1268,  0.9079, -2.3844,  0.3074],
+        [-1.2774, -2.3844,  8.2566, -3.0188],
+        [1.5296,  0.3074, -3.0188,  3.7767]],
+        [[0.2605, -0.0328, -0.6769, 0.3306],
+         [-0.0328, 0.0282, -0.1585, -0.1858],
+         [-0.6769, -0.1585, 7.9287, 1.6320],
+         [0.3306, -0.1858, 1.6320, 1.7752]],
+        [[1.7232, -0.7104, 0.3933, 3.7694],
+         [-0.7104, 0.7734, -1.2591, -1.5555],
+         [0.3933, -1.2591, 3.6391, 0.7968],
+         [3.7694, -1.5555, 0.7968, 8.5589]],
+        [[1.094, -0.079, -0.568, 1.331],
+           [-0.079, 2.376, -4.876, -2.423],
+           [-0.568, -4.876, 15.627, 9.517],
+           [1.331, -2.423, 9.517, 44.624]],
+        [[0.4217, -0.3304, 0.2178, 1.2149],
+         [-0.3304, 0.4037, -0.6332, -1.3119],
+         [0.2178, -0.6332, 2.2057, 2.3334],
+         [1.2149, -1.3119, 2.3334, 4.9441]],
+        [[0.5734, -0.6797, 1.3006, 1.320],
+         [-0.6797, 1.4485, -2.9368, -1.5774],
+         [1.3006, -2.9368, 6.0104, 2.9347],
+         [1.3200, -1.5774, 2.9347, 4.7359]]]
+o_c: [-100, -70]
+o_r: 30
\ No newline at end of file
diff --git a/dmp/motion_planning/online_traj_scaling/gmr_oa.py b/dmp/motion_planning/online_traj_scaling/gmr_oa.py
new file mode 100644
index 0000000..cc49b5a
--- /dev/null
+++ b/dmp/motion_planning/online_traj_scaling/gmr_oa.py
@@ -0,0 +1,363 @@
+#!/usr/bin/env python
+
+import numpy as np
+
+
+class GMRwOA:
+    def __init__(self, params):
+        self.x0 = np.array(params['x0'])
+        self.s_end = params['s_end']
+        self.n = self.x0.size
+        self.o_c = np.array(params['o_c'])
+        self.o_r = params['o_r']
+        self.priors = np.array(params['priors'])
+        self.mu = np.array(params['mu'])
+        self.sigma = np.array(params['sigma'])
+        self.nKernels = self.priors.size
+        self.A = np.zeros((self.nKernels, self.n, self.n))
+        self.b = np.zeros((self.nKernels, self.n))
+        for w in range(self.nKernels):
+            self.A[w, :, :] = self.sigma[w, self.n:, :self.n].dot(np.linalg.inv(
+                self.sigma[w, :self.n, :self.n]))
+            self.b[w, :] = self.mu[w, self.n:] - self.A[w, :, :].dot(self.mu[w, :self.n])
+
+    def f(self, x):
+        weights = self.weights(x)
+        f = np.zeros(self.n)
+        gmr_f = sum(weights[w] * (self.A[w, :, :].dot(x) + self.b[w, :]) for w in range(self.nKernels))
+        return self.modulation_matrix(x).dot(gmr_f)
+
+    def g(self, x):
+        return x
+
+    def gx(self, x):
+        return np.eye(self.n)
+
+    def dx_gxf(self, x):
+        x1 = x[0]
+        x2 = x[1]
+        t2 = x2 + 7.0e1
+        t3 = x1 + 1.0e2
+        t4 = t2 ** 2
+        t5 = t3 ** 2
+        t6 = x2 - 9.816261394778176e1
+        t7 = x1 * 1.530596366426007e-5
+        t8 = x2 * 2.109513339111852e-4
+        t9 = t7 + t8 - 1.971943673320373e-2
+        t10 = x1 + 6.455638083061622e1
+        t11 = x1 * 4.582396934010209e-4
+        t12 = x2 * 1.530596366426007e-5
+        t13 = t11 + t12 + 2.807982275662759e-2
+        t79 = t6 * t9
+        t80 = t10 * t13
+        t14 = -t79 - t80
+        t15 = np.exp(t14)
+        t16 = x2 - 5.415693532998247e1
+        t17 = x1 * 1.312704257151209e-5
+        t82 = x2 * 2.629035561972274e-4
+        t18 = t17 - t82 + 1.571727929602906e-2
+        t19 = t16 * t18
+        t20 = x1 + 1.126855799373714e2
+        t21 = x1 * 8.327024557111857e-4
+        t83 = x2 * 1.312704257151209e-5
+        t22 = t21 - t83 + 9.454447953270757e-2
+        t84 = t20 * t22
+        t23 = t19 - t84
+        t24 = np.exp(t23)
+        t25 = x1 + 2.251733280467149e1
+        t26 = x1 * 4.670158568124115e-4
+        t27 = x2 * 4.289836618923725e-4
+        t28 = t26 + t27 + 6.370025953155209e-2
+        t29 = x2 + 1.239774676360322e2
+        t30 = x1 * 4.289836618923725e-4
+        t31 = x2 * 1.040569631086783e-3
+        t32 = t30 + t31 + 1.386667556436968e-1
+        t88 = t25 * t28
+        t89 = t29 * t32
+        t33 = -t88 - t89
+        t34 = np.exp(t33)
+        t35 = t34 * 2.408872289627689e-5
+        t36 = x1 - 7.499276410192803e1
+        t37 = x2 * 1.142541742241694e-4
+        t90 = x1 * 8.178935231312593e-4
+        t38 = t37 - t90 + 7.263953274615121e-2
+        t39 = t36 * t38
+        t40 = x2 + 9.893237408811206e1
+        t41 = x2 * 5.666798935371871e-4
+        t91 = x1 * 1.142541742241694e-4
+        t42 = t41 - t91 + 6.463122355088623e-2
+        t92 = t40 * t42
+        t43 = t39 - t92
+        t44 = np.exp(t43)
+        t45 = t44 * 2.888145048134885e-5
+        t46 = x1 - 2.264354107101735e1
+        t47 = x1 * 2.247790700044474e-3
+        t48 = x2 * 2.608028701302809e-3
+        t49 = t47 + t48 - 5.480387720544926e-2
+        t50 = x2 - 1.497658429905395
+        t51 = x1 * 2.608028701302809e-3
+        t52 = x2 * 2.072560326248954e-2
+        t53 = t51 + t52 - 9.00948794532844e-2
+        t93 = t46 * t49
+        t94 = t50 * t53
+        t54 = -t93 - t94
+        t55 = np.exp(t54)
+        t56 = t55 * 2.698593356722665e-4
+        t57 = x2 + 6.301228183938932e1
+        t58 = x1 * 9.222652594971037e-4
+        t59 = x2 * 7.779669674794524e-4
+        t60 = t58 + t59 + 1.624861712161579e-1
+        t61 = x1 + 1.230282678775932e2
+        t62 = x1 * 1.965364578835002e-3
+        t63 = x2 * 9.222652594971037e-4
+        t64 = t62 + t63 + 2.999094383441548e-1
+        t95 = t57 * t60
+        t96 = t61 * t64
+        t65 = -t95 - t96
+        t66 = np.exp(t65)
+        t67 = t66 * 2.919147494282987e-5
+        t68 = x1 - 7.861117292542697e1
+        t69 = x1 * 3.302595736312175e-3
+        t70 = x2 * 2.702662948139369e-3
+        t71 = t69 + t70 - 2.134336703875113e-1
+        t72 = x2 + 1.708953540592262e1
+        t73 = x1 * 2.702662948139369e-3
+        t74 = x2 * 3.450285534628542e-3
+        t75 = t73 + t74 - 1.534957275707511e-1
+        t97 = t68 * t71
+        t98 = t72 * t75
+        t76 = -t97 - t98
+        t77 = np.exp(t76)
+        t78 = t77 * 1.071251714048381e-4
+        t81 = t15 * 5.43860953025742e-6
+        t85 = t24 * 3.869452814178776e-5
+        t86 = t35 + t45 + t56 + t67 + t78 + t81 + t85
+        t87 = 1.0 / t86
+        t99 = x1 * 6.605191472624351e-3
+        t100 = x2 * 5.405325896278738e-3
+        t101 = t99 + t100 - 4.268673407750226e-1
+        t102 = x1 * 3.869851041803628
+        t103 = x2 * 1.010037993543203e1
+        t104 = t102 + t103
+        t105 = x1 * 4.495581400088948e-3
+        t106 = x2 * 5.216057402605618e-3
+        t107 = t105 + t106 - 1.096077544108985e-1
+        t108 = x2 * 2.285083484483388e-4
+        t117 = x1 * 1.635787046262519e-3
+        t109 = t108 - t117 + 1.452790654923024e-1
+        t110 = x1 * 1.665404911422371e-3
+        t115 = x2 * 2.625408514302419e-5
+        t111 = t110 - t115 + 1.890889590654151e-1
+        t112 = x1 * 1.983731639577469
+        t113 = x2 * 3.191903357349043
+        t114 = t112 + t113 - 1.4210854715202e-14
+        t116 = t24 * t111 * 3.869452814178776e-5
+        t118 = t77 * t101 * 1.071251714048381e-4
+        t119 = x1 * 9.164793868020419e-4
+        t120 = x2 * 3.061192732852015e-5
+        t121 = t119 + t120 + 5.615964551325517e-2
+        t122 = t15 * t121 * 5.43860953025742e-6
+        t123 = x1 * 9.34031713624823e-4
+        t124 = x2 * 8.57967323784745e-4
+        t125 = t123 + t124 + 1.274005190631042e-1
+        t126 = t34 * t125 * 2.408872289627689e-5
+        t127 = t55 * t107 * 2.698593356722665e-4
+        t128 = x1 * 3.930729157670005e-3
+        t129 = x2 * 1.844530518994207e-3
+        t130 = t128 + t129 + 5.998188766883095e-1
+        t131 = t66 * t130 * 2.919147494282987e-5
+        t136 = t44 * t109 * 2.888145048134885e-5
+        t132 = t116 + t118 + t122 + t126 + t127 + t131 - t136
+        t133 = 1.0 / t86 ** 2
+        t134 = x1 * 3.231732335122654e-5
+        t154 = x2 * 1.638686742732473
+        t135 = t134 - t154
+        t137 = x1 * 1.54461351435013
+        t138 = x2 * 2.410526413045497
+        t139 = t137 + t138
+        t140 = x1 * 7.128956258032981e-1
+        t141 = x2 * 2.282924141766298
+        t142 = t140 + t141
+        t143 = x1 * 3.04539679230562e-1
+        t144 = x2 * 2.17037228002446
+        t145 = t143 + t144 - 2.842170943040401e-14
+        t146 = x1 * 6.694733262807462e-1
+        t147 = x2 * 2.074491355757708
+        t148 = t146 + t147
+        t149 = x1 * 2.0
+        t150 = t149 + 2.0e2
+        t151 = t4 + t5
+        t152 = 1.0 / t151 ** 2
+        t183 = t3 * t150
+        t153 = t4 + t5 - t183
+        t155 = x1 * 1.145820509435398
+        t157 = x2 * 9.81512008356454e-1
+        t156 = t155 - t157
+        t158 = x1 * 5.169583816001215e-1
+        t166 = x2 * 5.977666165428746
+        t159 = t158 - t166 + 4.440892098500626e-16
+        t160 = x1 * 1.659508447689607
+        t161 = x2 * 5.924016783798807e-1
+        t162 = t160 + t161
+        t163 = x1 * 2.279092938141525
+        t165 = x2 * 1.950918964167032e-2
+        t164 = t163 - t165
+        t167 = x2 * 2.48561120484202
+        t175 = x1 * 9.336740956565702e-1
+        t168 = t167 - t175 + 2.842170943040401e-14
+        t169 = x1 * 2.43188361814004
+        t174 = x2 * 1.144763805707237e-3
+        t170 = t169 - t174
+        t171 = x2 * 3.289247523618103e-3
+        t173 = x1 * 2.186101706496526
+        t172 = t171 - t173 + 7.105427357601002e-14
+        t176 = 1.0 / t151 ** 3
+        t177 = t15 * t87 * t156 * 5.43860953025742e-6
+        t178 = t55 * t87 * t159 * 2.698593356722665e-4
+        t179 = t24 * t87 * t162 * 3.869452814178776e-5
+        t180 = t66 * t87 * t164 * 2.919147494282987e-5
+        t181 = t44 * t87 * t170 * 2.888145048134885e-5
+        t224 = t77 * t87 * t168 * 1.071251714048381e-4
+        t225 = t34 * t87 * t172 * 2.408872289627689e-5
+        t182 = t177 + t178 + t179 + t180 + t181 - t224 - t225
+        t184 = t152 * t153 * 9.0e2
+        t185 = t184 + 1.0
+        t186 = x1 * 1.844530518994207e-3
+        t187 = x2 * 1.555933934958905e-3
+        t188 = t186 + t187 + 3.249723424323159e-1
+        t189 = x1 * 5.216057402605618e-3
+        t190 = x2 * 4.145120652497908e-2
+        t191 = t189 + t190 - 1.801897589065688e-1
+        t192 = t66 * t188 * 2.919147494282987e-5
+        t193 = x1 * 5.405325896278738e-3
+        t194 = x2 * 6.900571069257084e-3
+        t195 = t193 + t194 - 3.069914551415021e-1
+        t196 = t77 * t195 * 1.071251714048381e-4
+        t197 = x1 * 2.625408514302419e-5
+        t212 = x2 * 5.258071123944548e-4
+        t198 = t197 - t212 + 3.143455859205812e-2
+        t199 = x2 * 1.133359787074374e-3
+        t214 = x1 * 2.285083484483388e-4
+        t200 = t199 - t214 + 1.292624471017725e-1
+        t201 = t44 * t200 * 2.888145048134885e-5
+        t202 = x1 * 8.57967323784745e-4
+        t203 = x2 * 2.081139262173565e-3
+        t204 = t202 + t203 + 2.773335112873937e-1
+        t205 = t34 * t204 * 2.408872289627689e-5
+        t206 = t55 * t191 * 2.698593356722665e-4
+        t207 = x1 * 3.061192732852015e-5
+        t208 = x2 * 4.219026678223704e-4
+        t209 = t207 + t208 - 3.943887346640746e-2
+        t210 = t15 * t209 * 5.43860953025742e-6
+        t213 = t24 * t198 * 3.869452814178776e-5
+        t211 = t192 + t196 + t201 + t205 + t206 + t210 - t213
+        t215 = x2 * 2.0
+        t216 = t215 + 1.4e2
+        t217 = t55 * t87 * t104 * 2.698593356722665e-4
+        t218 = t77 * t87 * t114 * 1.071251714048381e-4
+        t219 = t44 * t87 * t139 * 2.888145048134885e-5
+        t220 = t34 * t87 * t142 * 2.408872289627689e-5
+        t221 = t66 * t87 * t145 * 2.919147494282987e-5
+        t222 = t15 * t87 * t148 * 5.43860953025742e-6
+        t244 = t24 * t87 * t135 * 3.869452814178776e-5
+        t223 = t217 + t218 + t219 + t220 + t221 + t222 - t244
+        t226 = t150 * t152 * 9.0e2
+        t260 = t2 * t216
+        t227 = t4 + t5 - t260
+        t228 = t15 * t87 * 6.231670342579768e-6
+        t229 = t24 * t87 * 6.421389633066001e-5
+        t230 = t34 * t87 * 5.266039823087284e-5
+        t231 = t44 * t87 * 7.023632629371505e-5
+        t232 = t55 * t87 * 1.395060454288188e-4
+        t233 = t66 * t87 * 6.653008439613883e-5
+        t234 = t77 * t87 * 1.000199975334673e-4
+        t235 = t15 * t132 * t133 * t156 * 5.43860953025742e-6
+        t236 = t55 * t132 * t133 * t159 * 2.698593356722665e-4
+        t237 = t24 * t132 * t133 * t162 * 3.869452814178776e-5
+        t238 = t66 * t132 * t133 * t164 * 2.919147494282987e-5
+        t239 = t44 * t87 * t109 * t170 * 2.888145048134885e-5
+        t240 = t34 * t87 * t125 * t172 * 2.408872289627689e-5
+        t241 = t44 * t132 * t133 * t170 * 2.888145048134885e-5
+        t242 = t77 * t87 * t101 * t168 * 1.071251714048381e-4
+        t243 = t228 + t229 + t230 + t231 + t232 + t233 + t234 + t235 + t236 + t237 + t238 + t239 + t240 + t241 + t242 - t15 * t87 * t121 * t156 * 5.43860953025742e-6 - t24 * t87 * t111 * t162 * 3.869452814178776e-5 - t55 * t87 * t107 * t159 * 2.698593356722665e-4 - t66 * t87 * t130 * t164 * 2.919147494282987e-5 - t34 * t132 * t133 * t172 * 2.408872289627689e-5 - t77 * t132 * t133 * t168 * 1.071251714048381e-4
+        t245 = t15 * t87 * 3.641004012563601e-6
+        t246 = t34 * t87 * 1.717274518394355e-5
+        t247 = t44 * t87 * 4.46106787275255e-5
+        t248 = t55 * t87 * 1.044315431291755e-3
+        t249 = t66 * t87 * 8.889962415356397e-6
+        t250 = t77 * t87 * 2.125075919109369e-4
+        t251 = t55 * t104 * t132 * t133 * 2.698593356722665e-4
+        t252 = t44 * t87 * t109 * t139 * 2.888145048134885e-5
+        t253 = t24 * t87 * t111 * t135 * 3.869452814178776e-5
+        t254 = t77 * t114 * t132 * t133 * 1.071251714048381e-4
+        t255 = t44 * t132 * t133 * t139 * 2.888145048134885e-5
+        t256 = t34 * t132 * t133 * t142 * 2.408872289627689e-5
+        t257 = t66 * t132 * t133 * t145 * 2.919147494282987e-5
+        t258 = t15 * t132 * t133 * t148 * 5.43860953025742e-6
+        t259 = t245 + t246 + t247 + t248 + t249 + t250 + t251 + t252 + t253 + t254 + t255 + t256 + t257 + t258 - t24 * t87 * 1.25050357788129e-9 - t55 * t87 * t104 * t107 * 2.698593356722665e-4 - t15 * t87 * t121 * t148 * 5.43860953025742e-6 - t77 * t87 * t101 * t114 * 1.071251714048381e-4 - t34 * t87 * t125 * t142 * 2.408872289627689e-5 - t24 * t132 * t133 * t135 * 3.869452814178776e-5 - t66 * t87 * t130 * t145 * 2.919147494282987e-5
+        t261 = t152 * t227 * 9.0e2
+        t262 = t261 + 1.0
+        t263 = t15 * t87 * 5.338060562709511e-6
+        t264 = t34 * t87 * 7.923377213370146e-8
+        t265 = t44 * t87 * 3.306243916737403e-8
+        t266 = t55 * t87 * 1.613129020273186e-3
+        t267 = t66 * t87 * 5.695020205797351e-7
+        t268 = t77 * t87 * 2.662715263644876e-4
+        t269 = t55 * t87 * t159 * t191 * 2.698593356722665e-4
+        t270 = t34 * t133 * t172 * t211 * 2.408872289627689e-5
+        t271 = t66 * t87 * t164 * t188 * 2.919147494282987e-5
+        t272 = t15 * t87 * t156 * t209 * 5.43860953025742e-6
+        t273 = t44 * t87 * t170 * t200 * 2.888145048134885e-5
+        t274 = t77 * t133 * t168 * t211 * 1.071251714048381e-4
+        t275 = t263 + t264 + t265 + t266 + t267 + t268 + t269 + t270 + t271 + t272 + t273 + t274 - t24 * t87 * 2.292270341531259e-5 - t24 * t87 * t162 * t198 * 3.869452814178776e-5 - t34 * t87 * t172 * t204 * 2.408872289627689e-5 - t15 * t133 * t156 * t211 * 5.43860953025742e-6 - t77 * t87 * t168 * t195 * 1.071251714048381e-4 - t24 * t133 * t162 * t211 * 3.869452814178776e-5 - t44 * t133 * t170 * t211 * 2.888145048134885e-5 - t55 * t133 * t159 * t211 * 2.698593356722665e-4 - t66 * t133 * t164 * t211 * 2.919147494282987e-5
+        t276 = t152 * t216 * 9.0e2
+        t277 = t15 * t87 * 1.128234845786051e-5
+        t278 = t24 * t87 * 6.340821028223617e-5
+        t279 = t34 * t87 * 5.49927270442291e-5
+        t280 = t44 * t87 * 6.9619499232357e-5
+        t281 = t55 * t87 * 2.725681819413176e-3
+        t282 = t66 * t87 * 6.335636802894656e-5
+        t283 = t77 * t87 * 3.419331942636945e-4
+        t284 = t77 * t114 * t133 * t211 * 1.071251714048381e-4
+        t285 = t44 * t133 * t139 * t211 * 2.888145048134885e-5
+        t286 = t34 * t133 * t142 * t211 * 2.408872289627689e-5
+        t287 = t66 * t133 * t145 * t211 * 2.919147494282987e-5
+        t288 = t15 * t133 * t148 * t211 * 5.43860953025742e-6
+        t289 = t55 * t104 * t133 * t211 * 2.698593356722665e-4
+        t290 = t277 + t278 + t279 + t280 + t281 + t282 + t283 + t284 + t285 + t286 + t287 + t288 + t289 - t55 * t87 * t104 * t191 * 2.698593356722665e-4 - t24 * t87 * t135 * t198 * 3.869452814178776e-5 - t15 * t87 * t148 * t209 * 5.43860953025742e-6 - t34 * t87 * t142 * t204 * 2.408872289627689e-5 - t44 * t87 * t139 * t200 * 2.888145048134885e-5 - t77 * t87 * t114 * t195 * 1.071251714048381e-4 - t66 * t87 * t145 * t188 * 2.919147494282987e-5 - t24 * t133 * t135 * t211 * 3.869452814178776e-5
+        return np.reshape([-t185 * t259 + t223 * (
+                t226 + t150 * t153 * t176 * 1.8e3) - t2 * t152 * t182 * 1.8e3 - t2 * t150 * t152 * t243 * 9.0e2 + t2 * t150 ** 2 * t176 * t182 * 1.8e3,
+                           t243 * t262 + t182 * (
+                                   t226 - t150 * t176 * t227 * 1.8e3) + t152 * t216 * t223 * 9.0e2 + t3 * t152 * t216 * t259 * 9.0e2 - t3 * t150 * t176 * t216 * t223 * 1.8e3,
+                           -t185 * t290 - t223 * (
+                                   t276 - t153 * t176 * t216 * 1.8e3) - t150 * t152 * t182 * 9.0e2 + t2 * t150 * t152 * t275 * 9.0e2 + t2 * t150 * t176 * t182 * t216 * 1.8e3,
+                           -t262 * t275 - t182 * (
+                                   t276 + t176 * t216 * t227 * 1.8e3) + t3 * t152 * t223 * 1.8e3 + t3 * t152 * t216 * t290 * 9.0e2 - t3 * t176 * t216 ** 2 * t223 * 1.8e3],
+                          [2, 2], 'F')
+
+    def weights(self, x):
+        num = np.zeros(self.nKernels)
+        for w in range(self.nKernels):
+            num[w] = self.priors[w] * self.mvn_pdf(x, self.mu[w, :self.n], self.sigma[w, :self.n, :self.n])
+        den = num.sum()
+        return num / den
+
+    @staticmethod
+    def mvn_pdf(x, mu, sigma):
+        n = x.size
+        return 1 / np.sqrt((2 * np.pi) ** n * np.linalg.det(sigma)) * np.exp(
+            -0.5 * (x - mu).transpose().dot(np.linalg.inv(sigma).dot(x - mu)))
+
+    def modulation_matrix(self, x):
+        xd = x - self.o_c
+        return np.eye(self.n) + (self.o_r / xd.transpose().dot(xd))**2 * (xd.transpose().dot(xd) * np.eye(self.n) -
+                                                                          2 * np.outer(xd, xd))
+
+    def gamma(self, x):
+        return sum((np.linalg.norm(x[i] - self.o_c[i]) / self.o_r) ** 2 for i in range(self.n))
+
+    def lambda_r(self, x):
+        return 1 - 1 / self.gamma(x)
+
+    def lambda_e(self, x):
+        return 1 + 1 / self.gamma(x)
diff --git a/dmp/motion_planning/online_traj_scaling/gmr_oa.pyc b/dmp/motion_planning/online_traj_scaling/gmr_oa.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..248b7e889920da02a0f108bf4358457600deb468
GIT binary patch
literal 14523
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

literal 0
HcmV?d00001

diff --git a/dmp/motion_planning/online_traj_scaling/trajectory_generator.py b/dmp/motion_planning/online_traj_scaling/trajectory_generator.py
new file mode 100755
index 0000000..899b8af
--- /dev/null
+++ b/dmp/motion_planning/online_traj_scaling/trajectory_generator.py
@@ -0,0 +1,93 @@
+#!/usr/bin/env python
+
+import matplotlib.pyplot as plt
+import yaml
+from gmr_oa import GMRwOA
+import numpy as np
+
+class TrajectoryGenerator:
+    def __init__(self, dyn_sys):
+        # parameters
+        self.dyn_sys = dyn_sys
+        # state
+        self.x = None
+        self.s = None
+        self.ds = None
+        self.sat_flag = None
+        # Output state
+        self.pos = None
+        self.vel = None
+        self.acc = None
+        # desired path
+        self.path = None
+
+        self.reset()
+
+    def reset(self):
+        self.x = self.dyn_sys.x0
+        self.s = 0
+        self.ds = 1
+        self.sat_flag = 0
+        self.pos = self.dyn_sys.g(self.x)
+        self.vel = self.dyn_sys.gx(self.x).dot(self.dyn_sys.f(self.x))
+        self.acc = self.dyn_sys.dx_gxf(self.x).dot(self.dyn_sys.f(self.x))
+
+    def step(self, dt):
+        # Derivative
+        dx = self.dyn_sys.f(self.x) * self.ds
+        dds, self.sat_flag = self.traj_scaling()
+
+        # Integrate
+        self.x += dx * dt
+        self.s += self.ds * dt
+        self.ds += dds * dt
+
+        # Update reference
+        self.pos = self.dyn_sys.g(self.x)
+        self.vel = self.dyn_sys.gx(self.x).dot(self.dyn_sys.f(self.x))
+        self.acc = self.dyn_sys.gx(self.x).dot(self.dyn_sys.f(self.x)) * dds + self.dyn_sys.dx_gxf(
+            self.x).dot(self.dyn_sys.f(self.x)) * self.ds ** 2
+
+    def roll_out(self, dt, T = None):
+        self.reset()
+        pos = np.array([self.pos])
+        vel = np.array([self.vel])
+        acc = np.array([self.acc])
+        t = np.array([0])
+        s = np.array([0])
+        # for k in range(1, round(T/dt)+1):
+        k = 0
+        while True:
+            k += 1
+            self.step(dt)
+            t = np.append(t, k*dt)
+            s = np.append(s, self.s)
+            pos = np.append(pos, np.array([self.pos]), axis=0)
+            vel = np.append(vel, np.array([self.vel]), axis=0)
+            acc = np.append(acc, np.array([self.acc]), axis=0)
+            if T and k*dt > T:
+                break
+            if not T and self.s > self.dyn_sys.s_end:
+                break
+        return t, s, pos, vel, acc
+
+    def traj_scaling(self):
+        dds = 0
+        sat_flag = 0
+
+        return dds, sat_flag
+
+if __name__ == "__main__":
+    with open("example.yaml", 'r') as stream:
+        try:
+            params = yaml.safe_load(stream)
+            params['sigma'] = [[[el * 1e3 for el in row] for row in col] for col in params['sigma']]
+            gmr = GMRwOA(params)
+            tg = TrajectoryGenerator(gmr)
+            t, s, pos, vel, acc = tg.roll_out(0.01)
+            plt.plot(0.0032*pos[:, 0], 0.0026*pos[:, 1] + 0.7)
+            # plt.plot(s, pos[:, 0])
+            # plt.plot(s, pos[:, 1])
+            plt.show()
+        except yaml.YAMLError as exc:
+            print(exc)
diff --git a/dmp/motion_planning/online_traj_scaling/trajectory_generator.pyc b/dmp/motion_planning/online_traj_scaling/trajectory_generator.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..c1df99f5686f4e652cb2f5d7683dfb0f5585c66d
GIT binary patch
literal 3744
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

literal 0
HcmV?d00001

diff --git a/dmp/msg/DMPState.msg b/dmp/msg/DMPState.msg
new file mode 100644
index 0000000..aec6613
--- /dev/null
+++ b/dmp/msg/DMPState.msg
@@ -0,0 +1,8 @@
+Header header
+float64[] position
+float64[] velocity
+float64[] acceleration
+float64 theta
+float64 s
+float64 tau
+
diff --git a/dmp/msg/TrajGenState.msg b/dmp/msg/TrajGenState.msg
new file mode 100644
index 0000000..936c4e9
--- /dev/null
+++ b/dmp/msg/TrajGenState.msg
@@ -0,0 +1,6 @@
+Header header
+float64[] position
+float64[] velocity
+float64[] acceleration
+float64 s
+float64 s_dot
diff --git a/dmp/todos.md b/dmp/todos.md
index ec74f5a..6ac3bb8 100644
--- a/dmp/todos.md
+++ b/dmp/todos.md
@@ -4,7 +4,7 @@ and it's matlab
 
 # calculating the dmp from the trajectory
 is in 
-TC_DMP_constrainedVelAcc/something/DMP.m
+TC_DMP_constrainedVelAcc/matlab/DMP.m
 
 # running the dmp node
 TC_DMP_constrainedVelAcc/catkin_ws/src/motion_planning/nodes/dmp_node
diff --git a/dmp/traj_scaling_node b/dmp/traj_scaling_node
new file mode 100755
index 0000000..e4e6aca
--- /dev/null
+++ b/dmp/traj_scaling_node
@@ -0,0 +1,113 @@
+#!/usr/bin/env python
+
+from motion_planning.online_traj_scaling import GMRwOA, TrajectoryGenerator
+import numpy as np
+import rospy
+from robot_ctrl.msg import CtrlTarget
+from std_msgs.msg import Float64, String
+from motion_planning.msg import TrajGenState
+
+
+class TrajGenNode:
+    def __init__(self):
+        self.active = False
+        self.rate = None
+        self.dt = None
+        self.traj_gen = None
+
+        # Load parameters from server
+        if not self.load_params():
+            rospy.logwarn("Trajectory Generator not initialized")
+
+        # Setup ros topics
+        self.target_pub = rospy.Publisher("robot_ctrl/command", CtrlTarget, queue_size=1)
+        self.state_pub = rospy.Publisher("motion_planning/state", TrajGenState, queue_size=1)
+        rospy.Subscriber("motion_planning/command", String, self.command_parser)
+
+        # Go into spin
+        self.spin()
+
+    def load_params(self):
+        parameters = ['x0', 's_end', 'priors', 'mu', 'sigma', 'o_c', 'o_r']
+        if not rospy.has_param('motion_planning/update_rate'):
+            rospy.logerr("Parameter " + rospy.get_namespace() + "motion_planning/update_rate not on parameter server.")
+            return False
+        update_rate = rospy.get_param('motion_planning/update_rate')
+        self.rate = rospy.Rate(update_rate)
+        params = {}
+        for i in range(len(parameters)):
+            if not rospy.has_param('motion_planning/' + parameters[i]):
+                rospy.logerr("Parameter " + rospy.get_namespace() + "motion_planning/" + parameters[i] + " not on parameter server.")
+                return False
+            params[parameters[i]] = rospy.get_param('motion_planning/' + parameters[i])
+        gmr = GMRwOA(params)
+        self.traj_gen = TrajectoryGenerator(gmr)
+        return True
+
+    def command_parser(self, msg):
+        if msg.data == 'start':
+            self.active = True
+        elif msg.data == 'stop':
+            self.active = False
+        elif msg.data == 'reset':
+            self.traj_gen.reset()
+            self.active = False
+            rospy.loginfo("Reset motion_planner.")
+        elif msg.data == 'step':
+            self.traj_gen.step(self.dt)
+        elif msg.data == 'load_params':
+            self.load_params()
+            rospy.loginfo("Reloaded motion_planner parameters.")
+        else:
+            rospy.loginfo("Invalid command string for motion planner.")
+
+    # spin -----------------------------------------------------
+    # -----------------------------------------------------------
+    def spin(self):
+        print_flag = True
+        while not rospy.is_shutdown():
+
+            if self.active:
+                # Step DMP
+                self.traj_gen.step(self.dt)
+                # Send target trajectory state command
+                pub_msg = CtrlTarget()
+                pub_msg.header.stamp = rospy.Time.now()
+                pub_msg.acceleration = self.traj_gen.acc
+                pub_msg.velocity = self.traj_gen.vel
+                pub_msg.position = self.traj_gen.pos
+                self.target_pub.publish(pub_msg)
+            else:
+                print_flag = True
+
+            # Publish DMP state command
+            pub_msg = TrajGenState()
+            pub_msg.header.stamp = rospy.Time.now()
+            pub_msg.acceleration = [0.0032*self.traj_gen.acc[0], 0, 0.0026*self.traj_gen.acc[1]]
+            pub_msg.velocity = [0.0032*self.traj_gen.vel[0], 0, 0.0026*self.traj_gen.vel[1]]
+            pub_msg.position = [0.0032*self.traj_gen.pos[0], 0, 0.0026*self.traj_gen.pos[1]+0.7]
+            pub_msg.s = self.traj_gen.s
+            pub_msg.s_dot = self.traj_gen.ds
+            self.state_pub.publish(pub_msg)
+
+            # Notify when DMP trajectory is finished
+            if print_flag and self.traj_gen.s > self.traj_gen.dyn_sys.s_end:
+                rospy.loginfo("Trajectory finished.")
+                print_flag = False
+
+            # Sleep
+            self.rate.sleep()
+
+
+# --------------------------------------------------------------------
+# Here is the main entry point
+if __name__ == '__main__':
+    try:
+        # Init the node:
+        rospy.init_node('TrajGenNode')
+
+        # Initializing and continue running the main class:
+        TrajGenNode()
+
+    except rospy.ROSInterruptException:
+        pass
-- 
GitLab