Пример #1
0
class OutputPlotGraphics():
    ''' Class containing the output plot display behaviour: plotting the state and drawing the speed arrow

        Can also plot other information on the graph such as a line that represents the target trajectory,
        but these functions have been disabled to reduce display latency'''
    def __init__(self, outputPlot):

        self.decayValue = 0

        self.outputPlot = outputPlot

        self.measurementPatch = Rectangle((0, 0),
                                          1,
                                          1,
                                          linewidth=1,
                                          color='gray',
                                          facecolor='none')
        self.statePatch = Circle((0, 0), 1, facecolor='blue')
        self.speedPatch = Arrow(0, 0, 3, 3)
        self.circlePatch = Circle((0, 0),
                                  1,
                                  linewidth=1,
                                  color='red',
                                  facecolor='None')
        self.linePatch = ConnectionPatch((0, 0), (1, 1), 'data')

        self.model = 0
        self.startLine = (0, 0)
        self.needToResetStartLine = True

        self.outputPlot.add_patch(self.measurementPatch)
        self.outputPlot.add_patch(self.statePatch)
        self.outputPlot.add_patch(self.speedPatch)
        self.outputPlot.add_patch(self.circlePatch)
        self.outputPlot.add_patch(self.linePatch)

        self.circlePatch.set_visible(False)
        self.linePatch.set_visible(False)

    def setModel(self, model):

        if model != self.model:
            self.decayValue = 10
        elif self.decayValue > 0:
            self.decayValue -= 1

            if self.decayValue == 5:
                self.needToResetStartLine = True

        self.model = model

        if self.decayValue <= 0:
            if model == 0:
                self.speedPatch.set_visible(False)
                self.linePatch.set_visible(False)
                self.circlePatch.set_visible(False)

            if model == 1:
                self.speedPatch.set_visible(True)
                self.linePatch.set_visible(True)
                self.circlePatch.set_visible(False)

            if model == 2:
                self.speedPatch.set_visible(True)
                self.linePatch.set_visible(False)
                #self.circlePatch.set_visible(True)

    def setState(self, x, y):
        self.statePatch.center = x, y

    def setMeasurement(self, x, y):
        self.measurementPatch.set_xy((x, y))

    def setSpeed(self, x, y, vx, vy):
        self.speedPatch.remove()
        self.speedPatch = Arrow(x, y, vx / 10, vy / 10)
        self.outputPlot.add_patch(self.speedPatch)

    def setCircle(self, x, y, R):
        self.circlePatch.set_radius(R)
        self.circlePatch.center = x, y

    def setLine(self, x, y):
        """ if self.needToResetStartLine:
            self.needToResetStartLine = False
            self.startLine = (x,y)

        self.linePatch.remove()
        self.linePatch = ConnectionPatch((self.startLine[0],self.startLine[1]), (x+1, y+1), 'data')
        self.outputPlot.add_patch(self.linePatch) """
        pass
Пример #2
0
class Body(object):
    '''
    Represent a solid body by a list of vertices, the position of its center of
    mass and orientation
    '''
    def __init__(self,
                 orientation=0.0,
                 x=0.0,
                 y=0.0,
                 v=0.0,
                 acc=0.0,
                 omega=0.0,
                 vertex=None):
        self.x = x
        self.y = y
        self.orientation = orientation
        self.v = v
        self.acc = acc
        self.omega = omega

        self.lastUpdate = 0.0

        if vertex is None:
            self.vertices = np.matrix([0, 0])
        else:
            self.vertices = np.matrix(vertex)

        self.radius = self.__calculateRadius__()

        # handling plot
        self.plotRefreshRate = 2  # seconds
        self.fig = None
        self.timeOfLastPlot = -self.plotRefreshRate

        self.bodyLine = None
        self.directionArrow = None

    @classmethod
    def fromVehicle(cls, vehicle):
        orientation = vehicle.getOrientation()
        pos = vehicle.getPos()
        vel = vehicle.getVelocity()
        acc = vehicle.getAcc()
        omega = vehicle.getOmega()

        vertices = [(-vehicle.length / 2, -2), (-vehicle.length / 2, 2),
                    (vehicle.length / 2, 2), (vehicle.length / 2, -2)]
        return cls(orientation=orientation,
                   x=pos[0],
                   y=pos[1],
                   v=vel,
                   acc=acc,
                   omega=omega,
                   vertex=vertices)

    def setVertex(self, vertex):
        self.vertices = np.matrix(vertex)
        self.radius = self.__calculateRadius__()

    def __calculateRadius__(self):
        rows, cols = self.vertices.shape
        radius = 0
        for i in range(rows):
            currRadius = sqrt(self.vertices[i, ] * self.vertices[i, ].T)
            radius = max(radius, currRadius)
        return radius

    def checkBodyCollision(self, body):
        d = self.getDistance(body)
        if (d < self.radius + body.radius):
            polygonSelf = Polygon(self.getPose())
            polygonBody = Polygon(body.getPose())
            return polygonSelf.intersects(polygonBody)
        else:
            return False

    def checkLineCollision(self, line):
        polygonSelf = Polygon(self.getPose())
        return polygonSelf.intersects(line)

    def getPolygon(self):
        return Polygon(self.getPose())

    def getOrigin(self):
        return Point(self.x, self.y)

    def getDistance(self, body):
        return sqrt((self.x - body.x)**2 + (self.y - body.y)**2)

    def setAcceleration(self, acc):
        self.acc = acc

    def setOmega(self, omega):
        self.omega = omega

    def updateStates(self, t):
        dt = t - self.lastUpdate

        self.x += self.v * cos(self.orientation)
        self.y += self.v * sin(self.orientation)
        self.v += self.acc * dt
        self.orientation += self.omega * dt

        self.lastUpdate = t

    def setStates(self, x, y, v, orientation, t):
        self.x = x
        self.y = y
        self.v = v
        self.orientation = orientation

        self.lastUpdate = t

    def resetTime(self):
        self.lastUpdate = 0

    def getPosition(self):
        return self.x, self.y

    def getOrientation(self):
        return self.orientation

    def getVelocity(self):
        return self.v

    def createPlot(self, fig=None, ax=None):
        self.timeOfLastPlot = -1

        if (fig is None):
            self.fig = plt.figure()
        else:
            self.fig = fig

        if (ax is None):
            self.ax = self.fig.add_subplot(111)
        else:
            self.ax = ax

        (verticesX, verticesY) = self.getDrawingVertex()
        self.bodyLine, = self.ax.plot(verticesX, verticesY, 'k')
        self.directionArrow = Arrow(self.x,
                                    self.y,
                                    0.1 * self.v * cos(self.orientation),
                                    0.1 * self.v * sin(self.orientation),
                                    color='c')
        self.ax.add_patch(self.directionArrow)
        self.ax.set_xlim([self.x - 10, self.x + 10])
        self.ax.set_ylim([self.y - 10, self.y + 10])
        self.ax.set_xlabel('Distance X')
        self.ax.set_ylabel('Distance Y')

    def getPose(self):
        verticesX = []
        verticesY = []
        self.R = np.matrix([(cos(self.orientation), -sin(self.orientation)),
                            (sin(self.orientation), cos(self.orientation))])
        v = self.R * self.vertices.transpose()  # applyting the rotation matrix
        v = v.transpose()
        rows, cols = v.shape
        for i in range(rows):
            verticesX.append(v[i, 0] + self.x)
            verticesY.append(v[i, 1] + self.y)
        return v + np.matrix([self.x, self.y])

    def getDrawingVertex(self):
        vertices = self.getPose()
        vX = [v[0, 0] for v in vertices]
        vX.append(vertices[0, 0])
        vY = [v[0, 1] for v in vertices]
        vY.append(vertices[0, 1])
        return vX, vY

    def plot(self, draw=True):
        (verticesX, verticesY) = self.getDrawingVertex()
        self.bodyLine.set_ydata(verticesY)
        self.bodyLine.set_xdata(verticesX)

        self.directionArrow.remove()
        self.directionArrow = Arrow(self.x,
                                    self.y,
                                    0.1 * self.v * cos(self.orientation),
                                    0.1 * self.v * sin(self.orientation),
                                    color='c')
        self.ax.add_patch(self.directionArrow)
        self.ax.set_xlim([self.x - 10, self.x + 10])
        self.ax.set_ylim([self.y - 10, self.y + 10])

        if (draw):
            self.fig.canvas.draw()
            plt.pause(0.001)
Пример #3
0
class Plot_canvas(FigureCanvas):
    def __init__(self):
        fig = Figure(figsize=(4, 4), dpi=100)
        self.ax = fig.add_subplot(111)
        super().__init__(fig)
        FigureCanvas.setSizePolicy(self, QSizePolicy.Expanding,
                                   QSizePolicy.Expanding)
        FigureCanvas.updateGeometry(self)
        self.radars = []

    def init_walls(self, pos_angle, ends, fin_pos):
        self.ax.cla()
        self.ax.plot(*zip(*ends),
                     color='k')  # zip equals to tranpose, * eauals to depack
        finish_area = Rectangle(xy=(fin_pos[0][0], fin_pos[1][1]),
                                width=fin_pos[1][0] - fin_pos[0][0],
                                height=fin_pos[1][1] - fin_pos[0][1],
                                color='red')
        self.ax.add_artist(finish_area)
        pos = tuple(pos_angle[:2])
        angle = math.radians(pos_angle[2])
        self.car = Circle(pos, radius=3, color='mediumblue')
        self.head = Arrow(pos[0],
                          pos[1],
                          dx=5 * math.cos(angle),
                          dy=5 * math.sin(angle),
                          facecolor='gold',
                          edgecolor='k')
        self.ax.add_artist(self.car)
        self.ax.add_artist(self.head)
        self.draw()

    def update_car(self, pos_angle, inters):
        self.car.remove()
        self.head.remove()

        pos = tuple(pos_angle[:2])
        angle = math.radians(pos_angle[2])
        self.car = Circle(pos, radius=3, color='mediumblue')
        self.head = Arrow(pos[0],
                          pos[1],
                          dx=5 * math.cos(angle),
                          dy=5 * math.sin(angle),
                          facecolor='gold',
                          edgecolor='k')
        if self.radars:
            for radar in self.radars:
                radar.remove()
        self.radars = [
            Line2D(*zip(pos, inter), linestyle='-', color='gray')
            for inter in inters
        ]
        for radar in self.radars:
            self.ax.add_line(radar)
        self.ax.add_artist(self.car)
        self.ax.add_artist(self.head)
        self.draw()

    def collide(self):
        self.car.set_color('darkred')
        self.draw()

    def show_path(self, path_x, path_y):
        self.path = Line2D(path_x,
                           path_y,
                           linewidth=6,
                           solid_capstyle='round',
                           solid_joinstyle='round',
                           alpha=0.75,
                           color='gray')
        self.ax.add_line(self.path)
        self.draw()
Пример #4
0
class MyMainWindow(QMainWindow, Ui_MainWindow):
    """
    Main window class
    """
    def __init__(self, ):
        """
        Main constructor
        """
        super(MyMainWindow, self).__init__()

        self.setupUi(self)
        self.connect_click_handlers()

        self.emitter = Emitter()

        self.particleList = []

        self.figure = plt.figure()
        self.canvas = FigureCanvas(self.figure)

        self.setLayouts()

        self.ax = self.figure.add_subplot(1, 1, 1)

        self.emitter_vector = Arrow(self.emitter.coordinates[0],
                                    self.emitter.coordinates[1],
                                    self.emitter.vector[0] / 20,
                                    self.emitter.vector[1] / 20,
                                    width=0.09)

        self.figure.canvas.mpl_connect('button_press_event',
                                       self.changeEmitter)

        self.solar_mode = False

        self.particleList = self.initialize_solar_system()
        self.particleListV = supercopy(self.particleList)

        self.toDraw = supercopy(self.particleList)

        self.animation = FuncAnimation(self.figure,
                                       self.draw_particles,
                                       interval=10)

        self.x_scale = None

        self.inaccuracy_iter = [[], []]
        self.i = 0

    def draw_particles(self, frame):
        """
        Function to draw all particles
        """
        if self.pauseRadioButton.isChecked():
            return

        self.i += 1

        for i in range(len(self.toDraw)):
            try:
                self.toDraw[i].circle.remove()
            except Exception:
                pass

        delta_t = 0.01 if self.solar_mode else 1

        odeint_list = supercopy(self.particleList)
        verle_list = supercopy(self.particleListV)

        start_time = datetime.datetime.now()
        verle_list = overall_verle(verle_list, [0, delta_t / 2, delta_t])[0]
        #verle_list = overall_verle_threading(verle_list, [0, delta_t / 2, delta_t])[0]
        #verle_list = overall_verle_multiprocessing(verle_list, [0, delta_t / 2, delta_t])[0]
        #verle_list = overall_verle_cython(verle_list, [0, delta_t / 2, delta_t])[0]
        #verle_list = overall_verle_opencl(verle_list, [0, delta_t / 2, delta_t])[0]
        print("Verle iteration: {}".format(datetime.datetime.now() -
                                           start_time))

        #start_time = datetime.datetime.now()
        odeint_list = overall_odeint(odeint_list, [0, delta_t / 2, delta_t])[0]
        #print("Odeint iteration: {}".format(datetime.datetime.now() - start_time))

        self.particleList = to_particle_list(odeint_list, self.particleList)
        self.particleListV = to_particle_list(verle_list_, self.particleListV)

        metric = .0

        for p_1, p_2 in zip(self.particleList, self.particleListV):
            dist = np.array(p_1.coordinates) - np.array(p_2.coordinates)
            metric += np.linalg.norm(dist)

        self.inaccuracy_iter[0].append(self.i)
        self.inaccuracy_iter[1].append(metric)

        self.toDraw = supercopy(
            self.particleListV) if self.methodCheckBox.isChecked(
            ) else supercopy(self.particleList)

        if len(self.toDraw) != 0:

            if self.x_scale is None:
                self.x_scale = max(
                    [elem.coordinates[0] for elem in self.toDraw] + [100])
            max_m = max([elem.mass for elem in self.toDraw])

            sorted_masses = sorted([elem.mass for elem in self.toDraw])
            masses_map = dict()
            sizes = np.linspace(0.01, 0.03, len(sorted_masses))

            for i, elem in enumerate(sorted_masses):
                masses_map[elem] = sizes[i]

            for i in range(len(self.toDraw)):

                self.toDraw[i].create_circle(
                    coordinates=[
                        self.toDraw[i].coordinates[0] / (self.x_scale * 2.1) +
                        0.5, self.toDraw[i].coordinates[1] /
                        (self.x_scale * 2.1) + 0.5
                    ],
                    size=masses_map[self.toDraw[i].mass],
                    color=self.toDraw[i].color)

                self.ax.add_artist(self.toDraw[i].circle)

        self.figure.canvas.draw_idle()

    def connect_click_handlers(self):
        """
        Function that connects button click events to proper handlers
        """
        self.generateParticleButton.clicked.connect(self.generateParticle)
        self.emitterChangeButton.clicked.connect(self.changeEmitter)
        self.pauseRadioButton.clicked.connect(self.draw_inacc)

    def draw_inacc(self):
        plt.plot(self.inaccuracy_iter[0], self.inaccuracy_iter[1])

    def setLayouts(self):
        vertical_layout1 = QVBoxLayout()

        vertical_layout1.addWidget(self.particleXAxisSpeedLineEdit)
        vertical_layout1.addWidget(self.particleYAxisSpeedLineEdit)
        vertical_layout1.addWidget(self.particleColorLineEdit)
        vertical_layout1.addWidget(self.massLabel)
        vertical_layout1.addWidget(self.particleMassLineEdit)
        vertical_layout1.addWidget(self.generateParticleButton)

        vertical_layout2 = QVBoxLayout()

        vertical_layout2.addWidget(self.emitterXLineEdit)
        vertical_layout2.addWidget(self.emitterYLineEdit)
        vertical_layout2.addWidget(self.emitterXVectorLineEdit)
        vertical_layout2.addWidget(self.emitterYVectorLineEdit)
        vertical_layout2.addWidget(self.emitterChangeButton)
        vertical_layout2.addWidget(self.pauseRadioButton)

        horizontal_layout1 = QHBoxLayout()

        horizontal_layout1.addLayout(vertical_layout1)
        horizontal_layout1.addLayout(vertical_layout2)

        vertical_layout3 = QVBoxLayout()

        vertical_layout3.addLayout(horizontal_layout1)
        vertical_layout3.addWidget(self.methodCheckBox)

        horizontal_layout2 = QHBoxLayout()

        horizontal_layout2.addLayout(vertical_layout3)
        self.canvas.setMinimumWidth(700)
        self.canvas.setMinimumHeight(700)
        horizontal_layout2.addWidget(self.canvas)

        self.centralwidget.setLayout(horizontal_layout2)

    def generateParticle(self):
        """
        Generate particle button click event handler
        """
        try:
            xAxisSpeed = float(self.particleXAxisSpeedLineEdit.text())
        except Exception:
            print("generateParticle(): x axis speed is in wrong format!")
            return

        try:
            yAxisSpeed = float(self.particleYAxisSpeedLineEdit.text())
        except Exception:
            print("generateParticle(): y axis speed is in wrong format!")
            return

        color = self.particleColorLineEdit.text()

        #mass = self.particleMassSlider.value()

        try:
            mass_list = self.particleMassLineEdit.text().upper().split('E')
            mass = float(mass_list[0]) * pow(10, int(mass_list[1]))
        except Exception as ex:
            print("generateParticle(): failed to parse mass, error: " +
                  str(ex))
            return

        particle = Particle(
            [self.emitter.coordinates[0], self.emitter.coordinates[1]], [
                xAxisSpeed * self.emitter.vector[0],
                yAxisSpeed * self.emitter.vector[1]
            ], mass, color)

        self.particleList.append(particle)
        self.x_scale = None

    def changeEmitter(self):
        """
        Emitter position changed button click event handler
        """
        # ------------------------ Parsing new valus ---------------------------
        try:
            xAxis = float(self.emitterXLineEdit.text())
        except Exception:
            print("changeEmitter(): x axis is in wrong format!")
            return

        try:
            yAxis = float(self.emitterYLineEdit.text())
        except Exception:
            print("changeEmitter(): y axis is in wrong format!")
            return

        try:
            xVector = int(self.emitterXVectorLineEdit.text())
        except Exception:
            print("changeEmitter(): x axis vector is in wrong format!")
            return

        try:
            yVector = int(self.emitterYVectorLineEdit.text())
        except Exception:
            print("changeEmitter(): y axis vector is in wrong format!")
            return
        # -----------------------------------------------------------------------

        # Changing emitter position
        self.emitter.change_position([xAxis, yAxis], [xVector, yVector])

        # Removing old emitter (we have no emitter, don't do anything)
        try:
            self.emitter_vector.remove()
        except Exception:
            pass

        # Creating new emitter
        self.emitter_vector = Arrow(self.emitter.coordinates[0],
                                    self.emitter.coordinates[1],
                                    self.emitter.vector[0] / 20,
                                    self.emitter.vector[1] / 20,
                                    width=0.09)

        # Redraw plot
        self.figure.canvas.draw_idle()

    def initialize_solar_system(self, data_file="solar_system.json"):
        """
        Function that prepares solar system example
        """
        self.particleList = []

        with open(data_file, "r") as descr:
            text_content = descr.read()

        json_content = json.loads(text_content)

        for val in json_content["particles"].values():

            particle = Particle(coordinates=[val["x"], val["y"]],
                                speed=[val["u"], val["v"]],
                                mass=val["m"],
                                color=val["color"],
                                living_time=val["lifetime"])

            self.particleList.append(particle)

        self.solar_mode = True

        return self.particleList

    def print_particle_list(self, lst=None):
        for elem in lst:
            print(elem.coordinates)

        print("-----")
Пример #5
0
class Enviroment(SimulationEnviroment):
    '''
    Creates a map of the vehicle and its surroding enviroment. This map is used
    by the planner to avoid collision.

    This might be expanded later with a SLAM.
    '''
    def __init__(self, vehicle, mapRadius=80):
        self.bodies = []
        self.mapRadius = mapRadius
        self.centerBody = Body.fromVehicle(vehicle)
        self.centerBodyLine = None
        self.centerBodyArrow = None
        self.vehicle = vehicle
        self.radiusCircle = None
        self.bodyLines = []  # might be better changing this to a dict
        self.bodyArrows = []  # as to avoid having to keep bodies on track

    def addBody(self, body):
        if (body not in self.bodies
                and self.centerBody.getDistance(body) <= self.mapRadius):
            self.bodies.append(body)

    def lidarScan(self):
        for lidar in self.vehicle.lidarArray:
            lidar.updateRays()
            lidar.rayTracing(self.bodies)

    def update(self, t):
        bodiesToRemove = []
        for idx in range(len(self.bodies)):
            body = self.bodies[idx]
            body.updateStates(t)
            if (self.centerBody.getDistance(body) > self.mapRadius):
                bodiesToRemove.append(idx)

#        for removeIdx in bodiesToRemove:
#            del self.bodies[removeIdx]

        orientation = self.vehicle.getOrientation()
        pos = self.vehicle.getPos()
        vel = self.vehicle.getVelocity()
        acc = self.vehicle.getAcc()
        omega = self.vehicle.getOmega()

        self.centerBody.setStates(pos[0], pos[1], vel, orientation, t)
        self.centerBody.setAcceleration(acc)
        self.centerBody.setOmega(omega)

    def createPlot(self, fig=None, ax=None):
        self.timeOfLastPlot = -1

        if (fig is None):
            self.fig = plt.figure()
        else:
            self.fig = fig

        if (ax is None):
            self.ax = self.fig.add_subplot(111)
        else:
            self.ax = ax

#        for lidar in self.vehicle.lidarArray:
        pm = [
            pm.coords if pm is not None else None
            for pm in self.vehicle.lidar.read()
        ]
        bodyLine, = self.ax.plot(pm, 'r-', linewidth=0.1)
        self.bodyLines.append(bodyLine)

        (verticesX, verticesY) = self.centerBody.getDrawingVertex()
        self.centerBodyLine, = self.ax.plot(verticesX, verticesY, 'r')
        self.centerBodyArrow = Arrow(
            self.centerBody.x,
            self.centerBody.y,
            0.1 * self.centerBody.v * cos(self.centerBody.orientation),
            0.1 * self.centerBody.v * sin(self.centerBody.orientation),
            color='c')
        self.ax.add_patch(self.centerBodyArrow)

        self.radiusCircle = Circle((self.centerBody.x, self.centerBody.y),
                                   self.mapRadius,
                                   color='k',
                                   linestyle=':',
                                   fill=False)
        self.ax.add_patch(self.radiusCircle)

        self.ax.set_xlim([
            self.centerBody.x - self.mapRadius * 1.1,
            self.centerBody.x + self.mapRadius * 1.1
        ])
        self.ax.set_ylim([
            self.centerBody.y - self.mapRadius * 1.1,
            self.centerBody.y + self.mapRadius * 1.1
        ])
        self.ax.set_xlabel('Distance X')
        self.ax.set_ylabel('Distance Y')

    def plot(self, draw=True):
        #        for idx in range(len(self.vehicle.lidarArray)):

        idx = 0
        lidar = self.vehicle.lidar
        pm_x = [(self.centerBody.x, pm.xy[0][0]) if pm is not None else None
                for pm in lidar.read()]
        pm_y = [(self.centerBody.y, pm.xy[1][0]) if pm is not None else None
                for pm in lidar.read()]

        bodyLine = self.bodyLines[idx]
        bodyLine.set_ydata(pm_y)
        bodyLine.set_xdata(pm_x)

        (verticesX, verticesY) = self.centerBody.getDrawingVertex()
        self.centerBodyLine.set_ydata(verticesY)
        self.centerBodyLine.set_xdata(verticesX)

        self.centerBodyArrow.remove()
        self.centerBodyArrow = Arrow(
            self.centerBody.x,
            self.centerBody.y,
            0.1 * self.centerBody.v * cos(self.centerBody.orientation),
            0.1 * self.centerBody.v * sin(self.centerBody.orientation),
            color='c')
        self.ax.add_patch(self.centerBodyArrow)

        self.radiusCircle.remove()
        self.radiusCircle = Circle((self.centerBody.x, self.centerBody.y),
                                   self.mapRadius,
                                   color='k',
                                   linestyle=':',
                                   fill=False)
        self.ax.add_patch(self.radiusCircle)

        self.ax.set_xlim([
            self.centerBody.x - self.mapRadius * 1.1,
            self.centerBody.x + self.mapRadius * 1.1
        ])
        self.ax.set_ylim([
            self.centerBody.y - self.mapRadius * 1.1,
            self.centerBody.y + self.mapRadius * 1.1
        ])

        if (draw):
            self.fig.canvas.draw()
            plt.pause(0.001)
Пример #6
0
class SimulationEnviroment(object):
    '''
    Creates a map of the vehicle and its surroding enviroment. This map is used
    by the planner to avoid collision.

    This might be expanded later with a SLAM.
    '''
    def __init__(self, centerBody, mapRadius=80):
        self.bodies = []
        self.mapRadius = mapRadius
        self.centerBody = centerBody
        self.centerBodyLine = None
        self.centerBodyArrow = None
        self.radiusCircle = None
        self.bodyLines = []  # might be better changin g this to a dict
        self.bodyArrows = []  # as to avoid having to keep bodies on track
        self.lidarArray = []

    def addLIDAR(self, lidar):
        self.lidarArray.append(lidar)

    def getPointMap(self):
        pm = []
        for lidar in self.lidarArray:
            pm.extend(lidar.pointMap)

        return pm

    def lidarScan(self):
        for lidar in self.lidarArray:
            lidar.updateRays()
            lidar.rayTracing(self.bodies)

    def addBody(self, body):
        if (body not in self.bodies):
            self.bodies.append(body)

    def update(self, t):
        for b in self.bodies:
            b.updateStates(t)

#        prevPos = self.centerBody.getPosition()
#        prevOrientation = self.centerBody.getOrientation()
#        self.centerBody.updateStates(t)
        pos = (self.centerBody.x, self.centerBody.y)
        #        delta_x, delta_y = (currPos[0] - prevPos[0], currPos[1] - prevPos[1])
        #        delta_theta = self.centerBody.getOrientation() - prevOrientation
        for lidar in self.lidarArray:
            lidar.setPose(pos, 0)

        self.lidarScan()


#        self.centerBody.update(t)

    def createPlot(self, fig=None, ax=None):
        self.timeOfLastPlot = -1

        if (fig is None):
            self.fig = plt.figure()
        else:
            self.fig = fig

        if (ax is None):
            self.ax = self.fig.add_subplot(111)
        else:
            self.ax = ax

        for b in self.bodies:
            (verticesX, verticesY) = b.getDrawingVertex()
            bodyLine, = self.ax.plot(verticesX, verticesY, 'k')
            self.bodyLines.append(bodyLine)
            directionArrow = Arrow(b.x,
                                   b.y,
                                   0.1 * b.v * cos(b.orientation),
                                   0.1 * b.v * sin(b.orientation),
                                   color='c')
            self.bodyArrows.append(directionArrow)
            self.ax.add_patch(directionArrow)

        (verticesX, verticesY) = self.centerBody.getDrawingVertex()
        self.centerBodyLine, = self.ax.plot(verticesX, verticesY, 'r')
        self.centerBodyArrow = Arrow(
            self.centerBody.x,
            self.centerBody.y,
            0.1 * b.v * cos(self.centerBody.orientation),
            0.1 * b.v * sin(self.centerBody.orientation),
            color='c')
        self.ax.add_patch(self.centerBodyArrow)

        self.radiusCircle = Circle((self.centerBody.x, self.centerBody.y),
                                   self.mapRadius,
                                   color='k',
                                   linestyle=':',
                                   fill=False)
        self.ax.add_patch(self.radiusCircle)

        self.ax.set_xlim([
            self.centerBody.x - self.mapRadius * 1.1,
            self.centerBody.x + self.mapRadius * 1.1
        ])
        self.ax.set_ylim([
            self.centerBody.y - self.mapRadius * 1.1,
            self.centerBody.y + self.mapRadius * 1.1
        ])
        self.ax.set_xlabel('Distance X')
        self.ax.set_ylabel('Distance Y')

    def plot(self, draw=True):
        for idx in range(len(self.bodies)):
            b = self.bodies[idx]
            (verticesX, verticesY) = b.getDrawingVertex()
            bodyLine = self.bodyLines[idx]
            bodyLine.set_ydata(verticesY)
            bodyLine.set_xdata(verticesX)

            directionArrow = self.bodyArrows[idx]
            directionArrow.remove()

            directionArrow = Arrow(b.x,
                                   b.y,
                                   0.1 * b.v * cos(b.orientation),
                                   0.1 * b.v * sin(b.orientation),
                                   color='c')
            self.ax.add_patch(directionArrow)
            self.bodyArrows[idx] = directionArrow

        (verticesX, verticesY) = self.centerBody.getDrawingVertex()
        self.centerBodyLine.set_ydata(verticesY)
        self.centerBodyLine.set_xdata(verticesX)

        self.centerBodyArrow.remove()
        self.centerBodyArrow = Arrow(
            self.centerBody.x,
            self.centerBody.y,
            0.1 * self.centerBody.v * cos(self.centerBody.orientation),
            0.1 * self.centerBody.v * sin(self.centerBody.orientation),
            color='c')
        self.ax.add_patch(self.centerBodyArrow)

        self.radiusCircle.remove()
        self.radiusCircle = Circle((self.centerBody.x, self.centerBody.y),
                                   self.mapRadius,
                                   color='k',
                                   linestyle=':',
                                   fill=False)
        self.ax.add_patch(self.radiusCircle)

        self.ax.set_xlim([
            self.centerBody.x - self.mapRadius * 1.1,
            self.centerBody.x + self.mapRadius * 1.1
        ])
        self.ax.set_ylim([
            self.centerBody.y - self.mapRadius * 1.1,
            self.centerBody.y + self.mapRadius * 1.1
        ])

        if (draw):
            self.fig.canvas.draw()
            plt.pause(0.001)
Пример #7
0
class BikeTrailer(object):
    def __init__(self,
                 theta=0.0,
                 x_0=0.0,
                 y_0=0.0,
                 lengthTractor=4.0,
                 lengthTrailer=10.0,
                 tailDistance=0.5):
        self.tractor = Bike(theta,
                            x_0,
                            y_0,
                            acc=1.0,
                            dPhi=1.0 * pi / 180.0,
                            v=0.0,
                            phi=0.0,
                            length=lengthTractor,
                            tailDistance=tailDistance)

        self.trailer = Bike(theta,
                            self.tractor.x - cos(self.tractor.orientation) *
                            (self.tractor.length + self.tractor.tailDistance),
                            self.tractor.y - sin(self.tractor.orientation) *
                            (self.tractor.length + self.tractor.tailDistance),
                            acc=1.0,
                            dPhi=1.0 * pi / 180.0,
                            v=0.0,
                            phi=0.0,
                            length=lengthTrailer,
                            tailDistance=tailDistance)

        # handling plot
        self.plotRefreshRate = 2  # seconds
        self.fig = None
        self.timeOfLastPlot = -self.plotRefreshRate

        self.tractorFront = None
        self.trailerFront = None
        self.tractorLine = None
        self.trailerLine = None
        self.directionArrow = None

    def setNoise(self, errorPos, errorPhi, errorOrientation, errorVelocity):
        self.tractor.setNoise(errorPos, errorPhi, errorOrientation,
                              errorVelocity)
        self.trailer.setNoise(errorPos, errorPhi, errorOrientation,
                              errorVelocity)

    def update_posture(self, X):
        l_1 = self.tractor.length
        l_off = self.tractor.tailDistance

        x_1, y_1, delta_1, delta_2 = X

        x_2 = x_1 - (l_1 + l_off) * cos(delta_1)
        y_2 = y_1 - (l_1 + l_off) * sin(delta_1)

        self.tractor.set_pose(delta_1, x_1, y_1)
        self.trailer.set_pose(delta_2, x_2, y_2)

    def getStates(self):
        return [
            self.tractor.x, self.tractor.y, self.tractor.orientation,
            self.trailer.orientation
        ]

    def setStates(self, tractorX, tractorY, tractorOrientation,
                  trailerOrientation):
        self.tractor.x = tractorX
        self.tractor.y = tractorY
        self.tractor.orientation = tractorOrientation
        self.trailer.orientation = trailerOrientation

    def move(self, finalTime):
        X0 = self.getStates()
        self.tractor.resetTime()

        X = integrate.odeint(self.diff, X0, [0, finalTime])

        self.update_posture(X[-1])

        return X

    def update(self, finalTime):
        self.move(finalTime)

    def diff(self, X, t):
        delta_1 = X[2]
        delta_2 = X[3]
        self.update_posture(X)
        dt = t - self.tractor.lastUpdate
        self.tractor.updateStates(dt)
        self.tractor.lastUpdate = t

        phi_1 = self.tractor.phi
        v_1 = self.tractor.v

        l_1 = self.tractor.length
        l_2 = self.trailer.length
        l_off = self.tractor.tailDistance

        theta_1 = delta_1 + phi_1
        dDelta_1 = (1.0 / l_1) * (v_1 * sin(phi_1))

        if (abs(phi_1) > 0.0):
            self.radius = l_1 / sin(phi_1)
            self.tractor.acc_cent = v_1 * v_1 / self.radius
        else:
            self.tractor.acc_cent = 0.0

        alpha = delta_1 - delta_2

        c_1 = v_1 * sin(phi_1)
        c_2 = v_1 * cos(phi_1)
        c_3 = sin(alpha)
        c_4 = cos(alpha)

        dDelta_2 = (1 / l_2) * (c_2 * c_3) - (l_off / (l_1 * l_2)) * c_1 * c_4

        dX_1 = v_1 * cos(theta_1)
        dY_1 = v_1 * sin(theta_1)

        self.setStates(dX_1, dY_1, dDelta_1, dDelta_2)

        if (t - self.timeOfLastPlot >= self.plotRefreshRate):
            self.plot()
            self.timeOfLastPlot = t

        return [dX_1, dY_1, dDelta_1, dDelta_2]

    '''
    def printStatus(self):
        if(sys.version_info.major == 3):
            print('Tractor pose')
            self.tractor.printStatus()

            print('Trailer pose')
            self.trailer.printStatus()

            print('Velocity')
            print(self.tractor.cruiseControl.v)

            print('angle')
            print(self.tractor.cruiseControl.phi)
        else:
            print 'Tractor pose'
            self.tractor.printStatus()

            print 'Trailer pose'
            self.trailer.printStatus()

            print 'Velocity'
            print self.tractor.cruiseControl.v

            print 'angle'
            print self.tractor.cruiseControl.phi
    '''

    def createPlot(self, fig=None, ax=None):
        self.timeOfLastPlot = -1

        if (fig is None):
            self.fig = plt.figure()
        else:
            self.fig = fig

        if (ax is None):
            self.ax = self.fig.add_subplot(111)
        else:
            self.ax = ax

        self.tractorFront, = self.ax.plot(self.tractor.x,
                                          self.tractor.y,
                                          'r*',
                                          label='Tractor Front')
        self.tractorLine, = self.ax.plot([self.tractor.x, self.trailer.x],
                                         [self.tractor.y, self.trailer.y],
                                         'k',
                                         label='Tractor Body')
        self.trailerFront, = self.ax.plot(self.trailer.x,
                                          self.trailer.y,
                                          'm*',
                                          label='Trailer Front')
        self.trailerLine, = self.ax.plot([
            self.trailer.x,
            self.trailer.x - self.trailer.length * cos(self.trailer.length)
        ], [
            self.trailer.y,
            self.trailer.y - self.trailer.length * sin(self.trailer.length)
        ],
                                         'b',
                                         label='Trailer Body')
        self.directionArrow = Arrow(
            self.tractor.x,
            self.tractor.y,
            0.1 * self.tractor.v *
            cos(self.tractor.orientation + self.tractor.phi),
            0.1 * self.tractor.v *
            sin(self.tractor.orientation + self.tractor.phi),
            color='c',
            label='Wheel Direction')
        self.ax.add_patch(self.directionArrow)
        self.ax.set_xlim([-10, 10])
        self.ax.set_ylim([-10, 10])
        self.ax.set_xlabel('Distance X')
        self.ax.set_ylabel('Distance Y')
        self.ax.legend()

    def plot(self, draw=True):
        self.tractorFront.set_ydata(self.tractor.y)
        self.tractorFront.set_xdata(self.tractor.x)
        self.tractorLine.set_ydata([self.tractor.y, self.trailer.y])
        self.tractorLine.set_xdata([self.tractor.x, self.trailer.x])
        self.directionArrow.remove()
        self.directionArrow = Arrow(
            self.tractor.x,
            self.tractor.y,
            0.1 * self.tractor.v *
            cos(self.tractor.orientation + self.tractor.phi),
            0.1 * self.tractor.v *
            sin(self.tractor.orientation + self.tractor.phi),
            color='c')
        self.ax.add_patch(self.directionArrow)

        self.trailerFront.set_ydata(self.trailer.y)
        self.trailerFront.set_xdata(self.trailer.x)

        x_4 = self.trailer.x - (self.trailer.length + self.trailer.tailDistance
                                ) * cos(self.trailer.orientation)
        y_4 = self.trailer.y - (self.trailer.length + self.trailer.tailDistance
                                ) * sin(self.trailer.orientation)
        self.trailerLine.set_ydata([y_4, self.trailer.y])
        self.trailerLine.set_xdata([x_4, self.trailer.x])

        self.ax.set_xlim([self.trailer.x - 10, self.trailer.x + 10])
        self.ax.set_ylim([self.trailer.y - 10, self.trailer.y + 10])

        if (draw):
            self.fig.canvas.draw()
            plt.pause(0.001)