Ejemplo n.º 1
0
    def __init__(self, ter=None, AS=0, DS=0):
        self.Ter = list(ter) if ter is not None else None
        self.N = 0 if self.Ter is None else len(self.Ter)
        self.AS = AS
        self.DS = DS

        self.maxV = 0.0
        self.VSP = 0.0
        self.upA = 0.0
        self.upV = 0.0
        self.rV = 0.0
        self.upX = 0.0
        self.dX = 0.0
        self.E = 0.0
        self.upAF = 0.0

        self.T = []
        self.X = []
        self.rX = []
        self.V = []
        self.rV = []
        self.K = []
        self.F = []
        self.VSp = []

        self.M = 4.0
        self.MinVSF = 0.1

        self.vK1_pid = PID(0.3, 0.1, 0.3, 0.0, 1.0)
Ejemplo n.º 2
0
def sim_PID():
    np.random.seed(42)

    def rSV(val, delta):
        return max(0, min(100,
                          val + (delta * np.random.random() - delta / 2.0)))

    t1 = 10.0
    PV = 10.0
    SV = [rSV(50, 100)]
    T = np.arange(0, t1, PID.dt)
    sSV = SV[-1]
    for _t in T[1:]:
        r = np.random.random()
        if r < 0.98:
            SV.append(SV[-1])
            continue
        sSV = rSV(sSV, 50)
        SV.append(sSV)

    pid1 = PID(0.8, 0.2, 0.001, -10, 10)
    pid2 = PID2(0.8, 0.2, 0.001, -10, 10)

    pid1.sim(PV, SV, T)
    pid2.sim(PV, SV, T)
    plt.show()
Ejemplo n.º 3
0
def sim_PointNav():
    P = 2
    D = 0.1
    AAk = 0.5
    pid = PID(P, 0, D, 0, 10)
    accel = np.arange(0.1, 1.1, 0.1)
    distance = 500
    distanceF = 0.1
    cols = color_grad(len(accel))
    for i, a in enumerate(accel):
        d = [distance]
        v = [0]
        act = [0]
        t = 0
        A = [0]
        while d[-1] > 0:
            pid.kp = P * a / clampL(v[-1], 0.01)
            act.append(pid.update(d[-1] * distanceF))
            aa = a * AAk

            if v[-1] < pid.action:
                if A[-1] < a: A.append(A[-1] + a * AAk * dt)
                else: A.append(a)
            elif v[-1] > pid.action:
                if A[-1] > -a: A.append(A[-1] - a * AAk * dt)
                else: A.append(-a)
            elif A[-1] > 0: A.append(A[-1] - a * AAk * dt)
            elif A[-1] < 0: A.append(A[-1] + a * AAk * dt)
            else: A.append(0)
            #             print 'd=% 8.4f, v=% 8.4f, act=% 8.4f, A=% 8.4f' % (d[-1], v[-1], act[-1], A[-1])
            v.append(v[-1] + A[-1] * dt)
            d.append(d[-1] - v[-1] * dt)
            t += dt
        print 'accel=%.2f, time: %.1fs' % (a, t)
        print len(d), len(A)
        plt.subplot(3, 1, 1)
        plt.plot(d, v, color=cols[i], label="accel=%.2f" % a)
        plt.ylabel("V")
        plt.xlabel("distance")
        plt.subplot(3, 1, 2)
        plt.plot(d, act, color=cols[i], label="accel=%.2f" % a)
        plt.ylabel("act")
        plt.xlabel("distance")
        plt.subplot(3, 1, 3)
        plt.plot(d, A, color=cols[i], label="accel=%.2f" % a)
        plt.ylabel("real accel");
        plt.xlabel("distance")
    plt.legend()
    plt_show_maxed()
Ejemplo n.º 4
0
def sim_Rotation():
    def _plot(r, c, n, X, Y, aa, ylab):
        plt.subplot(r, c, n)
        plt.plot(X, Y, label=("V: AA=%.1f" % aa))
        plt.xlabel("time (s)")
        plt.ylabel(ylab)

    MaxAngularA = np.arange(0.5, 30, 5);
    start_error = 0.8 * np.pi
    end_time = 10.0

    def test(c, n, pid):
        p = pid.kp;
        d = pid.kd
        for aa in MaxAngularA:
            A = [start_error]
            V = [0.0]
            S = [0.0]
            T = [0.0]

            def plot(c, n, Y, ylab):
                _plot(3, c, n, T, Y, aa, ylab)

            pid.kp = p / aa
            pid.kd = d / aa
            while T[-1] < end_time:
                S.append(pid.update(A[-1]))
                V.append(V[-1] - S[-1] * aa * dt)
                A.append(A[-1] + V[-1] * dt)
                T.append(T[-1] + dt)
            plot(c, n, np.fromiter(A, float) / np.pi * 180.0, 'Angle')
            plot(c, c + n, V, 'Angular velocity')
            plot(c, c * 2 + n, S, 'Steering')

    test(2, 1, PID(6.0, 0, 10.0, -1, 1))
    test(2, 2, PID(4.0, 0, 6.0, -1, 1))
    legend()
    plt.show()
Ejemplo n.º 5
0
    def run_alt(self, alt, salt=0.0, thrust=20.0, pid=PID(0.5, 0.0, 0.5, -9.9, 9.9)):
        self.pid = pid
        self._vK = self.vK2
        self.cthrust = self.M * 9.81
        self.maxV = 0.0
        self.VSP = 0.0
        self.upV = 0.0
        self.upX = salt if self.Ter is None else self.Ter[0] + 10
        self.Vsp = [self.maxV]
        self.dVsp = [0]
        self.init(thrust)
        d = pid.kd

        def on_frame():
            alt_err = alt - self.dX
            if self.AS > 0 or self.DS > 0:
                if alt_err > 0:
                    self.pid.kp = clamp(0.01 * abs(alt_err) / clampL(self.upV, 1), 0.0, d)
                elif alt_err < 0:
                    self.pid.kp = clamp(self.twr ** 2 / clampL(-self.upV, 1), 0.0, clampH(d * self.twr / 2, d))
                else: self.pid.kp = d
            self.pid.kd = d / clampL(self.dX, 1)
            if alt_err < 0: alt_err = alt_err / clampL(self.dX, 1)
            self.maxV = self.pid.update(alt_err)
            print self.pid, alt_err, clamp(0.01 * abs(alt_err) / clampL(self.upV, 1), 0.0, d), d
            if self.N > 0:
                dV = (self.upV - self.dV) / clampL(self.dX, 1)
                if alt_err < 0:
                    #                     print '% f %+f = %f' % (dV/clampL(self.dX/50, 1), clampL(alt_err*self.dX/5000*self.twr, self.pid.min*10), dV/clampL(self.dX/50, 1) + clampL(alt_err*self.dX/5000*self.twr, self.pid.min*10))
                    dV = dV + clampL(alt_err * self.dX / 500 * self.twr, self.pid.min * 10)
                else:
                    dV = clampL(dV, 0)
                #                 print dV
                self.dVsp.append(dV)
                self.maxV += dV
            self.Vsp.append(self.maxV)

        self.phys_loop(on_frame)
Ejemplo n.º 6
0
from __future__ import print_function
from __future__ import print_function
import numpy as np
import matplotlib.pyplot as plt

from scipy.optimize import curve_fit

from common import clampL, clampH, clamp01, lerp, PID, PID2, dt, center_deg

if __name__ == '__main__':
    amp = np.pi
    bearing_pid = PID(amp, 0.001, 1.0, -amp, amp)

    av_pid = PID(1.0, 0.05, 0, -1.0, 1.0)

    def timelines(t, *lines):
        n = len(lines)
        for i in range(n):
            plt.subplot(n, 1, i + 1)
            plt.plot(t, lines[i])
        plt.show()

    def sym(angle, maxAA, max_t, aaF, draw=False):
        t = [0]
        a = [angle]
        av = [0]
        avn = [0]
        st = [0]
        bearing_pid.reset()
        av_pid.reset()
        bearing_pid.D = aaF
Ejemplo n.º 7
0
    def __init__(self, debug=False):
        super(DriveNode, self).__init__(name='DriveNode', debug=debug)
        """
        ------------------------------------------------------------------------------------------
        Publishers
        ------------------------------------------------------------------------------------------
        """

        # Publisher of speed to motor driver and odometry to other nodes
        self._speedout_pub = HALSpeedOutPublisher()
        self._odom_pub = OdometryPublisher()
        """
        ------------------------------------------------------------------------------------------
        Parameters
        ------------------------------------------------------------------------------------------
        """

        # Robot physical dimensions
        self._track_width = rospy.get_param('Track Width', 0.3937)
        self._wheel_radius = rospy.get_param('Wheel Radius', 0.0785)

        # Main loop rate in hz
        drive_node_rate = rospy.get_param('Drive Node Rate', 10)
        self._loop_rate = rospy.Rate(drive_node_rate)
        self._loop_period = 1.0 / float(drive_node_rate)

        max_wheel_rpm = rospy.get_param('Max Wheel RPM', 95.0)
        max_wheel_ang_vel = rpm_to_rps(max_wheel_rpm, self._wheel_radius)

        # Calculate max unicycle velocities based on wheel maximum, track width and wheel radius
        max_lin_vel, max_ang_vel = uni_max(max_wheel_ang_vel,
                                           self._track_width,
                                           self._wheel_radius)

        max_angular_accel = rospy.get_param('Max Angular Accel', 0.15)
        max_angular_decel = rospy.get_param('Max Angular Decel', 0.15)

        self._angular_max = AngularMax(ccw=max_ang_vel,
                                       cw=-max_ang_vel,
                                       accel=max_angular_accel,
                                       decel=-max_angular_decel,
                                       wheel=max_ang_vel)

        max_linear_accel = rospy.get_param('Max Linear Accel', 0.035)
        max_linear_decel = rospy.get_param('Max Linear Decel', 0.035)

        self._linear_max = LinearMax(forward=max_lin_vel,
                                     backward=-max_lin_vel,
                                     accel=max_linear_accel,
                                     decel=-max_linear_decel)

        # PID controllers
        linear_kp = rospy.get_param('Linear Gain Kp', 0.8)
        linear_ki = rospy.get_param('Linear Gain Ki', 0.0)
        linear_kd = rospy.get_param('Linear Gain Kd', 0.0)
        self._lin_pid = PID('linear', linear_kp, linear_ki, linear_kd, 0.0,
                            max_lin_vel, self._loop_period)

        angular_kp = rospy.get_param('Angular Gain Kp', 0.8)
        angular_ki = rospy.get_param('Angular Gain Ki', 0.0)
        angular_kd = rospy.get_param('Angular Gain Kd', 0.0)
        self._ang_pid = PID('angular', angular_kp, angular_ki, angular_kd, 0.0,
                            max_ang_vel, self._loop_period)

        # State variable storage
        self._vel_state = VelocityState()
        self._odometry = OdometryState()
        self._cmd_vel_state = CommandVelocityState()

        rospy.loginfo(
            STATUS_FMT.format(self._track_width, self._wheel_radius,
                              self._wheel_radius * 2,
                              self._wheel_radius * 2 * math.pi,
                              max_wheel_ang_vel, max_ang_vel, max_lin_vel,
                              max_angular_accel, max_linear_accel))
        """
        -------------------------------------------------------------------------------------------
        Subscribers
        -------------------------------------------------------------------------------------------
        """

        # Note: Declare subscribers at the end to prevent premature callbacks

        # Subscriber for Twist messages
        self._twist_sub = rospy.Subscriber("cmd_vel",
                                           Twist,
                                           self._twist_cmd_cb,
                                           queue_size=1)
        # Subscriber for motor driver speed, distance, and orientation messages
        self._speedin_sub = rospy.Subscriber("HALSpeedIn",
                                             HALSpeedIn,
                                             self._speedin_cb,
                                             queue_size=1)
        self._positionin_sub = rospy.Subscriber("HALPositionIn",
                                                HALPositionIn,
                                                self._positionin_cb,
                                                queue_size=1)
        self._headingin_sub = rospy.Subscriber("HALHeadingIn",
                                               HALHeadingIn,
                                               self._headingin_cb,
                                               queue_size=1)
        self._eulerin_sub = rospy.Subscriber("HALEulerIn",
                                             HALEulerIn,
                                             self._eulerin_cb,
                                             queue_size=1)
Ejemplo n.º 8
0
class DriveNode(BaseNode):
    """
    The DriveNode is responsible for:
        * accepting Twist messages to be sent to the motor driver.
        * ensuring max linear/angular velocity and applying acceleration limits.
        * reading speed, distance and heading data from the hardware drivers, calculating and publishing
          odometry.
    """
    def __init__(self, debug=False):
        super(DriveNode, self).__init__(name='DriveNode', debug=debug)
        """
        ------------------------------------------------------------------------------------------
        Publishers
        ------------------------------------------------------------------------------------------
        """

        # Publisher of speed to motor driver and odometry to other nodes
        self._speedout_pub = HALSpeedOutPublisher()
        self._odom_pub = OdometryPublisher()
        """
        ------------------------------------------------------------------------------------------
        Parameters
        ------------------------------------------------------------------------------------------
        """

        # Robot physical dimensions
        self._track_width = rospy.get_param('Track Width', 0.3937)
        self._wheel_radius = rospy.get_param('Wheel Radius', 0.0785)

        # Main loop rate in hz
        drive_node_rate = rospy.get_param('Drive Node Rate', 10)
        self._loop_rate = rospy.Rate(drive_node_rate)
        self._loop_period = 1.0 / float(drive_node_rate)

        max_wheel_rpm = rospy.get_param('Max Wheel RPM', 95.0)
        max_wheel_ang_vel = rpm_to_rps(max_wheel_rpm, self._wheel_radius)

        # Calculate max unicycle velocities based on wheel maximum, track width and wheel radius
        max_lin_vel, max_ang_vel = uni_max(max_wheel_ang_vel,
                                           self._track_width,
                                           self._wheel_radius)

        max_angular_accel = rospy.get_param('Max Angular Accel', 0.15)
        max_angular_decel = rospy.get_param('Max Angular Decel', 0.15)

        self._angular_max = AngularMax(ccw=max_ang_vel,
                                       cw=-max_ang_vel,
                                       accel=max_angular_accel,
                                       decel=-max_angular_decel,
                                       wheel=max_ang_vel)

        max_linear_accel = rospy.get_param('Max Linear Accel', 0.035)
        max_linear_decel = rospy.get_param('Max Linear Decel', 0.035)

        self._linear_max = LinearMax(forward=max_lin_vel,
                                     backward=-max_lin_vel,
                                     accel=max_linear_accel,
                                     decel=-max_linear_decel)

        # PID controllers
        linear_kp = rospy.get_param('Linear Gain Kp', 0.8)
        linear_ki = rospy.get_param('Linear Gain Ki', 0.0)
        linear_kd = rospy.get_param('Linear Gain Kd', 0.0)
        self._lin_pid = PID('linear', linear_kp, linear_ki, linear_kd, 0.0,
                            max_lin_vel, self._loop_period)

        angular_kp = rospy.get_param('Angular Gain Kp', 0.8)
        angular_ki = rospy.get_param('Angular Gain Ki', 0.0)
        angular_kd = rospy.get_param('Angular Gain Kd', 0.0)
        self._ang_pid = PID('angular', angular_kp, angular_ki, angular_kd, 0.0,
                            max_ang_vel, self._loop_period)

        # State variable storage
        self._vel_state = VelocityState()
        self._odometry = OdometryState()
        self._cmd_vel_state = CommandVelocityState()

        rospy.loginfo(
            STATUS_FMT.format(self._track_width, self._wheel_radius,
                              self._wheel_radius * 2,
                              self._wheel_radius * 2 * math.pi,
                              max_wheel_ang_vel, max_ang_vel, max_lin_vel,
                              max_angular_accel, max_linear_accel))
        """
        -------------------------------------------------------------------------------------------
        Subscribers
        -------------------------------------------------------------------------------------------
        """

        # Note: Declare subscribers at the end to prevent premature callbacks

        # Subscriber for Twist messages
        self._twist_sub = rospy.Subscriber("cmd_vel",
                                           Twist,
                                           self._twist_cmd_cb,
                                           queue_size=1)
        # Subscriber for motor driver speed, distance, and orientation messages
        self._speedin_sub = rospy.Subscriber("HALSpeedIn",
                                             HALSpeedIn,
                                             self._speedin_cb,
                                             queue_size=1)
        self._positionin_sub = rospy.Subscriber("HALPositionIn",
                                                HALPositionIn,
                                                self._positionin_cb,
                                                queue_size=1)
        self._headingin_sub = rospy.Subscriber("HALHeadingIn",
                                               HALHeadingIn,
                                               self._headingin_cb,
                                               queue_size=1)
        self._eulerin_sub = rospy.Subscriber("HALEulerIn",
                                             HALEulerIn,
                                             self._eulerin_cb,
                                             queue_size=1)

    def _twist_cmd_cb(self, msg):
        """
        Callback registered to receive cmd_vel messages

        Averages the receipt times of cmd_vel messages for use in velocity processing
        Stores velocity for later processing

        :param msg: the cmd_vel message
        :return: None
        """
        self._cmd_vel_state.add_delta(rospy.Time.now())
        self._cmd_vel_state.velocity.set(v=msg.linear.x, w=msg.angular.z)

    def _speedin_cb(self, msg):
        """
        Callback registered to receive HALSpeedIn messages

        Receives and stores unicycle speed

        :param msg: the HALSpeedIn message (see HALSpeedIn.msg)
        :return: None
        """
        self._odometry.set_velocity(msg.linear, msg.angular)

    def _positionin_cb(self, msg):
        """
        Callback registered to receive HALPositionIn messages

        Receives and stores x/y position

        :param msg: the HALPositionIn message (see HALPositionIn.msg)
        :return: None
        """
        self._odometry.set_position(msg.x, msg.y)

    def _headingin_cb(self, msg):
        """

        :param msg:
        :return:
        """
        self._odometry.set_orientation(yaw=msg.heading)

    def _eulerin_cb(self, msg):
        """
        Callback registered to receive HALEulerIn messages

        Receives and stores roll, pitch and yaw

        :param msg: the HALEulerIn message
        :return: None
        """
        #self._odometry.set_orientation(msg.roll, msg.pitch, msg.yaw)

    def _publish_odom(self):
        """
        Publishes odometry on the odom topic

        :return: None
        """
        if self._odometry.is_ready():
            self._odom_pub.publish(self._odometry.x, self._odometry.y,
                                   self._odometry.velocity.linear,
                                   self._odometry.velocity.angular,
                                   self._odometry.heading)

    def _velocity_has_changed(self):
        return (not isclose(self._vel_state.target_velocity.linear,
                            self._vel_state.last_velocity.linear)
                or not isclose(self._vel_state.target_velocity.angular,
                               self._vel_state.last_velocity.angular))

    def _safety_check(self):
        """
        Perform safety/sanity checking on the command velocity before passing through the velocity pipeline

        if the command velocity is active (we're getting velocity commands) and command velocity is recent
            - constrain the commanded velocity to mechanical and user-defined limits
            - ensure requested angular velocity can be achieved
            - store in target velocity
        if the command velocity is stale or not being received at all
            - zero out target velocity

        :return: None
        """

        # TODO-Add a velocity check for 'too' large velocity change with resulting adjustment that is proportional

        if self._cmd_vel_state.is_active():

            if self._cmd_vel_state.is_recent(num_msgs=5, max_time=2.0):

                v_initial = self._cmd_vel_state.velocity.linear
                w_initial = self._cmd_vel_state.velocity.angular

                # Ensure linear and angular velocity are within mecahnical and user-defined ranges
                v = constrain(v_initial, self._linear_max.backward,
                              self._linear_max.forward)
                w = constrain(w_initial, self._angular_max.cw,
                              self._angular_max.ccw)

                # Ensure the specified angular velocity can be achieved.
                #
                # Even though velocity is constrained within defined limits, it is necessary to check that the resulting
                # velocities are achievable.  For example if both wheels are moving at the maximum linear velocity and
                # an angular velocity is specified, it is necessary to reduce the linear velocity in order to achieve
                # the angular velocity.

                # Note: Will adjust linear velocity if necessary
                v, w = ensure_w(v, w, self._track_width, self._wheel_radius,
                                self._angular_max.wheel)

                rospy.loginfo(
                    "SafetyCheck: initial {:.3f} {:.3f}, constrained {:.3f} {:.3f}"
                    .format(v_initial, w_initial, v, w))

                self._vel_state.target_velocity.set(v, w)

            else:
                rospy.logwarn(
                    "No message received for {} msgs or {} secs".format(
                        5, 1.0))
                self._vel_state.zero_target()

        else:
            rospy.logwarn("No command velocity active")
            self._vel_state.zero_target()

    def _limit_accel(self):
        lv_initial = self._vel_state.last_velocity
        tv_initial = self._vel_state.target_velocity

        # Calculate the desired and max velocity increments for linear and angular velocities
        v_inc, max_v_inc = calc_vel_inc(self._vel_state.target_velocity.linear,
                                        self._vel_state.last_velocity.linear,
                                        self._linear_max.accel,
                                        self._linear_max.decel,
                                        self._loop_period)

        w_inc, max_w_inc = calc_vel_inc(
            self._vel_state.target_velocity.angular,
            self._vel_state.last_velocity.angular, self._angular_max.accel,
            self._angular_max.decel, self._loop_period)

        # Create normalized vectors for desired (v_inv/w_inc) and maximum (max_v_inc/max_w_inc) velocity increments
        Av, Aw = normalize_vector(v_inc, w_inc)
        Bv, Bw = normalize_vector(max_v_inc, max_w_inc)

        # Use the angle between the vectors to determine which increment will dominate
        theta = math.atan2(Bw, Bv) - math.atan2(Aw, Av)

        if theta < 0.0:
            try:
                max_v_inc = (max_w_inc * math.fabs(v_inc)) / math.fabs(w_inc)
            except ZeroDivisionError:
                pass
        else:
            try:
                max_w_inc = (max_v_inc * math.fabs(w_inc)) / math.fabs(v_inc)
            except ZeroDivisionError:
                pass

        # Calculate the velocity delta to be applied
        v_delta = math.copysign(1.0, v_inc) * min(math.fabs(v_inc),
                                                  math.fabs(max_v_inc))
        w_delta = math.copysign(1.0, w_inc) * min(math.fabs(w_inc),
                                                  math.fabs(max_w_inc))

        # Apply the velocity delta to the last velocity
        self._vel_state.target_velocity.linear = self._vel_state.last_velocity.linear + v_delta
        self._vel_state.target_velocity.angular = self._vel_state.last_velocity.angular + w_delta

        rospy.logdebug("LimitAccel - initial {} {}, resulting {} {}".format(
            lv_initial, tv_initial, self._vel_state.last_velocity,
            self._vel_state.target_velocity))

    def _track_velocity(self):
        """
        Track linear and angular velocity using PID controller
        Note: Only track when command velocity is active; otherwise, zero out published velocity

        :return:
        """
        rospy.logdebug("TV Entry - O: {}, T: {}, L: {}".format(
            self._odometry.velocity, self._vel_state.target_velocity,
            self._vel_state.last_velocity))

        delta_v = self._lin_pid.update(self._odometry.velocity.linear)
        delta_w = self._ang_pid.update(self._odometry.velocity.angular)

        self._lin_pid.print(rospy.logdebug)
        self._ang_pid.print(rospy.logdebug)

        rospy.logdebug("TV - dv {:02.3f}, dw {:02.3f}".format(
            delta_v, delta_w))

        self._vel_state.target_velocity.linear += delta_v
        self._vel_state.target_velocity.angular += delta_w

        rospy.logdebug("TV Exit - O: {}, T: {}, L: {}".format(
            self._odometry.velocity, self._vel_state.target_velocity,
            self._vel_state.last_velocity))

    def _process_velocity(self):
        rospy.logdebug("PV Entry - T: {}, L: {}".format(
            self._vel_state.target_velocity, self._vel_state.last_velocity))

        self._safety_check()

        if self._velocity_has_changed():
            rospy.logdebug("Velocity Changed")
            self._limit_accel()

        else:
            rospy.logdebug("Velocity Unchanged")
            self._vel_state.target_velocity.linear = self._vel_state.last_velocity.linear
            self._vel_state.target_velocity.angular = self._vel_state.last_velocity.angular

        #self._lin_pid.set_target(self._vel_state.target_velocity.linear)
        #self._ang_pid.set_target(self._vel_state.target_velocity.angular)

        rospy.logdebug("PV Exit - T: {}, L: {}".format(
            self._vel_state.target_velocity, self._vel_state.last_velocity))

    def _update_speed(self):
        linear, angular = 0.0, 0.0
        if self._vel_state.target_velocity.linear != 0.0 or self._vel_state.target_velocity.angular != 0.0:
            linear, angular = self._vel_state.target_velocity.linear, self._vel_state.target_velocity.angular

        self._speedout_pub.publish(SpeedData(linear=linear, angular=angular))

    def start(self):
        rospy.loginfo("DriveNode starting ...")
        self._speedout_pub.publish(SpeedData(linear=0.0, angular=0.0))
        rospy.loginfo("DriveNode started")

    def loop(self):
        rospy.loginfo("DriveNode loop starting ...")
        while not rospy.is_shutdown():

            # Smooth velocity
            self._process_velocity()

            # Update Speed
            self._update_speed()

            # Track velocity
            #self._track_velocity()

            self._vel_state.last_velocity.linear = self._vel_state.target_velocity.linear
            self._vel_state.last_velocity.angular = self._vel_state.target_velocity.angular

            # Publish odometry
            self._publish_odom()

            rospy.loginfo(
                "Linear(T/O): {:6.3f}/{:6.3f}, Angular(T/O): {:6.3f}/{:6.3f}".
                format(self._vel_state.target_velocity.linear,
                       self._odometry.velocity.linear,
                       self._vel_state.target_velocity.angular,
                       self._odometry.velocity.angular))

            self._loop_rate.sleep()

        self.shutdown()
        rospy.loginfo("DriveNode loop exiting")

    def shutdown(self):
        rospy.loginfo("DriveNode shutdown")
Ejemplo n.º 9
0
                    if IR in XBMC_dic.keys():
                        kodi(XBMC_dic[IR])
                    elif codeIR[0] in extra_esp_keys:
                        e = ESP()
                        e.Go_parallel(extra_esp_keys[IR])
                    else:
                        logger.info('speaking only ' + IR)
                        Speak(IR)
                last = [IR, datetime.datetime.now()]
        except:
            logger.error('error : ' + str(sys.exc_info()))
            Speak('error in lirc module')
            sleep(2)
        sleep(0.3)


if __name__ == '__main__':
    #    with daemon.DaemonContext():
    try:
        from common import LOGGER, PID
        logger = LOGGER('lirc')
        #            logger = log # compatibility
        logger.info('starting lirc')
        from time import sleep
        from KODI_control import kodi
        PID()
        import lirc
        sockid = lirc.init("test", blocking=False)
        Start()
    except:
        logger.error('error on initiation: ' + str(sys.exc_info()))
Ejemplo n.º 10
0
class VSF_sim(object):
    t1 = 5.0

    def __init__(self, ter=None, AS=0, DS=0):
        self.Ter = list(ter) if ter is not None else None
        self.N = 0 if self.Ter is None else len(self.Ter)
        self.AS = AS
        self.DS = DS

        self.maxV = 0.0
        self.VSP = 0.0
        self.upA = 0.0
        self.upV = 0.0
        self.rV = 0.0
        self.upX = 0.0
        self.dX = 0.0
        self.E = 0.0
        self.upAF = 0.0

        self.T = []
        self.X = []
        self.rX = []
        self.V = []
        self.rV = []
        self.K = []
        self.F = []
        self.VSp = []

        self.M = 4.0
        self.MinVSF = 0.1

        self.vK1_pid = PID(0.3, 0.1, 0.3, 0.0, 1.0)

    def vK1(self):
        #         upAF = 0.0
        #         if self.upA < 0 and self.AS > 0: upAF = (1.0/self.AS)*2
        #         elif self.DS > 0: upAF = (1.0/self.DS)*1
        #         upAF *= -self.upA*0.04
        #         self.VSP = self.maxV+(2.0+upAF)/self.twr
        #         self.E = self.VSP-self.upV
        return self.vK1_pid.update(self.E)

    def vK2(self):
        #         print('Thrust %.2f, W %.2f, H %.2f, upV %.2f, E %.2f, upA %.2f, upAF %.3f, dVSP %.2f, K0 %.3f, K1 %.3f'
        #               % (self.cthrust, self.M*9.81, self.upX, self.upV, self.maxV-self.upV, self.upA, upAF, (2.0+upAF)/self.twr,
        #                  clamp01(self.E/2.0/(clampL(self.upA/self.K1+1.0, self.L1)**2)),
        #                  clamp01(self.E/2.0/(clampL(self.upA/self.K1+1.0, self.L1)**2)+upAF)))
        # return clampL(clamp01(self.E/2.0/(clampL(self.upA/self.K1+1.0, self.L1)**2)+upAF), 0.05)
        #         if self.upV <= self.maxV:
        K = clamp01(self.E * 0.5 + self.upAF)
        #         else:
        #             K = clamp01(self.E*self.upA*0.5+self.upAF)
        return clampL(K, self.MinVSF)

    _vK = vK2

    @property
    def vK(self):
        self.E = self.VSP - self.upV
        return self._vK()

    def init(self, thrust):
        self.thrust = thrust
        self.add_thrust = 0
        self.twr = thrust / 9.81 / self.M
        self.upA = 0.0
        self.dV = self.upV
        self.dX = self.upX - self.Ter[0] if self.N > 0 else 0
        self.T = [0.0]
        self.A = [self.upA]
        self.V = [self.upV]
        self.rV = [self.dV]
        self.X = [self.upX]
        self.rX = [self.dX]
        self.K = [self.vK]
        self.F = [0.0]

    def update_upAF(self):
        self.upAF = 0.0
        if self.upA < 0 < self.AS: self.upAF = (1.0 / self.AS) * 2
        elif self.DS > 0: self.upAF = (1.0 / self.DS) * 1
        self.upAF = -self.upA * 0.2 * self.upAF
        self.VSP = self.maxV + (2.0 + self.upAF) / self.twr

    def phys_loop(self, on_frame=lambda: None):
        i = 1
        while self.dX >= 0 and (self.T[-1] < self.t1 or i < self.N):
            self.T.append(self.T[-1] + dt)
            self.update_upAF()
            on_frame()
            # VSF
            self.K.append(self.vK)
            # thrust
            rthrust = self.thrust * self.K[-1]
            speed = self.AS if rthrust > self.cthrust else self.DS
            self.cthrust = lerp(self.cthrust, rthrust, speed * dt) if speed > 0 else rthrust
            # dynamics
            self.upA = (self.add_thrust + self.cthrust - self.M * 9.81) / self.M
            self.upV += self.upA * dt
            self.upX += self.upV * dt
            self.dX = self.upX - (self.Ter[i] if self.N > 0 else 0)
            self.dV = EWA(self.dV, (self.dX - self.rX[-1]) / dt, 0.1)
            # logging
            self.F.append(self.cthrust * dt)
            self.A.append(self.upA)
            self.V.append(self.upV)
            self.rV.append(self.dV)
            self.X.append(self.upX)
            self.rX.append(self.dX)
            i += 1

    def run(self, upV, maxV=1.0, thrust=20.0, vK=None):
        if vK is not None: self._vK = vK
        self.cthrust = self.M * 9.81
        self.maxV = maxV
        self.VSP = maxV
        self.upV = upV
        self.upX = 100.0
        self.init(thrust)
        self.phys_loop()

    def run_impulse(self, dthrust=10, impulse=0.1, maxV=1.0, thrust=20.0):
        self._vK = self.vK2
        self.cthrust = self.M * 9.81
        self.maxV = maxV
        self.VSP = maxV
        self.upV = maxV
        self.upX = 100.0
        self.init(thrust)

        def on_frame():
            if 3 < self.T[-1] < 3 + impulse:
                self.add_thrust = dthrust
            else: self.add_thrust = 0
            self.twr = (self.thrust + self.add_thrust) / 9.81 / self.M

        self.phys_loop(on_frame)

    def run_alt(self, alt, salt=0.0, thrust=20.0, pid=PID(0.5, 0.0, 0.5, -9.9, 9.9)):
        self.pid = pid
        self._vK = self.vK2
        self.cthrust = self.M * 9.81
        self.maxV = 0.0
        self.VSP = 0.0
        self.upV = 0.0
        self.upX = salt if self.Ter is None else self.Ter[0] + 10
        self.Vsp = [self.maxV]
        self.dVsp = [0]
        self.init(thrust)
        d = pid.kd

        def on_frame():
            alt_err = alt - self.dX
            if self.AS > 0 or self.DS > 0:
                if alt_err > 0:
                    self.pid.kp = clamp(0.01 * abs(alt_err) / clampL(self.upV, 1), 0.0, d)
                elif alt_err < 0:
                    self.pid.kp = clamp(self.twr ** 2 / clampL(-self.upV, 1), 0.0, clampH(d * self.twr / 2, d))
                else: self.pid.kp = d
            self.pid.kd = d / clampL(self.dX, 1)
            if alt_err < 0: alt_err = alt_err / clampL(self.dX, 1)
            self.maxV = self.pid.update(alt_err)
            print self.pid, alt_err, clamp(0.01 * abs(alt_err) / clampL(self.upV, 1), 0.0, d), d
            if self.N > 0:
                dV = (self.upV - self.dV) / clampL(self.dX, 1)
                if alt_err < 0:
                    #                     print '% f %+f = %f' % (dV/clampL(self.dX/50, 1), clampL(alt_err*self.dX/5000*self.twr, self.pid.min*10), dV/clampL(self.dX/50, 1) + clampL(alt_err*self.dX/5000*self.twr, self.pid.min*10))
                    dV = dV + clampL(alt_err * self.dX / 500 * self.twr, self.pid.min * 10)
                else:
                    dV = clampL(dV, 0)
                #                 print dV
                self.dVsp.append(dV)
                self.maxV += dV
            self.Vsp.append(self.maxV)

        self.phys_loop(on_frame)

    #         print(("Start velocity: %f\n"
    #                "K1 %f; L1 %f; K2 %f L2 %f\n"
    #                "Fuel consumed: %f\n")
    #               % (upV, self.K1, self.L1, self.K2, self.L2, sum(self.F)))

    def describe(self):
        from scipy import stats
        cols = ('X', 'rX', 'V', 'rV', 'Vsp', 'dVsp', 'K')
        for n in cols:
            c = getattr(self, n)
            d = stats.describe(c)
            print '%s:' % n
            print '   sum:    ', sum(c)
            print '   min-max:', d.minmax
            print '   mean:   ', d.mean
            print '   median: ', np.median(c)
            print '   std:    ', np.std(c)
            print '   sem:    ', stats.sem(c)
            print '   skew:   ', d.skewness
            print '   hist:   '
            h = np.histogram(c, normed=True)
            for i, e in enumerate(h[1][1:]):
                e0 = h[1][i]
                print '[% 8.3f : % 8.3f]: %s' % (e0, e, "#" * int(h[0][i] * 80))
            print ''
        print '\n'

    def _plot(self, r, c, n, Y, ylab):
        plt.subplot(r, c, n)
        plt.plot(self.T, Y, label=("V: twr=%.1f" % self.twr))
        plt.ylabel(ylab)

    def legend(self):
        plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)

    def plot_a(self, r, c, n):
        self._plot(r, c, n, self.A, ylab="vertical acceleration (m/s2)")

    def plot_vs(self, r, c, n):
        self._plot(r, c, n, self.V, ylab="vertical speed (m/s)")

    def plot_ter(self, r, c, n):
        if self.N == 0: return
        self._plot(r, c, n, self.Ter[:len(self.T)], ylab="terrain (m)")

    def plot_alt(self, r, c, n):
        self._plot(r, c, n, self.X, ylab="altitude (m)")

    def plot_ralt(self, r, c, n):
        self._plot(r, c, n, self.rX, ylab="relative altitude (m)")

    def plot_vsp(self, r, c, n):
        self._plot(r, c, n, self.Vsp, ylab="VSP (m/s)")

    def plot_dvsp(self, r, c, n):
        if len(self.dVsp) != len(self.T): return
        self._plot(r, c, n, self.dVsp, ylab="dVSP (m/s)")

    def plot_k(self, r, c, n):
        self._plot(r, c, n, self.K, ylab="K")
from __future__ import print_function
import numpy as np
import matplotlib.pyplot as plt
from multiprocessing import Pool, cpu_count

from scipy.optimize import curve_fit

from common import clampL, clampH, clamp01, lerp, PID, PID2, PID3, dt, center_deg, plt_show_maxed

if __name__ == '__main__':
    rad2deg = 180 / np.pi
    bearing_pid = PID(1, 0.0, 0.0, 0, np.pi * 10)

    av_pid = PID3(
        1.0,
        0.1,
        0,
        -1.0,
        1.0,
        3 * dt,
    )

    def timelines(t, *lines):
        n = len(lines)
        ax1 = None
        for i, line in enumerate(lines):
            ax = plt.subplot(n, 1, i + 1, sharex=ax1)
            plt.plot(t, line)
            plt.grid(b=False,
                     which='major',
                     axis='x',