예제 #1
0
파일: lidar.py 프로젝트: TedSYt/DonkeyX
class BreezySLAM(object):
    '''
    https://github.com/simondlevy/BreezySLAM
    '''
    def __init__(self, MAP_SIZE_PIXELS=500, MAP_SIZE_METERS=10):
        from breezyslam.algorithms import RMHC_SLAM
        from breezyslam.sensors import Laser

        laser_model = Laser(scan_size=360,
                            scan_rate_hz=10.,
                            detection_angle_degrees=360,
                            distance_no_detection_mm=12000)
        MAP_QUALITY = 5
        self.slam = RMHC_SLAM(laser_model, MAP_SIZE_PIXELS, MAP_SIZE_METERS,
                              MAP_QUALITY)

    def run(self, distances, angles, map_bytes):

        self.slam.update(distances, scan_angles_degrees=angles)
        x, y, theta = self.slam.getpos()

        if map_bytes is not None:
            self.slam.getmap(map_bytes)

        #print('x', x, 'y', y, 'theta', norm_deg(theta))
        return x, y, deg2rad(norm_deg(theta))

    def shutdown(self):
        pass
예제 #2
0
def main():
    # Connect to Lidar unit
    lidar = Lidar(LIDAR_DEVICE)

    # Create an RMHC SLAM object with a laser model and optional robot model
    slam = RMHC_SLAM(LaserModel(), MAP_SIZE_PIXELS, MAP_SIZE_METERS)

    # Set up a SLAM display
    viz = MapVisualizer(MAP_SIZE_PIXELS, MAP_SIZE_METERS, 'SLAM')

    # Initialize an empty trajectory
    trajectory = []

    # Initialize empty map
    mapbytes = bytearray(MAP_SIZE_PIXELS * MAP_SIZE_PIXELS)

    # Create an iterator to collect scan data from the RPLidar
    iterator = lidar.iter_scans()

    # We will use these to store previous scan in case current scan is inadequate
    previous_distances = None
    previous_angles = None

    # First scan is crap, so ignore it
    next(iterator)

    while True:

        # Extract (quality, angle, distance) triples from current scan
        items = [item for item in next(iterator)]

        # Extract distances and angles from triples
        distances = [item[2] for item in items]
        print(distances)
        angles = [item[1] for item in items]

        # Update SLAM with current Lidar scan and scan angles if adequate
        if len(distances) > MIN_SAMPLES:
            slam.update(distances, scan_angles_degrees=angles)
            previous_distances = distances.copy()
            previous_angles = angles.copy()

        # If not adequate, use previous
        elif previous_distances is not None:
            slam.update(previous_distances,
                        scan_angles_degrees=previous_angles)

        # Get current robot position
        x, y, theta = slam.getpos()

        # Get current map bytes as grayscale
        slam.getmap(mapbytes)

        # Display map and robot pose, exiting gracefully if user closes it
        if not viz.display(x / 1000., y / 1000., theta, mapbytes):
            exit(0)

    # Shut down the lidar connection
    lidar.stop()
    lidar.disconnect()
예제 #3
0
class Lidar(BaseLidar):

    def __init__(self, on_map_change):
        super().__init__(on_map_change=on_map_change)
        self.lidar = RPLidar(os.getenv('LIDAR_DEVICE', SLAM["LIDAR_DEVICE"]))
        self.slam = RMHC_SLAM(RPLidarA1(), SLAM['MAP_SIZE_PIXELS'], SLAM['MAP_SIZE_METERS'])
        self.map_size_pixels = SLAM['MAP_SIZE_PIXELS']
        self.trajectory = []
        self.mapbytes = bytearray(SLAM['MAP_SIZE_PIXELS'] * SLAM['MAP_SIZE_PIXELS'])
        self.prev_checksum = 0

    def stop(self):
        # await super().stop()
        self.lidar.stop()
        self.lidar.stop_motor()
        self.lidar.disconnect()

    def run(self):
        try:
            previous_distances = None
            previous_angles = None
            iterator = self.lidar.iter_scans()
            next(iterator)

            while True:
                items = [(q, 360 - angle, dist) for q, angle, dist in next(iterator)]
                distances = [item[2] for item in items]
                angles = [item[1] for item in items]

                if len(distances) > SLAM['MIN_SAMPLES']:
                    self.slam.update(distances, scan_angles_degrees=angles)
                    previous_distances = distances.copy()
                    previous_angles = angles.copy()
                elif previous_distances is not None:
                    self.slam.update(previous_distances, scan_angles_degrees=previous_angles)

                x, y, theta = self.slam.getpos()
                self.trajectory.append((x, y))

                self.slam.getmap(self.mapbytes)

                for coords in self.trajectory:
                    x_mm, y_mm = coords

                    x_pix = mm2pix(x_mm)
                    y_pix = mm2pix(y_mm)

                    self.mapbytes[y_pix * SLAM['MAP_SIZE_PIXELS'] + x_pix] = 0
                checksum = sum(self.mapbytes)
                if self.on_map_change and checksum != self.prev_checksum:
                    # print(checksum)
                    x = Image.frombuffer('L', (self.map_size_pixels, self.map_size_pixels), self.mapbytes, 'raw', 'L', 0, 1)
                    bytes_img = io.BytesIO()
                    x.save(bytes_img, format='PNG')
                    self.on_map_change(bytearray(bytes_img.getvalue()))
                self.prev_checksum = checksum
        except Exception as e:
            print(e)
        finally:
            self.stop()
예제 #4
0
def main():
    print "initiating engine..."
    seed = 9999
    dequeueCount = 0
    time_start = time.time()
    targetProcess = "node server.js"
    targetSignal = signal.SIGUSR1
    serverMinTimeDelay = 5

    pid = getpid(targetProcess)
    slam = RMHC_SLAM(MinesLaser(), MAP_SIZE_PIXELS, MAP_SIZE_METERS, random_seed=seed) \
        if seed \
        else Deterministic_SLAM(MinesLaser(), MAP_SIZE_PIXELS, MAP_SIZE_METERS)
    trajectory = []
    
    while time.time() - time_start < 600:
        time_thisLoop = time.time()
        if not q.empty():
            while (not q.empty()):
                slam.update(q.get())
                dequeueCount = dequeueCount + 1
                x_mm, y_mm, theta_degrees = slam.getpos()    
                trajectory.append((x_mm, y_mm))
                                        
            # Create a byte array to receive the computed maps
            mapbytes = bytearray(MAP_SIZE_PIXELS * MAP_SIZE_PIXELS)
            
            # Get map from this batch
            slam.getmap(mapbytes)
            
            # Put trajectory into map as black pixels
            for coords in trajectory:
                        
                x_mm, y_mm = coords
                                       
                x_pix = mm2pix(x_mm)
                y_pix = mm2pix(y_mm)
                                                                                                      
                mapbytes[y_pix * MAP_SIZE_PIXELS + x_pix] = 0;
                            
            # Save map and trajectory as PNG file
            image = Image.frombuffer('L', (MAP_SIZE_PIXELS, MAP_SIZE_PIXELS), mapbytes, 'raw', 'L', 0, 1)
            image.save("../../webgui/images/" + "map" + ".png")
            print "map created after {} scans".format(dequeueCount)

            # Try to tell the server
            if pid == False:
                print "failure: no server pid"
                pid = getpid(targetProcess)
            else:
                try:
                    os.kill(int(pid),targetSignal)
                    print "success: signal sent to server"
                except OSError:
                    print "error: whoops, just lost the pid"
                    pid = getpid(targetProcess)

            # give the server at least serverMinTimeDelay seconds to catch up
            while time.time() - time_thisLoop < serverMinTimeDelay:
                ()
예제 #5
0
class SLAM:
    """
    takes a breezyslam laser object and a flag to determine the
    slam algorithms that is used.
    """
    def __init__(self, lidar_turret):
        self.map_size_pixels = 1600
        self.map_size_meters = 50
        self.trajectory = []
        self.mapbytes = bytearray(self.map_size_pixels * self.map_size_pixels)

        self.laser = Laser(lidar_turret.point_cloud_size, 2.4,
                           lidar_turret.detection_angle_degrees, 0)
        self.algorithm = RMHC_SLAM(self.laser, self.map_size_pixels,
                                   self.map_size_meters)

    def update(self, timestamp, point_cloud, velocity):
        self.algorithm.update(point_cloud, velocity)

        x_mm, y_mm, theta_degrees = self.algorithm.getpos()
        self.trajectory.append((x_mm, y_mm))

        self.algorithm.getmap(self.mapbytes)

    def make_image(self, image_name, image_format="pgm"):
        self.algorithm.getmap(self.mapbytes)
        for coords in self.trajectory:
            x_mm, y_mm = coords

            x_pix = self.mm2pix(x_mm)
            y_pix = self.mm2pix(y_mm)

            self.mapbytes[y_pix * self.map_size_pixels + x_pix] = 0

        if image_format == "pgm":
            pgm_save(image_name + "." + image_format, self.mapbytes,
                     (self.map_size_pixels, self.map_size_pixels))
        else:
            image = Image.frombuffer(
                'L', (self.map_size_pixels, self.map_size_pixels),
                self.mapbytes, 'raw', 'L', 0, 1)
            image.save(image_name + "." + image_format)

    def get_pos(self):
        return self.algorithm.getpos()

    def mm2pix(self, mm):
        return int(mm / (self.map_size_meters * 1000 / self.map_size_pixels))
예제 #6
0
    def __init__(self):
        from breezyslam.algorithms import RMHC_SLAM

        lidar = MyLidarModel()

        mapbytes = bytearray(800 * 800)

        slam = RMHC_SLAM(lidar, 800, 35)

        while True:
            scan = readLidar()

            slam.update(scan)

            x, y, theta = slam.getpos(scan)

            slam.getmap(mapbytes)
예제 #7
0
파일: slam.py 프로젝트: bierschi/SLAM_algo
def main():

    lidar = Lidar(device='/dev/ttyACM0')
    slam = RMHC_SLAM(LaserModel(), map_size_pixels=MAP_SIZE_PIXELS, map_size_meters=MAP_SIZE_METERS)

    display = SlamShow(MAP_SIZE_PIXELS, MAP_SIZE_METERS*1000/MAP_SIZE_PIXELS, 'SLAM')
    #image_thread = threading.Thread(target=save_image, args=[display])
    #image_thread.start()
    mapbytes = bytearray(MAP_SIZE_PIXELS * MAP_SIZE_PIXELS)

    while True:
        slam.update(lidar.getScan())
        x, y, theta = slam.getpos()
        #print(x, y, theta)
        slam.getmap(mapbytes)
        display.displayMap(mapbytes)
        display.setPose(x, y, theta)
        #display.save_image()
        display.save_pgm(mapbytes)
        if not display.refresh():
            exit(0)
예제 #8
0
def main():
    seed = 9999
    runCount = 0
    dequeueCount = 0
    slam = RMHC_SLAM(MinesLaser(), MAP_SIZE_PIXELS, MAP_SIZE_METERS, random_seed=seed) \
           if seed \
           else Deterministic_SLAM(MinesLaser(), MAP_SIZE_PIXELS, MAP_SIZE_METERS)
    trajectory = []
    while dequeueCount < 1000:
        time.sleep(10)
        if q.empty() == False:
            while (q.empty() == False):
                slam.update(q.get())
                #print "%i" %dequeueCount
                dequeueCount = dequeueCount + 1
                x_mm, y_mm, theta_degrees = slam.getpos()
                trajectory.append((x_mm, y_mm))

            # Create a byte array to receive the computed maps
            mapbytes = bytearray(MAP_SIZE_PIXELS * MAP_SIZE_PIXELS)

            # Get final map
            slam.getmap(mapbytes)

            # Put trajectory into map as black pixels
            for coords in trajectory:

                x_mm, y_mm = coords

                x_pix = mm2pix(x_mm)
                y_pix = mm2pix(y_mm)

                mapbytes[y_pix * MAP_SIZE_PIXELS + x_pix] = 0

            # Save map and trajectory as PNG file
            image = Image.frombuffer('L', (MAP_SIZE_PIXELS, MAP_SIZE_PIXELS),
                                     mapbytes, 'raw', 'L', 0, 1)
            #image.save('map%i.png' %runCount)
            #image.save("/home/card/webgui/images/" + "map" + str(dequeueCount) + ".png")
            image.save("/home/card/webgui/images/" + "map" + ".png")
예제 #9
0
 def update(self, scan_mm, velocities=None, command=0):
     """
     Calculates the amount of usefull pixels perframe and stores the time.
     scan_mm: new scan
     velocities: velocitie data
     command: next to perform command
     :param velocities:
     :param command:
     :param scan_mm:
     """
     errors = 0
     self.values = len(scan_mm)
     for x in range(0, len(scan_mm)):
         if scan_mm[x] == 0:
             errors += 1 
     self.error = float(errors) / len(scan_mm)
     if velocities == None:
         self.time = None
     else:
         self.time = velocities[2]
     self.command = command
     RMHC_SLAM.update(self, scan_mm, velocities)
예제 #10
0
 def update(self, scan_mm, velocities=None, command=0):
     """
     Calculates the amount of usefull pixels perframe and stores the time.
     scan_mm: new scan
     velocities: velocitie data
     command: next to perform command
     :param velocities:
     :param command:
     :param scan_mm:
     """
     errors = 0
     self.values = len(scan_mm)
     for x in range(0, len(scan_mm)):
         if scan_mm[x] == 0:
             errors += 1
     self.error = float(errors) / len(scan_mm)
     if velocities == None:
         self.time = None
     else:
         self.time = velocities[2]
     self.command = command
     RMHC_SLAM.update(self, scan_mm, velocities)
예제 #11
0
    # Create an RMHC SLAM object with a laser model and optional robot model
    slam = RMHC_SLAM(LaserModel(), MAP_SIZE_PIXELS, MAP_SIZE_METERS)

    # Set up a SLAM display
    display = SlamShow(MAP_SIZE_PIXELS, MAP_SIZE_METERS*1000/MAP_SIZE_PIXELS, 'SLAM')

    # Initialize an empty trajectory
    trajectory = []

    # Initialize empty map
    mapbytes = bytearray(MAP_SIZE_PIXELS * MAP_SIZE_PIXELS)

    while True:

        # Update SLAM with current Lidar scan, using first element of (scan, quality) pairs
        slam.update([pair[0] for pair in lidar.getScan()])

        # Get current robot position
        x, y, theta = slam.getpos()

        # Get current map bytes as grayscale
        slam.getmap(mapbytes)

        display.displayMap(mapbytes)

        display.displayRobot((x, y, theta))

        trajectory.append((x,y))

        # Display trajectory
        display.displayTrajectory(trajectory)
예제 #12
0
def slamThread():
    global SLAMrot
    global SLAMvel

    # Connect to Lidar unit
    lidar = Lidar(LIDAR_DEVICE)

    # Create an RMHC SLAM object with a laser model and optional robot model
    slam = RMHC_SLAM(LaserModel(), MAP_SIZE_PIXELS, MAP_SIZE_METERS)

    # Set up a SLAM display
    viz = MapVisualizer(MAP_SIZE_PIXELS, MAP_SIZE_METERS, 'SLAM')

    # Initialize an empty trajectory
    trajectory = []

    # Initialize empty map
    mapbytes = bytearray(MAP_SIZE_PIXELS * MAP_SIZE_PIXELS)

    # Create an iterator to collect scan data from the RPLidar
    iterator = lidar.iter_scans()

    # We will use these to store previous scan in case current scan is inadequate
    previous_distances = None
    previous_angles    = None

    # First scan is crap, so ignore it
    next(iterator)

    # start time
    start_time = time.time()
    
    prevTime = start_time
    print("start")

    while True:

        # Extract (quality, angle, distance) triples from current scan
        items = [item for item in next(iterator)]

        # Extract distances and angles from triples
        distances = [item[2] for item in items]
        angles    = [item[1] for item in items]

        # Update SLAM with current Lidar scan and scan angles if adequate
        if len(distances) > MIN_SAMPLES:
            slam.update(distances, pose_change = ( (SLAMvel, SLAMrot, time.time() - prevTime)),scan_angles_degrees=angles)
            prevTime = time.time()
            previous_distances = copy.copy(distances)
            previous_angles    = copy.copy(angles)
            print("updated - if")
            print((SLAMvel, SLAMrot, time.time() - prevTime))

        # If not adequate, use previous
        elif previous_distances is not None:
            slam.update(previous_distances, pose_change = ( (SLAMvel, SLAMrot, time.time() - prevTime)),scan_angles_degrees=previous_angles)
            prevTime = time.time()
            print("updated - else")
            print((SLAMvel, SLAMrot, time.time() - prevTime))


        # Get current robot position
        x, y, theta = slam.getpos()
        # Add new position to trajectory
        trajectory.append((x, y))

        # Get current map bytes as grayscale
        slam.getmap(mapbytes)

        if(time.time() - start_time > 30):
    # Put trajectory into map as black pixels
            for coords in trajectory:
                        
                x_mm, y_mm = coords
                                       
                x_pix = mm2pix(x_mm)
                y_pix = mm2pix(y_mm)
                                                                                                      
                mapbytes[y_pix * MAP_SIZE_PIXELS + x_pix] = 0;

            pgm_save('ok.pgm', mapbytes, (MAP_SIZE_PIXELS, MAP_SIZE_PIXELS))
            exit(0)
예제 #13
0
async def main():
    async with websockets.connect(SERVER_URL,
        max_size=None,
        max_queue=None,
        ping_interval=None,
        ping_timeout=None) as websocket:
        # Connect to Lidar unit
        lidar = Lidar(LIDAR_DEVICE)

        # Create an RMHC SLAM object with a laser model and optional robot model
        slam = RMHC_SLAM(LaserModel(), MAP_SIZE_PIXELS, MAP_SIZE_METERS)

        # Initialize an empty trajectory
        trajectory = []

        # Initialize empty map
        mapbytes = bytearray(MAP_SIZE_PIXELS * MAP_SIZE_PIXELS)

        # Create an iterator to collect scan data from the RPLidar
        iterator = lidar.iter_scans()

        # We will use these to store previous scan in case current scan is inadequate
        previous_distances = None
        previous_angles = None

        # First scan is crap, so ignore it
        next(iterator)

        while True:
            # Extract (quality, angle, distance) triples from current scan
            items = [item for item in next(iterator)]

            # Extract distances and angles from triples
            distances = [item[2] for item in items]
            angles = [item[1] for item in items]

            # Update SLAM with current Lidar scan and scan angles if adequate
            if len(distances) > MIN_SAMPLES:
                slam.update(distances, scan_angles_degrees=angles)
                previous_distances = distances.copy()
                previous_angles = angles.copy()

            # If not adequate, use previous
            elif previous_distances is not None:
                slam.update(previous_distances, scan_angles_degrees=previous_angles)

            # Get current robot position
            x, y, theta = slam.getpos()

            # Get current map bytes as grayscale
            slam.getmap(mapbytes)

            while True:
                try:
                    await websocket.send(struct.pack(STRUCT_FORMAT, x, y, theta, mapbytes))
                except:

                else:
                    break

        # Shut down the lidar connection
        lidar.stop()
        lidar.disconnect()
예제 #14
0
class LidarGraph(Thread):
    def __init__(self, port):
        Thread.__init__(self)
        self.scan = None
        self.running = False
        self.port = port

    def setup(self):
        GPIO.output(23, GPIO.HIGH)
        sleep(1)
        self.lidar = RPLidar(self.port)
        self.lidar.connect()
        self.lidar.start_motor()

        self.slam = RMHC_SLAM(LaserModel(),
                              MAP_SIZE_PIXELS,
                              MAP_SIZE_METERS,
                              map_quality=1,
                              max_search_iter=50)
        self.mapbytes = bytearray(MAP_SIZE_PIXELS * MAP_SIZE_PIXELS)

        success = False
        while success is not True:
            try:
                self.iterator = self.lidar.iter_scans()
                next(self.iterator)  #first scan is shit
                success = True
            except Exception as e:
                print('retrying')
                print(e)
                sleep(0.5)

    def restart(self):
        self.stop()
        self.go()

    def go(self):
        self.setup()
        self.running = True

    def stop(self):
        print('Stopping')
        self.running = False
        self.lidar.stop_motor()
        self.lidar.disconnect()
        del self.lidar
        GPIO.output(23, GPIO.LOW)  # turn off lidar relay
        sleep(1)

    def update(self):
        self.scan = next(self.iterator)
        self.offsets = np.array([(np.radians(meas[1]), meas[2])
                                 for meas in self.scan])
        self.intens = np.array([meas[0] for meas in self.scan])

        # BreezySLAM
        previous_distances = None
        previous_angles = None

        items = [item for item in self.scan]
        distances = [item[2] for item in items]
        angles = [item[1] for item in items]

        print(str(len(distances)) + ' distances')

        # Update SLAM with current Lidar scan and scan angles if adequate
        if len(distances) > MIN_SAMPLES:
            print('updating slam')
            self.slam.update(distances, scan_angles_degrees=angles)
            previous_distances = distances.copy()
            previous_angles = angles.copy()

        # If not adequate, use previous
        elif previous_distances is not None:
            self.slam.update(previous_distances,
                             scan_angles_degrees=previous_angles)

        # Get current robot position
        x, y, theta = self.slam.getpos()

        print('x ' + str(x) + 'y ' + str(y) + 'theta ' + str(theta))

        # Get current map bytes as grayscale
        self.slam.getmap(self.mapbytes)
        sleep(0.05)  #gather more samples?

    def data(self):
        if self.running != True:
            return {'intens': [], 'offsets': []}

        return {
            'intens': self.intens.tolist(),
            'offsets': self.offsets.tolist()
        }

    def get_map(self):
        # slam map
        return self.mapbytes

    def run(self):
        print('run')

        iterator = None

        while True:

            if self.running:
                try:
                    self.update()
                    print('Updated')
                except Exception as e:
                    print('Exception during update')
                    print(e)
예제 #15
0
        # Extract distances and angles from triples
        distances = [item[2] for item in items]
        angles = [item[1] for item in items]

        print(len(distances))

        # Update SLAM with current Lidar scan and scan angles if adequate
        if len(distances) > MIN_SAMPLES:

            # First interpolate to get 360 angles from 0 through 359, and corresponding distances
            f = interp1d(angles, distances, fill_value='extrapolate')
            distances = list(f(np.arange(360)))  # slam.update wants a list

            # Then update with interpolated distances
            slam.update(distances)

            # Store interplated distances for next time
            previous_distances = distances.copy()

        # If not adequate, use previous
        elif previous_distances is not None:
            slam.update(previous_distances)

        # Get current robot position
        x, y, theta = slam.getpos()

        # Get current map bytes as grayscale
        slam.getmap(mapbytes)

    # Shut down the lidar connection
예제 #16
0
def main():
	    
    # Bozo filter for input args
    if len(argv) < 4:
        print('Usage:   %s <dataset> <output_dir> <use_odometry> [random_seed]' % argv[0])
        print('Example: %s exp2 output 1 9999' % argv[0])
        exit(1)
    
    # Grab input args
    dataset = argv[1]
    use_odometry = True if int(argv[2]) else False
    seed =  int(argv[3])
    output_filename = argv[4]
    draw_trajectory = True if int(argv[5]) else False
    
    print("dataset: " + dataset)
    print("use_odometry: " + str(use_odometry))
    print("seed: " + str(seed))
    print("output_filename: " + output_filename)
    print("draw_trajectory: " + str(draw_trajectory))

	# Load the data from the file, ignoring timestamps
    _, lidars, odometries = load_data('.', dataset)
    
    # Build a robot model if we want odometry
    robot = Robot() if use_odometry else None
        
    # Create a CoreSLAM object with laser params and optional robot object
    slam = RMHC_SLAM(Laser(), MAP_SIZE_PIXELS, MAP_SIZE_METERS, random_seed=seed) \
           if seed \
           else Deterministic_SLAM(Laser(), MAP_SIZE_PIXELS, MAP_SIZE_METERS)
           
    # Report what we're doing
    nscans = len(lidars)
    print('Processing %d scans with%s odometry / with%s particle filter...' % \
        (nscans, \
         '' if use_odometry else 'out', '' if seed else 'out'))
    progbar = ProgressBar(0, nscans, 80)
    
    # Start with an empty trajectory of positions
    trajectory = []

    # Start timing
    start_sec = time()
    
    # Loop over scans    
    for scanno in range(nscans):
    
        if use_odometry:
                  
            # Convert odometry to pose change (dxy_mm, dtheta_degrees, dt_seconds)
            velocities = robot.computePoseChange(odometries[scanno])
                                 
            # Update SLAM with lidar and velocities
            slam.update(lidars[scanno], velocities)
            
        else:
        
            # Update SLAM with lidar alone
            slam.update(lidars[scanno])

        # Get new position
        x_mm, y_mm, theta_degrees = slam.getpos()    
        
        # Add new position to trajectory
        trajectory.append((x_mm, y_mm))
        
        # Tame impatience
        progbar.updateAmount(scanno)
        stdout.write('\r%s' % str(progbar))
        stdout.flush()

    # Report elapsed time
    elapsed_sec = time() - start_sec
    print('\n%d scans in %f sec = %f scans / sec' % (nscans, elapsed_sec, nscans/elapsed_sec))
                    
                                
    # Create a byte array to receive the computed maps
    mapbytes = bytearray(MAP_SIZE_PIXELS * MAP_SIZE_PIXELS)
    
    # Get final map    
    slam.getmap(mapbytes)
    
    if(draw_trajectory):

        # Put trajectory into map as black pixels
        for coords in trajectory:
                
            x_mm, y_mm = coords
                               
            x_pix = mm2pix(x_mm)
            y_pix = mm2pix(y_mm)
                                                                                              
            mapbytes[y_pix * MAP_SIZE_PIXELS + x_pix] = 0;
                    
    # Save map and trajectory as PGM file    
    pgm_save(output_filename, mapbytes, (MAP_SIZE_PIXELS, MAP_SIZE_PIXELS))
예제 #17
0
    # First scan is crap, so ignore it
    next(iterator)

    while True:

        # Extract (quality, angle, distance) triples from current scan
        items = [item for item in next(iterator)]

        # Extract distances and angles from triples
        distances = [item[2] for item in items]
        angles    = [item[1] for item in items]

        # Update SLAM with current Lidar scan and scan angles if adequate
        if len(distances) > MIN_SAMPLES:
            slam.update(distances, scan_angles_degrees=angles)
            previous_distances = distances.copy()
            previous_angles    = angles.copy()

        # If not adequate, use previous
        elif previous_distances is not None:
            slam.update(previous_distances, scan_angles_degrees=previous_angles)

        # Get current robot position
        x, y, theta = slam.getpos()

        # Get current map bytes as grayscale
        slam.getmap(mapbytes)

        # Display map and robot pose, exiting gracefully if user closes it
        if not viz.display(x/1000., y/1000., theta, mapbytes):
예제 #18
0
파일: tmptest.py 프로젝트: azaroth08/Flora
from Methods import *
from LidarClass import *
from breezyslam.algorithms import RMHC_SLAM
import pandas as pd
from numpy import degrees
import matplotlib.pyplot as plt
Laser = YDlidarx2()
slam2 = RMHC_SLAM(Laser, 1000, 40)
mapbytes = bytearray(1000 * 1000)


class Flora:
    pass


Flora.MSP = 1000
P = [(0, 0, 0), (1000, 0, 1)]
for i in range(2):
    a = str(i)
    ld = pd.read_csv('/home/pi/Flora/FloraMainCode/scans/LD0' + a + '.csv')
    tmpd = ld.range * 1000
    tmpa = degrees(ld.angle)
    slam2.update(tmpd.tolist(), scan_angles_degrees=tmpa.tolist())
    slam2.getmap(mapbytes)
    Flora.mapbytes = mapbytes
    #slam2.position.x_mm = 10000+1000
AA = ByteMapToNP(Flora)
plt.imshow(AA)
plt.show()
예제 #19
0
    # First scan is crap, so ignore it
    next(iterator)

    while True:

        # Extract (quality, angle, distance) triples from current scan
        items = [item for item in next(iterator)]

        # Extract distances and angles from triples
        distances = [item[2] for item in items]
        angles = [item[1] for item in items]

        # Update SLAM with current Lidar scan and scan angles if adequate
        if len(distances) > MIN_SAMPLES:
            slam.update(distances, scan_angles_degrees=angles)
            previous_distances = distances.copy()
            previous_angles = angles.copy()

        # If not adequate, use previous
        elif previous_distances is not None:
            slam.update(previous_distances,
                        scan_angles_degrees=previous_angles)

        # Get current robot position
        x, y, theta = slam.getpos()

        # Get current map bytes as grayscale
        slam.getmap(mapbytes)

        # Display the map
예제 #20
0
파일: rpslam.py 프로젝트: zlite/BreezySLAM
    while True:

        # Extrat (quality, angle, distance) triples from current scan
        items = [item for item in next(iterator)]

        # Extract distances and angles from triples
        distances = [item[2] for item in items]
        angles    = [item[1] for item in items]

        # Interpolate to get 360 angles from 0 through 359, and corresponding distances
        f = interp1d(angles, distances, fill_value='extrapolate')
        distances = list(f(np.arange(360))) # slam.update wants a list

        # Update SLAM with current Lidar scan, using third element of (quality, angle, distance) triples
        slam.update(distances)

        # Get current robot position
        x, y, theta = slam.getpos()

        # Get current map bytes as grayscale
        slam.getmap(mapbytes)

        display.displayMap(mapbytes)

        display.setPose(x, y, theta)

        # Break on window close
        if not display.refresh():
            break
예제 #21
0
class Slam(Node):
    """
    SLAM NODE
    This node is in charge of receiving data from the LIDAR and creating a map of the environment
    while locating the robot in the map.

    INPUT
    - Bottle detected by the Neuron (to be removed soon)
    - Lidar detections

    OUTPUT
    - Robot position: /robot_pos
    - Map as a byte array: /world_map
    (this map can be interpred using the map_utils.py package !)
    """
    def __init__(self):
        super().__init__('slam_node')

        # Create second subscription (SLAM)
        self.subscription2 = self.create_subscription(
            LidarData, 'lidar_data', self.listener_callback_lidar, 100)
        self.subscription2  # prevent unused variable warning

        # Create third subscription (Motor speeds to compute robot pose change)
        self.subscription3 = self.create_subscription(
            MotorsSpeed, 'motors_speed', self.listener_callback_motorsspeed,
            1000)
        self.subscription3  # prevent unused variable warning

        # create subscription to control map_quality
        self.slam_control_sub = self.create_subscription(
            String, 'slam_control', self.slam_control_callback, 1000)

        # Create publisher for the position of the robot, and for the map
        self.publisher_position = self.create_publisher(
            Position, 'robot_pos', 10)
        self.publisher_map = self.create_publisher(Map, 'world_map', 10)

        # Initialize parameters for slam
        laser = LaserModel(detection_margin=DETECTION_MARGIN,
                           offset_mm=OFFSET_MM)
        self.slam = RMHC_SLAM(laser,
                              MAP_SIZE_PIXELS,
                              MAP_SIZE_METERS,
                              map_quality=MAP_QUALITY,
                              hole_width_mm=OBSTACLE_WIDTH_MM,
                              x0_mm=X0,
                              y0_mm=Y0,
                              theta0=0,
                              sigma_xy_mm=DEFAULT_SIGMA_XY_MM)
        self.trajectory = []
        self.mapbytes = bytearray(MAP_SIZE_PIXELS * MAP_SIZE_PIXELS)
        self.previous_distances = None
        self.previous_angles = None
        self.robot_pose_change = np.array([0.0, 0.0, 0.0])
        self.is_map_quality_high = True

        # DEBUG parameters
        self.map_index = 0
        self.previous_pos = (0, 0, 0)
        self.s = time.time()
        print("SLAM is starting")

    def slam_control_callback(self, msg):
        """Called to changed the map quality
        """
        if msg.data == "save_state":
            print("Slam is saving current state")
            self.last_valid_map = self.mapbytes.copy()
            self.last_valid_pos = self.slam.getpos()
        elif msg.data == "recover_state":
            # METHOD 1
            self.slam.setmap(self.last_valid_map)
            ##  self.slam.setpos(self.last_valid_pos)
        elif msg.data == "freeze":
            self.last_valid_map = self.mapbytes.copy()
            self.last_valid_pos = self.slam.getpos()
        elif msg.data == "unfreeze":
            self.slam.setmap(self.last_valid_map)
            # self.slam.setpos(self.last_valid_pos)
        return
        ##########################
        print("changing quality")
        if self.is_map_quality_high:
            #self.previous_map = self.mapbytes.copy()
            self.slam.map_quality = 0
            self.slam.sigma_xy_mm = 5 * DEFAULT_SIGMA_XY_MM
        else:
            #self.slam.setmap(self.previous_map)
            self.slam.map_quality = MAP_QUALITY
            self.slam.sigma_xy_mm = DEFAULT_SIGMA_XY_MM
        self.is_map_quality_high = not self.is_map_quality_high

    def listener_callback_motorsspeed(self, msg):
        """
        Must compute the robot pose change since the last time the data was collected from the motor
        The input are the motors speed and the time change.

        Documentation of the SLAM library says :
            "pose_change is a tuple (dxy_mm, dtheta_degrees, dt_seconds) computed from odometry"
        """
        dx_left = msg.RADIUS * msg.left * (0.1047) * msg.time_delta
        dx_right = msg.RADIUS * msg.right * (0.1047) * msg.time_delta
        delta_r = 1 / 2 * (dx_left + dx_right)  # [mm]
        delta_d = -(dx_right - dx_left)
        delta_theta = np.arctan(delta_d / msg.LENGTH) * 57.2958  # [deg]
        self.robot_pose_change += [delta_r, delta_theta, msg.time_delta]

    def listener_callback_lidar(self, msg):
        # transform angles to $FORMAT1
        angles = np.array(msg.angles)
        angles = list(
            (angles + 180) % 360)  # because LIDAR is facing the robot
        distances = list(msg.distances)

        # Update SLAM with current Lidar scan and scan angles if adequate
        if len(distances) > MIN_SAMPLES:
            e = time.time()
            self.s = e
            self.slam.update(distances,
                             scan_angles_degrees=angles,
                             pose_change=tuple(self.robot_pose_change))
            # self.analyse_odometry()
            self.robot_pose_change = np.array([0.0, 0.0, 0.0])
            self.previous_distances = distances.copy()
            self.previous_angles = angles.copy()
        elif self.previous_distances is not None:
            # If not adequate, use previous
            print("Slam NOT updating")
            self.slam.update(self.previous_distances,
                             scan_angles_degrees=self.previous_angles)

        # Get current robot position and current map bytes as grayscale
        x, y, theta = self.slam.getpos()
        self.slam.getmap(self.mapbytes)

        # Send topics
        pos = Position()
        pos.x = float(x)
        pos.y = float(y)
        pos.theta = float(theta)
        self.publisher_position.publish(pos)
        map_message = Map()
        map_message.map_data = self.mapbytes
        map_message.index = self.map_index
        self.publisher_map.publish(map_message)
        print("Map sent: ", self.map_index)
        self.map_index += 1

    # debug functions here (do NOT call them on real runs)

    def analyse_odometry(self):
        """Compare the odometry resuls with the change in position according to SLAM. 
        For this function to work, self.robot_pose_change must be set to something different than zero.
        And the variabe self.previous_pos must exist
        """
        x, y, theta = self.slam.getpos()
        x_old, y_old, theta_old = self.previous_pos
        dr = np.sqrt((x - x_old)**2 + (y - y_old)**2)
        dtheta = theta - theta_old
        print("-------")
        print("SLAM     change of pos: {:.3f}  {:.3f}".format(dr, dtheta))
        print("Odometry change of pos: {:.3f}  {:.3f} ".format(
            self.robot_pose_change[0], self.robot_pose_change[1]))
        self.previous_pos = (x, y, theta)

    def find_lidar_range(self, distances, angles):
        """Finds the critical angles of the LIDAR and prints them. 
        Careful, this function works (currently) only with the previous angles format.
        """
        (i1, i2) = lidar_utils.get_valid_lidar_range(distances=distances,
                                                     angles=angles,
                                                     n_points=10)
        print('indexes : {} : {} with angles {} - {}'.format(
            i1, i2, angles[i1], angles[i2]))
예제 #22
0
from roboviz import MapVisualizer
       
if __name__ == '__main__':

    # Connect to Lidar unit
    lidar = Lidar(LIDAR_DEVICE)

    # Create an RMHC SLAM object with a laser model and optional robot model
    slam = RMHC_SLAM(LaserModel(), MAP_SIZE_PIXELS, MAP_SIZE_METERS)

    # Set up a SLAM display
    viz = MapVisualizer(MAP_SIZE_PIXELS, MAP_SIZE_METERS, 'SLAM')

    # Initialize empty map
    mapbytes = bytearray(MAP_SIZE_PIXELS * MAP_SIZE_PIXELS)

    while True:

        # Update SLAM with current Lidar scan
        slam.update(lidar.getScan())

        # Get current robot position
        x, y, theta = slam.getpos()

        # Get current map bytes as grayscale
        slam.getmap(mapbytes)

        # Display map and robot pose, exiting gracefully if user closes it
        if not viz.display(x/1000., y/1000., theta, mapbytes):
            exit(0)
예제 #23
0
def slam(currentProgram):

    trajectory = []

    # Connect to Lidar unit
    try:
        lidar = Lidar(PORT0)
        currentProgram.roombaPort = PORT1
        iterator = lidar.iter_scans(1000)
        lidar.stop()
        next(iterator)
        print("Lidar 0, Roomba 1")
    except:
        print("Roomba 0, Lidar 1")
        lidar.stop()
        lidar.disconnect()
        lidar = Lidar(PORT1)
        currentProgram.roombaPort = PORT0
        iterator = lidar.iter_scans(1000)
        lidar.stop()
        next(iterator)

    # Create an RMHC SLAM object with a laser model and optional robot model
    slam = RMHC_SLAM(LaserModel(), MAP_SIZE_PIXELS, MAP_SIZE_METERS)
    trajectory = []
    previous_distances = None
    previous_angles = None
    # start time
    start_time = time.time()
    prevTime = start_time

    trigger_start = -100

    while (not currentProgram.stop):

        SLAMvel = currentProgram.SLAMvals[0]
        SLAMrot = currentProgram.SLAMvals[1]

        # Extract (quality, angle, distance) triples from current scan
        items = [item for item in next(iterator)]

        # Extract distances and angles from triples
        distances = [item[2] for item in items]
        angles = [item[1] for item in items]

        l =  list(zip(angles,distances))

        filtered = list(filter(lambda e: (e[0]>=45 and e[0]<=135) and e[1]<300 , l))
        # s = sorted(l, key = lambda e: e[0])
        if (len(filtered) > constants.POINTS_THRESHOLD) and (time.time()-trigger_start >5):
            currentProgram.programStatus = constants.Status.LIDAR_OBSTACLE
            topleft = list(filter(lambda e: (e[0]>=105 and e[0]<=135)  , filtered))
            front = list(filter(lambda e: (e[0]>=75 and e[0]<=105)  , filtered))
            topright = list(filter(lambda e: (e[0]>=45 and e[0]<=75)  , filtered))

            if (len(topleft) > 2):
                currentProgram.obstacleLocation[0] = 1
            if (len(front) > 2):
                currentProgram.obstacleLocation[1] = 1   
            if (len(topright) > 2):
                currentProgram.obstacleLocation[2] = 1  
            trigger_start = time.time()

        # Update SLAM with current Lidar scan and scan angles if adequate
        if len(distances) > MIN_SAMPLES:
            # print("using speeds ", SLAMvel, SLAMrot)
            dt = time.time() - prevTime
            slam.update(distances, pose_change=(
                (SLAMvel*dt, SLAMrot*dt, dt)), scan_angles_degrees=angles)
            prevTime = time.time()
            previous_distances = copy.copy(distances)
            previous_angles = copy.copy(angles)
            # print("updated - if")

        # If not adequate, use previous
        elif previous_distances is not None:
            # print("using speeds ", SLAMvel, SLAMrot)
            dt = time.time() - prevTime
            slam.update(previous_distances, pose_change=(
                (SLAMvel*dt, SLAMrot*dt, dt)), scan_angles_degrees=previous_angles)
            prevTime = time.time()
            # print("updated - else")

        # Get current robot position
        x, y, theta = slam.getpos()
        [x_pix, y_pix] = [mm2pix(x), mm2pix(y)]
        currentProgram.robot_pos = [
            y_pix // constants.CHUNK_SIZE, x_pix // constants.CHUNK_SIZE]
        # print("robot_pos - ",x_pix // constants.CHUNK_SIZE,y_pix // constants.CHUNK_SIZE, theta)
        # Get current map bytes as grayscale
        slam.getmap(currentProgram.mapbytes)

    # Shut down the lidar connection
    pgm_save('ok.pgm', currentProgram.mapbytes,
             (MAP_SIZE_PIXELS, MAP_SIZE_PIXELS))
    lidar.stop()
    lidar.disconnect()
예제 #24
0
for d in mapdata['data'][0]:

    ranges = [r * 1000 for r in d[0, 0]['Ranges'].reshape(360)]
    angles = [180 * rad / 3.14159 for rad in d[0, 0]['Angles'].reshape(360)]

    scans.append([ranges, angles])

for i in np.arange(0, len(scans), 1):

    # Extract distances and angles from triples
    distances = scans[i][0]
    angles = scans[i][1]

    # Update SLAM with current Lidar scan and scan angles if adequate
    slam.update(distances, scan_angles_degrees=angles)

    # Get current robot position
    x_mm, y_mm, theta_degrees = slam.getpos()
    trajectory.append((x_mm, y_mm))


def mm2pix(mm):
    return int(mm / (MAP_SIZE_METERS * 1000. / MAP_SIZE_PIXELS))


slam.getmap(mapbytes)
for coords in trajectory:
    x_mm, y_mm = coords
    x_pix = mm2pix(x_mm)
    y_pix = mm2pix(y_mm)
async def main():

    #---------------------------------------
    # Setup Lidar unit and SLAM
    #---------------------------------------
    # Connect to Lidar unit
    lidar = nanoLidar.nanoLidar(host)
    # get firmware info
    print("Lidar Version:")
    print(lidar.getInfo())

    # Create an RMHC SLAM object with a laser model and optional robot model
    slam = RMHC_SLAM(LaserModel(), MAP_SIZE_PIXELS, MAP_SIZE_METERS)

    # Set up a SLAM display
    display = SlamShow(MAP_SIZE_PIXELS,
                       MAP_SIZE_METERS * 1000 / MAP_SIZE_PIXELS, 'SLAM')

    # Initialize an empty trajectory
    trajectory = []

    # Initialize empty map
    mapbytes = bytearray(MAP_SIZE_PIXELS * MAP_SIZE_PIXELS)

    #---------------------------------------
    # Setup Robot unit
    #---------------------------------------
    # Connect to robot unit
    robot = robotPosition.robotPosition(host)
    robot.powerOn()
    # get firmware info
    print("Chassis Version:")
    print(robot.getInfo())

    #---------------------------------------
    # main loop
    #---------------------------------------
    run = True
    while run:

        # Update SLAM with current Lidar scan, using first element of (scan, quality) pairs
        slam.update([pair[0] for pair in lidar.getScan()])

        # Get current robot position
        x, y, theta = slam.getpos()

        # Get current map bytes as grayscale
        slam.getmap(mapbytes)

        display.displayMap(mapbytes)

        display.setPose(x, y, theta)

        # Exit on ESCape
        key = display.refresh()
        if key != None and (key & 0x1A):
            run = False

        # Movement control
        distance = int(input("Distance [mm]: "))
        angle = int(input("Turn angle [degrees]: "))
        (xp, yp, theta_deg, theta_rad) = robot.setPosition(distance, angle)
        if int(input("Carry on (1/0): ")) == 0:
            run = False

    # power off stepper motors
    robot.powerOff()
예제 #26
0
        # Extract distances and angles from triples
        distances = [item[2] for item in items]
        angles    = [item[1] for item in items]

        print(len(distances))

        # Update SLAM with current Lidar scan and scan angles if adequate
        if len(distances) > MIN_SAMPLES:

            # First interpolate to get 360 angles from 0 through 359, and corresponding distances
            f = interp1d(angles, distances, fill_value='extrapolate')
            distances = list(f(np.arange(360))) # slam.update wants a list

            # Then update with interpolated distances
            slam.update(distances)

            # Store interplated distances for next time
            previous_distances = distances.copy()

        # If not adequate, use previous
        elif previous_distances is not None:
            slam.update(previous_distances)

        # Get current robot position
        x, y, theta = slam.getpos()

        # Get current map bytes as grayscale
        slam.getmap(mapbytes)

        # Display map and robot pose, exiting gracefully if user closes it
예제 #27
0
class Map(Thread):

    MAP_SIZE_PIXELS         = 1000
    MAP_SIZE_METERS         = 7
    LIDAR_DEVICE            = '/dev/ttyACM0'
    THRESH_DETECTION = 100

    RAW_ANGLE = np.pi/4
    LIDAR_POS = np.array([140,140])



    def __init__(self):
        Thread.__init__(self)
        #self.lidar = Lidar(LIDAR_DEVICE)
        self.slam = RMHC_SLAM(LaserModel(), MAP_SIZE_PIXELS, MAP_SIZE_METERS, map_quality=50, hole_width_mm=200, max_search_iter=10000)
        self.N = 0
        self.bot_pos = [[1500, 1300]]
        self.bot_ori = [0]
        self.state = True

    def run(self):
        self.i = 0
        x_th = 1500
        y_th = 1300

        while(self.state):
            if(self.i<10):
                y_th +=35
            elif(self.i<33):
                x_th -= 45
            elif(self.i<45):
                y_th -= 35
            else:
                y_th -= 10
                x_th += 10
            # Update SLAM with current Lidar scan
            #self.slam.update(self.lidar.getScan())
            data = getHokuyoData([x_th, y_th],
                                 -self.i*5/180.0*np.pi, [np.array([[0, 2000, 2000, 0],[0, 0, 3000, 3000]]),
                                 np.array([[650, 1350, 1350, 650],[1450, 1450, 1550, 1550]]),
                                 np.array([[1500, 1600, 1600, 1500],[1000, 1000, 1100, 1100]]),
                                 np.array([[1000+200*np.cos(k*10/180*np.pi) for k in range(0,36)],
                                           [2500+200*np.sin(k*10/180*np.pi) for k in range(0,36)]])], 0)

            list = data[1].tolist()
            if(len(list) == 682):
                self.slam.update(list, [0,0,0.1])

            # Get current robot position
            y, x, theta = self.slam.getpos()
            x-=3500
            y-=3500
            x = -x
            #y-=198
            x+=1500
            y+=1300

            #angle = self.RAW_ANGLE + theta*3.1415/180
            #R = np.array([[np.cos(angle), -np.sin(angle)],[np.sin(angle), np.cos(angle)]])
            #pos = R.dot(np.array([x,y]))
            pos = np.array([x,y])

            self.bot_pos.append(pos)
            self.bot_ori.append(theta)

            self.i += 1

    def stop(self):
        self.state = False
예제 #28
0
def main():
	    
    # Bozo filter for input args
    if len(argv) < 3:
        print('Usage:   %s <dataset> <use_odometry> <random_seed>' % argv[0])
        print('Example: %s exp2 1 9999' % argv[0])
        exit(1)
    
    # Grab input args
    dataset = argv[1]
    use_odometry  =  True if int(argv[2]) else False
    seed =  int(argv[3]) if len(argv) > 3 else 0
    
	# Load the data from the file    
    lidars, odometries = load_data('.', dataset)
    
    # Build a robot model if we want odometry
    robot = Rover() if use_odometry else None
        
    # Create a CoreSLAM object with laser params and optional robot object
    slam = RMHC_SLAM(MinesLaser(), MAP_SIZE_PIXELS, MAP_SIZE_METERS, random_seed=seed) \
           if seed \
           else Deterministic_SLAM(URG04(), MAP_SIZE_PIXELS, MAP_SIZE_METERS)
           
    # Report what we're doing
    nscans = len(lidars)
    print('Processing %d scans with%s odometry / with%s particle filter...' % \
        (nscans, \
         '' if use_odometry else 'out', '' if seed else 'out'))
    progbar = ProgressBar(0, nscans, 80)
    
    # Start with an empty trajectory of positions
    trajectory = []

    # Start timing
    start_sec = time()
    
    # Loop over scans    
    for scanno in range(nscans):
    
        if use_odometry:
                  
            # Convert odometry to velocities
            velocities = robot.computeVelocities(odometries[scanno])
                                 
            # Update SLAM with lidar and velocities
            slam.update(lidars[scanno], velocities)
            
        else:
        
            # Update SLAM with lidar alone
            slam.update(lidars[scanno])
                    
        # Get new position
        x_mm, y_mm, theta_degrees = slam.getpos()    
        
        # Add new position to trajectory
        trajectory.append((x_mm, y_mm))
        
        # Tame impatience
        progbar.updateAmount(scanno)
        stdout.write('\r%s' % str(progbar))
        stdout.flush()

    # Report elapsed time
    elapsed_sec = time() - start_sec
    print('\n%d scans in %f sec = %f scans / sec' % (nscans, elapsed_sec, nscans/elapsed_sec))
                    
                                
    # Create a byte array to receive the computed maps
    mapbytes = bytearray(MAP_SIZE_PIXELS * MAP_SIZE_PIXELS)
    
    # Get final map    
    slam.getmap(mapbytes)
    
    # Put trajectory into map as black pixels
    for coords in trajectory:
                
        x_mm, y_mm = coords
                               
        x_pix = mm2pix(x_mm)
        y_pix = mm2pix(y_mm)
                                                                                              
        mapbytes[y_pix * MAP_SIZE_PIXELS + x_pix] = 0;
                    
    # Save map and trajectory as PGM file    
    pgm_save('%s.pgm' % dataset, mapbytes, (MAP_SIZE_PIXELS, MAP_SIZE_PIXELS))
예제 #29
0
def run_slam(LIDAR_DEVICE, MAP_SIZE_PIXELS, MAP_SIZE_METERS, mapbytes,
             posbytes, odometry, command, state, STATES):
    MIN_SAMPLES = 200

    # Connect to Lidar unit
    lidar = start_lidar(LIDAR_DEVICE)
    # Create an RMHC SLAM object with a laser model and optional robot model
    slam = RMHC_SLAM(LaserModel(),
                     MAP_SIZE_PIXELS,
                     MAP_SIZE_METERS,
                     map_quality=_DEFAULT_MAP_QUALITY,
                     hole_width_mm=_DEFAULT_HOLE_WIDTH_MM,
                     random_seed=None,
                     sigma_xy_mm=_DEFAULT_SIGMA_XY_MM,
                     sigma_theta_degrees=_DEFAULT_SIGMA_THETA_DEGREES,
                     max_search_iter=_DEFAULT_MAX_SEARCH_ITER)
    # Initialize empty map
    mapbytes_ = bytearray(MAP_SIZE_PIXELS * MAP_SIZE_PIXELS)
    # Send command to start scan
    lidar.start_scan()
    # We will use these to store previous scan in case current scan is inadequate
    previous_distances = None
    previous_angles = None

    pose_change = (0, 0, 0)
    pose_change_find = (0, 0, 0)
    iter_times = 1
    while command[0] != b'qa':

        # read a scan
        items = lidar.scan()

        # Extract distances and angles from triples
        distances = [item[2] for item in items]
        angles = [item[1] for item in items]

        if state[0] == STATES['stop']:
            if command[0] == b'lm':
                mapbytes_find = mapbytes

                pose_change_find = find_slam_pos(lidar, MAP_SIZE_PIXELS,
                                                 MAP_SIZE_METERS,
                                                 mapbytes_find,
                                                 pose_change_find,
                                                 iter_times / 2.0, slam)
                iter_times = iter_times + 1.0
                print(pose_change_find)
                pose_change = pose_change_find
                pose_change_find = (0, 0, 0)
                '''
                items = lidar.scan()

        # Extract distances and angles from triples
                distances = [item[2] for item in items]
                angles    = [item[1] for item in items]

                slam.update(distances, pose_change, scan_angles_degrees=angles)
                '''

                if (iter_times > 10):
                    command[0] = b'w'
                    print(slam)

                    slam.setmap(mapbytes_find)
                    pose_change = pose_change_find
                    pose_change_find = (0, 0, 0)
                    print('ennnnnnnnnnnnnnnnnnd')
                    print(pose_change)
                    iter_times = 1

        else:

            # Update SLAM with current Lidar scan and scan angles if adequate
            if len(distances) > MIN_SAMPLES:
                slam.update(distances, pose_change, scan_angles_degrees=angles)
                previous_distances = distances.copy()
                previous_angles = angles.copy()

            # If not adequate, use previous
            elif previous_distances is not None:
                slam.update(previous_distances,
                            pose_change,
                            scan_angles_degrees=previous_angles)

            #pass the value into point_cal function
            global point_a, point_b
            global current_theta_o
            # Get current robot position
            x, y, theta = slam.getpos()
            current_theta_o = theta
            point_a = x - 5000
            point_b = y - 5000

            # Calculate robot position in the map
            xbytes = int(x / 1000. / MAP_SIZE_METERS * MAP_SIZE_PIXELS)
            ybytes = int(y / 1000. / MAP_SIZE_METERS * MAP_SIZE_PIXELS)
            # Update robot position
            posbytes[xbytes + ybytes * MAP_SIZE_PIXELS] = 255
            #print('LIDAR::', command[0], x,y,theta)
            pose_change = (odometry[0], odometry[1] / np.pi * 180, odometry[2])
            # Get current map bytes as grayscale
            slam.getmap(mapbytes_)
            # Update map
            mapbytes[:] = mapbytes_

    # Shut down the lidar connection
    lidar.stop()
    lidar.disconnect()

    print('LIDAR::thread ends')
예제 #30
0
    #считаем одометрию для обоих колес
    errorCode, x_left = vrep.simxGetJointPosition(clientID, left_motor_handle,
                                                  vrep.simx_opmode_streaming)
    dx_left = abs(x_left - prev_pos_left)
    prev_pos_left = x_left
    dx_left = (dx_left + math.pi) % (2 * math.pi) - math.pi

    errorCode, x_right = vrep.simxGetJointPosition(clientID,
                                                   right_motor_handle,
                                                   vrep.simx_opmode_streaming)
    dx_right = abs(x_right - prev_pos_right)
    prev_pos_right = x_right
    dx_right = (dx_right + math.pi) % (2 * math.pi) - math.pi

    #обновляем информацию об изменении координат колес, угле между ними и времени
    velocities = robot.computePoseChange(time.time(), abs(dx_left),
                                         abs(dx_right))

    #обновляем карту
    slam.update(scan, velocities)
    #находим позицию робота на ней
    x, y, theta = slam.getpos()
    #получаем карту в виде массива байтов
    slam.getmap(mapbytes)
    #отображаем карту
    if not viz.display(x / 1000., y / 1000., theta, mapbytes):
        exit(0)

print('Simulation finished')
exit(0)
예제 #31
0
while True:
    # Receives raw lidar data
    raw_data = json.loads(socket1.recv())
    raw_data_new = [[i * 1000 for i in raw_data[0:360]]]
    for i in range(360, (len(raw_data))):
        fixed_data_org = [k * 1000 for k in raw_data[i]]
        raw_data_new.append(fixed_data_org)

    raw_data_new = list(raw_data_new)[0]

    # Sends message back to raw data script
    socket1.send_string('Got the raw data: %s ' % raw_data_new)

    # Update SLAM with current Lidar scan
    slam.update(raw_data_new)

    # Get current robot position
    map_x, map_y, map_theta = slam.getpos()
    #print(x, y)

    # Get current map bytes as grayscale
    slam.getmap(mapbytes)

    # Convert byteArray to array containing values 0-255 indicating grayscale colors
    mapping = np.reshape(np.frombuffer(mapbytes, dtype=np.uint8),
                         (MAP_SIZE_PIXELS, MAP_SIZE_PIXELS))

    # Convert array containing grayscale colors to 0's for open space and 1's for obstacles
    obstacleMap = convertToObstacleMap(mapping)
예제 #32
0
    lidar = Lidar(LIDAR_DEVICE)

    # Create an RMHC SLAM object with a laser model and optional robot model
    slam = RMHC_SLAM(LaserModel(), MAP_SIZE_PIXELS, MAP_SIZE_METERS)

    # Set up a SLAM display
    display = SlamShow(MAP_SIZE_PIXELS,
                       MAP_SIZE_METERS * 1000 / MAP_SIZE_PIXELS, 'SLAM')

    # Initialize empty map
    mapbytes = bytearray(MAP_SIZE_PIXELS * MAP_SIZE_PIXELS)

    while True:

        # Update SLAM with current Lidar scan
        slam.update(lidar.getScan())

        # Get current robot position
        x, y, theta = slam.getpos()

        # Get current map bytes as grayscale
        slam.getmap(mapbytes)

        display.displayMap(mapbytes)

        display.setPose(x, y, theta)

        # Exit on ESCape
        key = display.refresh()
        if key != None and (key & 0x1A):
            exit(0)
예제 #33
0
    # Connect to Lidar unit
    lidar = LidarReader('/dev/ttyACM1', 115200)

    # Create an RMHC SLAM object with a laser model and optional robot model
    slam = RMHC_SLAM(LaserModel(), MAP_SIZE_PIXELS, MAP_SIZE_METERS)

    # Set up a SLAM display
    viz = MapVisualizer(MAP_SIZE_PIXELS, MAP_SIZE_METERS, 'SLAM')

    # Initialize an empty trajectory
    trajectory = []

    # Initialize empty map
    mapbytes = bytearray(MAP_SIZE_PIXELS * MAP_SIZE_PIXELS)

    while True:

        # Update SLAM with current Lidar scan, using first element of (scan, quality) pairs
        slam.update([pair[0] for pair in lidar.getdata()])

        # Get current robot position
        x, y, theta = slam.getpos()

        # Get current map bytes as grayscale
        slam.getmap(mapbytes)

        # Display map and robot pose, exiting gracefully if user closes it
        if not viz.display(x / 1000., y / 1000., theta, mapbytes):
            exit(0)
예제 #34
0
def main():

    # Bozo filter for input args
    if len(argv) < 3:
        print('Usage:   %s <dataset> <use_odometry> [random_seed]' % argv[0])
        print('Example: %s exp2 1 9999' % argv[0])
        exit(1)

    # Grab input args
    dataset = argv[1]
    use_odometry = True if int(argv[2]) else False
    seed = int(argv[3]) if len(argv) > 3 else 0

    # Load the data from the file, ignoring timestamps
    _, lidars, odometries = load_data('.', dataset)

    # Build a robot model if we want odometry
    robot = Rover() if use_odometry else None

    # Create a CoreSLAM object with laser params and optional robot object
    slam = RMHC_SLAM(MinesLaser(), MAP_SIZE_PIXELS, MAP_SIZE_METERS, random_seed=seed) \
           if seed \
           else Deterministic_SLAM(MinesLaser(), MAP_SIZE_PIXELS, MAP_SIZE_METERS)

    # Report what we're doing
    nscans = len(lidars)
    print('Processing %d scans with%s odometry / with%s particle filter...' % \
        (nscans, \
         '' if use_odometry else 'out', '' if seed else 'out'))
    progbar = ProgressBar(0, nscans, 80)

    # Start with an empty trajectory of positions
    trajectory = []

    # Start timing
    start_sec = time()

    # Loop over scans
    for scanno in range(nscans):

        if use_odometry:

            # Convert odometry to velocities
            velocities = robot.computePoseChange(odometries[scanno])

            # Update SLAM with lidar and velocities
            slam.update(lidars[scanno], velocities)

        else:

            # Update SLAM with lidar alone
            slam.update(lidars[scanno])

        # Get new position
        x_mm, y_mm, theta_degrees = slam.getpos()

        # Add new position to trajectory
        trajectory.append((x_mm, y_mm))

        # Tame impatience
        progbar.updateAmount(scanno)
        stdout.write('\r%s' % str(progbar))
        stdout.flush()

    # Report elapsed time
    elapsed_sec = time() - start_sec
    print('\n%d scans in %f sec = %f scans / sec' %
          (nscans, elapsed_sec, nscans / elapsed_sec))

    # Create a byte array to receive the computed maps
    mapbytes = bytearray(MAP_SIZE_PIXELS * MAP_SIZE_PIXELS)

    # Get final map
    slam.getmap(mapbytes)

    # Pickle the map to a file
    pklname = dataset + '.map'
    print('Writing map to file ' + pklname)
    pickle.dump(mapbytes, open(pklname, 'wb'))
예제 #35
0
class Main():
    def __init__(self):
        self.b = True
        self.MIN_SAMPLES = 20
        while self.b == True:
            try:
                self.init_lidar()
                self.b = False
            except Exception as e:
                print(e)
        self.init_slam()

    def init_lidar(self):
        self.lidar = Lidar('/dev/ttyUSB0')
        self.iterator = self.lidar.iter_scans(1000)
        time.sleep(0.5)
        # First scan is crap, so ignore it
        next(self.iterator)

    def init_slam(self):
        self.MAP_SIZE_PIXELS = cfg.MAP_SIZE_PIXELS
        self.MAP_SIZE_METERS = cfg.MAP_SIZE_METERS
        self.slam = RMHC_SLAM(LaserModel(), self.MAP_SIZE_PIXELS,
                              self.MAP_SIZE_METERS)
        self.mapbytes = bytearray(self.MAP_SIZE_PIXELS * self.MAP_SIZE_PIXELS)

    def img_processing(self, mapimg):
        t_map = ip.thresholding(mapimg)
        d_map = ip.dilation(t_map)
        e_map = ip.erosion(d_map)
        blur = ip.blur(e_map, cfg.MAP_BLUR, t=0)
        return blur
        #cv2.imwrite("map2.jpg", blur)

    def main_loop(self):
        var = 0
        time_total = 0
        total_matches = 0
        max_matches = 0

        while var < 50:
            # Extract (quality, angle, distance) triples from current scan
            items = [item for item in next(self.iterator)]

            # Extract distances and angles from triples
            distances = [item[2] for item in items]
            angles = [item[1] for item in items]

            # Update SLAM with current Lidar scan and scan angles if adequate
            if len(distances) > self.MIN_SAMPLES:

                self.slam.update(distances, scan_angles_degrees=angles)
                self.previous_distances = distances.copy()
                self.previous_angles = angles.copy()

            # If not adequate, use previous
            elif self.previous_distances is not None:
                self.slam.update(self.previous_distances,
                                 scan_angles_degrees=self.previous_angles)

            # Get current robot position
            x, y, theta = self.slam.getpos()

            # Get current map bytes as grayscale
            self.slam.getmap(self.mapbytes)
            mapimg = np.reshape(np.frombuffer(self.mapbytes, dtype=np.uint8),
                                (self.MAP_SIZE_PIXELS, self.MAP_SIZE_PIXELS))

            t1 = time.time()
            blur = self.img_processing(mapimg)
            a, b, matches = ip.find_spot(blur)
            t2 = time.time() - t1

            if matches > max_matches:
                max_matches = matches

            time_total += t2
            total_matches += matches
            var += 1

        avg_time = time_total / var
        avg_matches = total_matches / var

        print("avg_matches: " + str(avg_matches))
        print("max_matches: " + str(max_matches))

        print("avg_time: " + str(avg_time))
예제 #36
0
    # Create an RMHC SLAM object with a laser model and optional robot model
    slam = RMHC_SLAM(LaserModel(), MAP_SIZE_PIXELS, MAP_SIZE_METERS)

    # Set up a SLAM display
    display = MapVisualizer(MAP_SIZE_PIXELS, MAP_SIZE_METERS, 'SLAM')

    # Initialize an empty trajectory
    trajectory = []

    # Initialize empty map
    mapbytes = bytearray(MAP_SIZE_PIXELS * MAP_SIZE_PIXELS)

    while True:

        # Update SLAM with current Lidar scan, using first element of (scan, quality) pairs
        slam.update([pair[0] for pair in lidar.getScan()])

        # Get current robot position
        x, y, theta = slam.getpos()

        # Get current map bytes as grayscale
        slam.getmap(mapbytes)

        # Display map
        display.displayMap(mapbytes)

        # Display pose after converting from mm to meters
        display.setPose(x / 1000., y / 1000., theta)

        # Exit on window close
        if not display.refresh():
예제 #37
0
class Robot:
    def __init__(self, messagequeue):
        # Connect to Lidar unit
        # when initializing the robot object, we first open lidar and start
        # reading data from the lidar
        self.lidar = lidarReader('/dev/mylidar', 115200)
        self.mover = MotorController()

        # Create an RMHC SLAM object with a laser model and optional robot model
        self.slam = RMHC_SLAM(LaserModel(), MAP_SIZE_PIXELS, MAP_SIZE_METERS)
        # Set up a SLAM display
        self.viz = MapVisualizer(MAP_SIZE_PIXELS, MAP_SIZE_METERS, 'SLAM')
        # Initialize empty map
        self.mapbytes = bytearray(MAP_SIZE_PIXELS * MAP_SIZE_PIXELS)
        self.messages = messagequeue

        # All the functions should run in the same process so that the variable can be shared
        self.thread = threading.Thread(target=self.navigate, args=())
        # the main-thread will exit without checking the sub-thread at the end of the main thread.
        # At the same time, all sub-threads with the daemon value of True will end with the main thread, regardless of whether the operation is completed.
        self.thread.daemon = True
        self.navigating = True
        self.thread.start()

    # Construct Map should always run in the main process
    def constructmap(self):
        while True:
            time.sleep(0.0001)
            # Update SLAM with current Lidar scan, using first element of (scan, quality) pairs
            self.slam.update(self.lidar.getdata())
            #print(self.lidar.getdata())
            # Get current robot position
            x, y, theta = self.slam.getpos()
            # Get current map bytes as grayscale
            self.slam.getmap(self.mapbytes)
            # Display map and robot pose, exiting gracefully if user closes it
            if not self.viz.display(x / 1000., y / 1000., theta,
                                    self.mapbytes):
                break

    def navigate(self):
        while self.navigating:
            time.sleep(
                0.01)  # (yield) allowing reading data from the serailport
            if (
                    self.messages.empty()
            ):  # The camera doesn't detect one traffic sign message.empty()
                #if(True): # The camera doesn't detect one traffic sign message.empty()
                front_too_close, left_too_close, right_too_close = False, False, False
                if (self.lidar.angle_180 < 400):
                    front_too_close = True
                left_angle = np.argmin(self.lidar.left_container)
                right_angle = np.argmin(self.lidar.right_container)
                if (self.lidar.left_container[left_angle] < 250):
                    left_too_close = True
                if (self.lidar.right_container[right_angle] < 250):
                    right_too_close = True
                if (front_too_close and left_too_close and right_too_close):
                    self.mover.backward()
                elif (front_too_close):
                    if (self.lidar.angle_270 > self.lidar.angle_90):
                        self.mover.turn_left()
                    else:
                        self.mover.turn_right()
                elif (left_too_close or right_too_close):
                    if (left_too_close):
                        self.mover.turn_right(left_angle)
                    else:
                        self.mover.turn_left(right_angle)
                else:
                    self.mover.forward()
                #print(self.lidar.left_container)
                #print(front_too_close, left_too_close, right_too_close, self.lidar.angle_180)
            else:
                sign = self.messages.get()  # get the detection id
                if (sign == 1):
                    self.mover.stop()
                elif (sign == 2):
                    self.mover.turn_right()
                else:
                    self.mover.turn_left()