def updateState(self, dt, waypoint):

        u = self.control(waypoint)

        pose, angles, velocities, angular_velocity = self.true_curr_state.updateState(
            dt, u)

        if not (self.sonar is None) and self.i % 50 == 0:
            _, view = self.sonar.generateView(pose[0:2].T, angles[2])
        else:
            view = []

        self.i += 1

        next_state = RobotState(pose,
                                angles,
                                velocities,
                                angular_velocity,
                                view=view)

        if (len(self.estimated_state_history) == 0) and not (self.ins is None):
            self.estimated_state_history = [self.true_curr_state, next_state]

            self.histories.append(self.estimated_state_history)

        if (len(self.true_state_history) >= 2) and not (self.ins is None):

            state_minus_2 = self.true_state_history[-2]

            measures = self.ins.generateMeasures(dt, next_state,
                                                 self.true_curr_state,
                                                 state_minus_2)

            pose, angles, velocities, angular_velocity, Gamma = self.integrateINS(
                dt, measures, self.previous_measure,
                self.estimated_state_history, view)

            self.previous_measure = measures

            # =============================================================================
            #         Create state instance
            # =============================================================================

            self.estimated_curr_state = RobotState(pose,
                                                   angles,
                                                   velocities,
                                                   angular_velocity,
                                                   Gamma,
                                                   view=view)

            # =============================================================================
            #         Save state
            # =============================================================================

            self.estimated_state_history.append(self.estimated_curr_state)

        self.true_curr_state = next_state

        self.true_state_history.append(self.true_curr_state)
Exemple #2
0
async def track(p: RobotState.RobotState, stream, yaw=0, speed=0):
    import state
    import tracking

    tracker = tracking.ExtendedKalmanFilterTracker()

    # For every message from GPS/robot or on timeout
    # run control loop and provide output to robot - OR - on fail safe, stop robot
    # (possibly with the option to resume the control loop, saving the last known good position)
    async for t, o in stream:
        # logger.debug("track input {%s} {%s}", t, o)
        if t is None or o is None:
            continue

        # returns (t, dt, z, u) or None
        m = p.update(t, o)
        # logger.debug("track input %s %r -> %r", t, o, m)

        if not p.battery_ok:
            logger.error("Battery low: %s", p.battery)
            return

        if not p.power_ok:
            logger.error("Power high: %s", p.power)
            return

        if m is not None:
            # logger.debug("track input %s %r -> %r", t, o, m)
            # feed tracking.track()
            _, dt, z, ud, hdop = m
            # logger.debug("TRACK STREAM %r %r %r", dt, z, ud)
            s = tracker.update2(z, ud, hdop, dt)
            s = state.from_array(s)
            logger.debug("STATE %g %g %g %g", s.x, s.y, s.theta, s.speed)
            yield s
Exemple #3
0
    def updateState(self, dt, waypoint):
        
        u  = self.control(waypoint)
        
        pose, angles, velocities, angular_velocity = self.true_curr_state.updateState(dt, u)
        
        if not (self.sonar is None) and self.i%50 == 0:
            _, view = self.sonar.generateView(pose[0:2].T, angles[2])
        else:
            view = []
            
        self.i += 1
        
        self.true_curr_state = RobotState(pose, angles, velocities, angular_velocity, view = view)   
        
        self.true_state_history.append(self.true_curr_state)
        
# =============================================================================
#         Live INS if possible
# =============================================================================
        
        if not(self.ins is None) and len(self.true_state_history) >= 3:
            
            state_minus_1 = self.true_state_history[-2]
            state_minus_2 = self.true_state_history[-3]
            
            if (len(self.estimated_state_history) == 0):
                self.estimated_state_history.append(self.true_state_history[0])
                self.estimated_state_history.append(self.true_state_history[1])
                
                self.histories.append(self.estimated_state_history)
                self.labels.append("Dead reckoning")
            
            measures = self.ins.generateMeasures(dt, self.true_curr_state, state_minus_1, state_minus_2)
            
            self.ins_measures_history = np.vstack((self.ins_measures_history, measures)) \
                                        if len(self.ins_measures_history) else measures
            
            previousState = self.estimated_state_history[-1]
            
            estimatedState = self.deadReckoningEstimator.compute_localization(previousState, measures, self.previous_measure, view)
            
            self.previous_measure = measures
            
            self.estimated_state_history.append(estimatedState)
Exemple #4
0
    def __init__(self, pose = np.array([0, 0, 0]), \
                 orientation = np.array([0, 0, 0]), \
                 linear_velocity = np.array([1, 0, 0]), \
                 angular_velocity = np.array([0, 0, 0]), \
                 initial_gamma = np.zeros((3, 3)), \
                 ins = None, \
                 sonar = None, \
                 environment = None):
        
        self.true_curr_state = RobotState(pose, orientation, linear_velocity, angular_velocity, initial_gamma)
        
        self.true_state_history = [self.true_curr_state]
        
        
        self.ins_measures_history = []
        
        
        self.histories = [self.true_state_history]
        
        self.labels = ["Ground truth"]
        
# =============================================================================
#         Equations
# =============================================================================
        
        self.A = np.eye(3)
        self.B = np.eye(3)
        
        self.ins = ins
        if not ins is None:
            self.estimated_state_history    = []
            self.labels.append("Dead reckoning")
            self.gamma_ins = self.ins.getCovarianceOfMeasures()
            
            self.deadReckoningEstimator = Dead_Reckoning_LocalizationEstimator(0.5, np.eye(3), np.eye(3), self.gamma_ins)
            
        self.sonar = sonar

        self.previous_measure = np.array([0, 0, -9.81, 0, 0, 0])
        
        self.i = 0
    def computeTrajectoryWithNewINS(self, ins, dt, name="No name"):

        gammaINS = ins.getCovarianceOfMeasures()

        new_estimated_history = []
        previous_measure = np.array([0, 0, -9.81, 0, 0, 0])

        if len(self.true_state_history) >= 2:

            new_estimated_history = self.true_state_history[0:2]

            for i in range(2, len(self.true_state_history)):

                current_state = self.true_state_history[i]
                minus_1_state = self.true_state_history[i - 1]
                minus_2_state = self.true_state_history[i - 2]

                view = self.true_state_history[i].view

                measures = ins.generateMeasures(dt, current_state,
                                                minus_1_state, minus_2_state)

                pose, angles, velocities, angular_velocity, Gamma = self.integrateINS(
                    dt, measures, previous_measure, new_estimated_history,
                    view, gammaINS)

                previous_measure = measures

                # =============================================================================
                #         Create state instance
                # =============================================================================

                newly_estimated_curr_state = RobotState(pose,
                                                        angles,
                                                        velocities,
                                                        angular_velocity,
                                                        Gamma,
                                                        view=view)

                # =============================================================================
                #         Save state
                # =============================================================================

                new_estimated_history.append(newly_estimated_curr_state)

        self.histories.append(new_estimated_history)
        self.labels.append(name)

        return new_estimated_history
Exemple #6
0
    def compute_localization(self, i, previousState, insMeasures,
                             previousInsMeasure, view):

        C, y, Gamma_obs = self.__generate_observations(i, view)

        correct_gravity = np.array([0, 0, 9.81])

        # =============================================================================
        #         Angular integration
        # =============================================================================

        angular_velocity = insMeasures[3:6]

        previousAngles = previousState.orientation

        previousR = rotmat(previousAngles[0], previousAngles[1],
                           previousAngles[2])

        angles = self.dt * angular_velocity + previousAngles

        R = rotmat(angles[0], angles[1], angles[2])

        # =============================================================================
        #         Velocities integration after correction of rotation and gravity
        # =============================================================================

        velocities = self.dt * (
            previousR @ previousInsMeasure[0:3] + R @ insMeasures[0:3] +
            2 * correct_gravity) / 2 + previousState.linear_velocity

        # =============================================================================
        #         Kalman filter for computing pose
        # =============================================================================

        pose, Gamma = kalman(previousState.pose, self.A, previousState.gamma,
                             self.dt * velocities, self.B, self.gammaINS, y,
                             Gamma_obs, C)

        estimatedState = RobotState(pose,
                                    angles,
                                    velocities,
                                    angular_velocity,
                                    Gamma,
                                    view=view)

        return estimatedState
Exemple #7
0
motorHandler.addMotor(leftMotor)
motorHandler.addMotor(rightMotor)

#Initialize sensor handler and add sensors and motors
LOGGER.Debug("Linking sensors and servos to sensor handler...")
sensorHandler.addServo(cameraServo)

#initialize encoder reset flags
driveEncoderResetFlag = False
scoopEncoderResetFlag = False
depthEncoderResetFlag = False
winchEncoderResetFlag = False

# initialize robotState
# LOGGER.Debug("Initializing robot state...")
robotState = RobotState()


def cameraCommunicationThread():
    global frame
    global cameraOutput
    LOGGER.Debug("Starting Cameraaaaaaaaaaaa")
    pipeline = TargetFinder()
    while cap.isOpened():
        cameraHandlerLock.acquire()
        have_frame, frame = cap.read()
        ret, jpeg = cv2.imencode(".jpg", frame)
        cameraOutput = jpeg.tobytes()
        #LOGGER.Debug(str(len(frame)))
        cameraHandlerLock.release()
Exemple #8
0
sensorHandler.addSensor(rightDriveCurrentSense)
sensorHandler.addSensor(collectorDepthCurrentSense)
sensorHandler.addSensor(collectorScoopsCurrentSense)
sensorHandler.addSensor(winchMotorCurrentSense)
sensorHandler.addSensor(scoopReedSwitch)
sensorHandler.addSensor(bucketMaterialDepthSense)

sensorHandler.addServo(ratchetServo)
sensorHandler.addServo(camServo1)
sensorHandler.addServo(camServo2)
sensorHandler.addServo(camServo3)
sensorHandler.addServo(camServo4)

# initialize robotState
LOGGER.Debug("Initializing robot state...")
robotState = RobotState()

# initialize joystick, if using joystick
if CONSTANTS.USING_JOYSTICK:
    LOGGER.Debug("Initializing joystick...")
    pygame.init()
    pygame.joystick.init()
    joystick1 = pygame.joystick.Joystick(0)
    joystick1.init()
    jReader = JoystickReader(joystick1)

ceaseAllMotorFunctions()

if CONSTANTS.USING_MOTOR_BOARD:
    LOGGER.Debug("Initializing motor board thread...")
    #Sets up an isr essentially using the motorCommunicationThread()
Exemple #9
0
import sys

from motorControl import motorControl
from leader import leader
from Follower import Follower
from captorDistance import captorDistance
from RobotState import RobotState

from pybricks.tools import DataLog, StopWatch, wait
# This program requires LEGO EV3 MicroPython v2.0 or higher.
# Click "Open user guide" on the EV3 extension tab for more information.

#for record in records:
#data.log(record['id'],record['firstname'])

# Create your objects here.
ev3 = EV3Brick()

#state = RobotState("all_or_nothing_follow")
#state = RobotState("up_to_point_follow")
state = RobotState("two_points_follow")

follower = Follower(state)

#l = leader(1000)

# Write your program here.
print(sys.version)

#ev3.speaker.beep(5)
Exemple #10
0
class Robot:
    """Describe the current state of the robot and store the previous states"""

    def __init__(self, pose = np.array([0, 0, 0]), \
                 orientation = np.array([0, 0, 0]), \
                 linear_velocity = np.array([1, 0, 0]), \
                 angular_velocity = np.array([0, 0, 0]), \
                 initial_gamma = np.zeros((3, 3)), \
                 ins = None, \
                 sonar = None, \
                 environment = None):
        
        self.true_curr_state = RobotState(pose, orientation, linear_velocity, angular_velocity, initial_gamma)
        
        self.true_state_history = [self.true_curr_state]
        
        
        self.ins_measures_history = []
        
        
        self.histories = [self.true_state_history]
        
        self.labels = ["Ground truth"]
        
# =============================================================================
#         Equations
# =============================================================================
        
        self.A = np.eye(3)
        self.B = np.eye(3)
        
        self.ins = ins
        if not ins is None:
            self.estimated_state_history    = []
            self.labels.append("Dead reckoning")
            self.gamma_ins = self.ins.getCovarianceOfMeasures()
            
            self.deadReckoningEstimator = Dead_Reckoning_LocalizationEstimator(0.5, np.eye(3), np.eye(3), self.gamma_ins)
            
        self.sonar = sonar

        self.previous_measure = np.array([0, 0, -9.81, 0, 0, 0])
        
        self.i = 0
        
        
        
    def __str__(self):
        
        return "Number of state(s) in trajectory : {}\n".format(len(self.true_state_history))
        
    def control(self, waypoint):
        
        curr_pos = self.true_curr_state.pose
        wp_gisement = np.arctan2(waypoint[1] - curr_pos[1], waypoint[0] - curr_pos[0])
        
        yaw_error = sawtooth(self.true_curr_state.orientation[2] - wp_gisement)
        
        if abs(yaw_error) > 2.5:
            u = 1.0
        else:
            u = -0.1 * yaw_error
        
        return u
    
    def updateState(self, dt, waypoint):
        
        u  = self.control(waypoint)
        
        pose, angles, velocities, angular_velocity = self.true_curr_state.updateState(dt, u)
        
        if not (self.sonar is None) and self.i%50 == 0:
            _, view = self.sonar.generateView(pose[0:2].T, angles[2])
        else:
            view = []
            
        self.i += 1
        
        self.true_curr_state = RobotState(pose, angles, velocities, angular_velocity, view = view)   
        
        self.true_state_history.append(self.true_curr_state)
        
# =============================================================================
#         Live INS if possible
# =============================================================================
        
        if not(self.ins is None) and len(self.true_state_history) >= 3:
            
            state_minus_1 = self.true_state_history[-2]
            state_minus_2 = self.true_state_history[-3]
            
            if (len(self.estimated_state_history) == 0):
                self.estimated_state_history.append(self.true_state_history[0])
                self.estimated_state_history.append(self.true_state_history[1])
                
                self.histories.append(self.estimated_state_history)
                self.labels.append("Dead reckoning")
            
            measures = self.ins.generateMeasures(dt, self.true_curr_state, state_minus_1, state_minus_2)
            
            self.ins_measures_history = np.vstack((self.ins_measures_history, measures)) \
                                        if len(self.ins_measures_history) else measures
            
            previousState = self.estimated_state_history[-1]
            
            estimatedState = self.deadReckoningEstimator.compute_localization(previousState, measures, self.previous_measure, view)
            
            self.previous_measure = measures
            
            self.estimated_state_history.append(estimatedState)
    
    def replace_INS_measures(self, dt, ins, name = "INS"):
        
        ins_history = self.conpute_ins_measure_history(dt, ins)
        
        self.ins_measures_history = np.copy(ins_history)
        
        deadReckoningEstimator = Dead_Reckoning_LocalizationEstimator(dt, np.eye(3), np.eye(3), ins.getCovarianceOfMeasures())
        
        self.compute_new_trajectory(deadReckoningEstimator, name = name)
        
        INS_trajectory_history = self.histories.pop()
        self.histories.insert(1, INS_trajectory_history)
        
        self.estimated_state_history = INS_trajectory_history
        
        
    def conpute_ins_measure_history(self, dt, ins):
        
        ins_history = None
        
        for i in range(2, len(self.true_state_history)):
            current_state = self.true_state_history[i]
            minus_1_state = self.true_state_history[i-1]
            minus_2_state = self.true_state_history[i-2]

            measures = ins.generateMeasures(dt, current_state, minus_1_state, minus_2_state)
        
            ins_history = np.vstack((ins_history, measures)) if (not ins_history is None) else measures
        
        return ins_history
    
    def compute_new_trajectory(self, estimator, ins = None, name = "No name"):
        
        dt = estimator.dt
        
        estimated_history = []
        previous_measure = np.array([0, 0, -9.81, 0, 0, 0])
        
        if len(self.true_state_history) >= 2:
            
            estimated_history = self.true_state_history[0:2]
            
            if ins is None:
                ins_measures_history = self.ins_measures_history
            else:
                ins_measures_history = self.conpute_ins_measure_history(dt, ins)
                
                
            for i in range(2, len(self.true_state_history)):
                
                data = self.true_state_history[i].view
                
                if name == "ScanMatching" or name == "Noisy ScanMatching":
                    
                    previousView = self.true_state_history[i-50].view
                    previousPose = self.true_state_history[i-50].pose
                    previousAngle = self.true_state_history[i-50].orientation
                    view = self.true_state_history[i].view
                    
                    data = [previousView, view, previousPose[0:2], previousAngle[2]]
                
                measures = ins_measures_history[i-2, :]
                
                previousState = estimated_history[-1]
                
                estimated_state = estimator.compute_localization(i, previousState, measures, previous_measure, data)
                
                previous_measure = measures
                
                estimated_history.append(estimated_state)
                
                
        
        self.histories.append(estimated_history)
        self.labels.append(name)
        
        return estimated_history
    
# =============================================================================
# =============================================================================
# #     PLOT FUNCTIONS
# =============================================================================
# =============================================================================
    
    def plot(self, axis = None):
        
        if axis is None:
            fig = plt.figure("Robot trajectories")
            axis = fig.add_subplot(111, aspect="equal")
        
        for history, label in zip(self.histories, self.labels):
                    
            if len(history) >= 2:
                trajectory = []
                for state in history:
                    trajectory = np.vstack((trajectory, state.pose)) if len(trajectory) else state.pose
        
                axis.plot(trajectory[:, 0], trajectory[:, 1], label = label)
        
        axis.legend()
        
    def plot_uncertainty(self):
        
#        fig = plt.figure("Uncertainty XY-plane")
#        traj_axis = fig.add_subplot(111, aspect='equal')
        
        fig = plt.figure("Evolution of error")
        error_axis = fig.add_subplot(111)
        
        init = True
        
        for history, label in zip(self.histories, self.labels):
            if len(history) >= 2:
                trajectory = []
                i = 0
                for state in history:
#                    if i%200 == 0:
#                        draw_ellipse(state.pose[0:2], state.gamma[0:2, 0:2], 0.9, traj_axis, 'r')
                        
                    i += 1
                    
                    trajectory = np.vstack((trajectory, state.pose[0:2])) if len(trajectory) else state.pose[0:2]
                
#                traj_axis.plot(trajectory[:, 0], trajectory[:, 1], '-.', label = label)
                
                if init:
                    ground_truth = np.copy(trajectory)
                    init = False
                else:
                    error = np.sqrt((trajectory[:, 0] - ground_truth[:, 0])**2 +
                                    (trajectory[:, 1] - ground_truth[:, 1])**2)
                    
                    error_axis.plot(error, '-.', label = label)
        
#        traj_axis.legend()
        error_axis.legend()
        plt.show()
    
    def plot_history(self):
        
        _, (ax1, ax2, ax3) = plt.subplots(1, 3)
        ax1.set_title('X Axis')
        ax2.set_title('Y Axis')
        ax3.set_title('Z Axis')
        
        _, (ax4, ax5, ax6) = plt.subplots(1, 3)
        ax4.set_title('Roll')
        ax5.set_title('Pitch')
        ax6.set_title('Yaw')
        
        for history, label in zip(self.histories, self.labels):
            if len(history) >= 2:
                trajectory = []
                for state in history:
                    data = np.hstack((state.pose, state.orientation, state.linear_velocity))
                    trajectory = np.vstack((trajectory, data)) if len(trajectory) else data
                
                ax1.plot(trajectory[:, 1])
                ax2.plot(trajectory[:, 2])
                ax3.plot(trajectory[:, 3])
                ax4.plot(trajectory[:, 4])
                ax5.plot(trajectory[:, 5])
                ax6.plot(trajectory[:, 6])
  
        plt.show()

    def comparison_plot(self):
        
        if len(self.histories) >= 2:
            
# =============================================================================
#             Ground truth
# =============================================================================
            
            groundTruth = self.histories[0]
            groundTruthLabel = self.labels[0]
            
            if len(groundTruth) >= 2:
                groundTruthTrajectory = []
                for state in groundTruth:
                    
                    groundTruthTrajectory = np.vstack((groundTruthTrajectory, state.pose[0:2])) if len(groundTruthTrajectory) else state.pose[0:2]
            
# =============================================================================
#             Dead Reckoning
# =============================================================================
            
            deadReckoning = self.histories[1]
            deadReckoningLabel = self.labels[1]
            
            if len(deadReckoning) >= 2:
                deadReckoningTrajectory = []
                for state in deadReckoning:
                    
                    deadReckoningTrajectory = np.vstack((deadReckoningTrajectory, state.pose[0:2])) if len(deadReckoningTrajectory) else state.pose[0:2]
       
                deadReckoningError = np.sqrt((deadReckoningTrajectory[:, 0] - groundTruthTrajectory[:, 0])**2 +
                                             (deadReckoningTrajectory[:, 1] - groundTruthTrajectory[:, 1])**2)
                
            
                plt.figure("{} | {}".format(groundTruthLabel, deadReckoningLabel))
                ax1 = plt.subplot2grid((1, 3), (0, 0), aspect='equal')
                ax2 = plt.subplot2grid((1, 3), (0, 1), colspan=2)
                
                ax1.plot(groundTruthTrajectory[:, 0], groundTruthTrajectory[:, 1], 'g', label = groundTruthLabel)
                ax1.plot(deadReckoningTrajectory[:, 0], deadReckoningTrajectory[:, 1], 'b', label = deadReckoningLabel)
                ax1.legend()
                
                ax2.plot(deadReckoningError, label = deadReckoningLabel)
                ax2.legend()
        
# =============================================================================
#         Others
# =============================================================================
        
        if len(self.histories) >= 3:
            
            for history, label in zip(self.histories[2:], self.labels[2:]):
                
                plt.figure("{}".format(label))
                ax1 = plt.subplot2grid((1, 3), (0, 0), aspect='equal')
                ax2 = plt.subplot2grid((1, 3), (0, 1), colspan=2)
                
                ax1.plot(groundTruthTrajectory[:, 0], groundTruthTrajectory[:, 1], 'g', label = groundTruthLabel)
                ax1.plot(deadReckoningTrajectory[:, 0], deadReckoningTrajectory[:, 1], 'b', label = deadReckoningLabel)
            
                ax2.plot(deadReckoningError, label = deadReckoningLabel)
            
                if len(history) >= 2:
                    trajectory = []
                    for state in history:
                        trajectory = np.vstack((trajectory, state.pose[0:2])) if len(trajectory) else state.pose[0:2]
                    
                    ax1.plot(trajectory[:, 0], trajectory[:, 1], 'r', label = label)
            
                    error = np.sqrt((trajectory[:, 0] - groundTruthTrajectory[:, 0])**2 +
                                    (trajectory[:, 1] - groundTruthTrajectory[:, 1])**2)
                    
                    ax2.plot(error, label = label)
            
                ax1.legend()
                ax2.legend()

        plt.show()