Ejemplo n.º 1
0
    def debugOutput(self, segment_list_msg, d_max, phi_max):
        """Creates and publishes debug messages

        Args:
            segment_list_msg (:obj:`SegmentList`): message containing list of filtered segments
            d_max (:obj:`float`): best estimate for d
            phi_max (:obj:``float): best estimate for phi

        """
        if self._debug:

            # Get the segments that agree with the best estimate and publish them
            inlier_segments = self.filter.get_inlier_segments(
                segment_list_msg.segments, d_max, phi_max)
            inlier_segments_msg = SegmentList()
            inlier_segments_msg.header = segment_list_msg.header
            inlier_segments_msg.segments = inlier_segments

            self.pub_seglist_filtered.publish(inlier_segments_msg)

            # Create belief image and publish it
            ml = self.filter.generate_measurement_likelihood(
                segment_list_msg.segments)
            if ml is not None:
                ml_img = self.bridge.cv2_to_imgmsg(
                    np.array(255 * ml).astype("uint8"), "mono8")
                ml_img.header.stamp = segment_list_msg.header.stamp
                self.pub_ml_img.publish(ml_img)
Ejemplo n.º 2
0
    def debugOutput(self, segment_list_msg, d_max, phi_max, timestamp_before_processing):
        """Creates and publishes debug messages

        Args:
            segment_list_msg (:obj:`SegmentList`): message containing list of filtered segments
            d_max (:obj:`float`): best estimate for d
            phi_max (:obj:``float): best estimate for phi
            timestamp_before_processing (:obj:`float`): timestamp dating from before the processing

        """
        if self._debug:
            # Latency of Estimation including curvature estimation
            estimation_latency_stamp = rospy.Time.now() - timestamp_before_processing
            estimation_latency = estimation_latency_stamp.secs + estimation_latency_stamp.nsecs / 1e9
            self.latencyArray.append(estimation_latency)

            if len(self.latencyArray) >= 20:
                self.latencyArray.pop(0)

            # print "Latency of segment list: ", segment_latency
            self.loginfo(f"Mean latency of Estimation:................. {np.mean(self.latencyArray)}")

            # Get the segments that agree with the best estimate and publish them
            inlier_segments = self.filter.get_inlier_segments(segment_list_msg.segments, d_max, phi_max)
            inlier_segments_msg = SegmentList()
            inlier_segments_msg.header = segment_list_msg.header
            inlier_segments_msg.segments = inlier_segments
            self.pub_seglist_filtered.publish(inlier_segments_msg)

            # Create belief image and publish it
            belief_img = self.bridge.cv2_to_imgmsg(
                np.array(255 * self.filter.belief).astype("uint8"), "mono8"
            )
            belief_img.header.stamp = segment_list_msg.header.stamp
            self.pub_belief_img.publish(belief_img)
    def processSegments(self, segment_list_msg):
        if not self.active:
            return
        # Get actual timestamp for latency measurement
        timestamp_now = rospy.Time.now()

        # TODO-TAL double call to param server ... --> see TODO in the readme, not only is it never updated, but it is alwas 0
        # Step 0: get values from server
        if (rospy.get_param('~curvature_res') is not self.curvature_res):
            self.curvature_res = rospy.get_param('~curvature_res')
            self.filter.updateRangeArray(self.curvature_res)

        # Step 1: predict
        current_time = rospy.get_time()
        dt = current_time - self.t_last_update
        v = self.velocity.v
        w = self.velocity.omega

        self.filter.predict(dt=dt, v=v, w=w)
        self.t_last_update = current_time

        # Step 2: update

        self.filter.update(segment_list_msg.segments)

        parking_detected = BoolStamped()
        parking_detected.header.stamp = segment_list_msg.header.stamp
        parking_detected.data = self.filter.parking_detected
        self.pub_parking_detection.publish(parking_detected)

        parking_on = BoolStamped()
        parking_on.header.stamp = segment_list_msg.header.stamp
        parking_on.data = True
        self.pub_parking_on.publish(parking_on)

        if self.active_mode:
            # Step 3: build messages and publish things
            [d_max, phi_max] = self.filter.getEstimate()
            # print "d_max = ", d_max
            # print "phi_max = ", phi_max

            inlier_segments = self.filter.get_inlier_segments(
                segment_list_msg.segments, d_max, phi_max)
            inlier_segments_msg = SegmentList()
            inlier_segments_msg.header = segment_list_msg.header
            inlier_segments_msg.segments = inlier_segments
            self.pub_seglist_filtered.publish(inlier_segments_msg)

            #max_val = self.filter.getMax()
            #in_lane = max_val > self.filter.min_max
            # build lane pose message to send
            lanePose = LanePose()
            lanePose.header.stamp = segment_list_msg.header.stamp
            lanePose.d = d_max[0]
            lanePose.phi = phi_max[0]
            #lanePose.in_lane = in_lane
            # XXX: is it always NORMAL?
            lanePose.status = lanePose.NORMAL

            if self.curvature_res > 0:
                lanePose.curvature = self.filter.getCurvature(
                    d_max[1:], phi_max[1:])

            self.pub_lane_pose.publish(lanePose)

            # TODO-TAL add a debug param to not publish the image !!
            # TODO-TAL also, the CvBridge is re instantiated every time...
            # publish the belief image
            bridge = CvBridge()
            belief_img = bridge.cv2_to_imgmsg(
                np.array(255 * self.filter.beliefArray[0]).astype("uint8"),
                "mono8")
            belief_img.header.stamp = segment_list_msg.header.stamp
            self.pub_belief_img.publish(belief_img)

            # Latency of Estimation including curvature estimation
            estimation_latency_stamp = rospy.Time.now() - timestamp_now
            estimation_latency = estimation_latency_stamp.secs + estimation_latency_stamp.nsecs / 1e9
            self.latencyArray.append(estimation_latency)

            if (len(self.latencyArray) >= 20):
                self.latencyArray.pop(0)

            # print "Latency of segment list: ", segment_latency
            # print("Mean latency of Estimation:................. %s" % np.mean(self.latencyArray))

            # also publishing a separate Bool for the FSM
            in_lane_msg = BoolStamped()
            in_lane_msg.header.stamp = segment_list_msg.header.stamp
            in_lane_msg.data = self.filter.inLane
            if (self.filter.inLane):
                self.pub_in_lane.publish(in_lane_msg)
Ejemplo n.º 4
0
    def processSegments(self, segment_list_msg):
        # Get actual timestamp for latency measurement
        timestamp_now = rospy.Time.now()

        if not self.active:
            return

        # TODO-TAL double call to param server ... --> see TODO in the readme, not only is it never updated, but it is alwas 0
        # Step 0: get values from server
        if (rospy.get_param('~curvature_res') is not self.curvature_res):
            self.curvature_res = rospy.get_param('~curvature_res')
            self.filter.updateRangeArray(self.curvature_res)

        ## #######################################################
        # ########################################################
        # Parameters
        # ########################################################
        lane_width = 0.23  # [m]
        valid_rad = 0.5  # [m]
        lookahead = 0.1  # [m]
        n_test_points = 50
        max_buffer_size = 25

        # ########################################################
        # Process inputs
        # ########################################################
        # Generate an xy list from the data
        white_xy = []
        yellow_xy = []
        for segment in segment_list_msg.segments:
            # White points
            if segment.color == 0:
                white_xy.append([segment.points[0].x, segment.points[0].y])
            # Yellow points
            elif segment.color == 1:
                yellow_xy.append([segment.points[0].x, segment.points[0].y])
            else:
                print("Unrecognized segment color")

        # Turn into numpy arrays
        white_xy = np.array(white_xy)
        yellow_xy = np.array(yellow_xy)

        # ########################################################
        # Process buffer
        # ########################################################
        # Integrate the odometry
        current_time = rospy.get_time()
        dt = current_time - self.t_last_update
        self.t_last_update = current_time

        delta_x = self.velocity.v * dt
        delta_theta = self.velocity.omega * dt
        # Form the displacement
        delta_r = delta_x * np.array(
            [-np.sin(delta_theta), np.cos(delta_theta)])

        # If buffers contains data, propogate it BACKWARD
        if len(self.buffer_white) > 0:
            self.buffer_white = self.buffer_white - delta_r
        if len(self.buffer_yellow) > 0:
            self.buffer_yellow = self.buffer_yellow - delta_r

        # If new observations were received, then append them to the top of the list
        if len(white_xy) > 0:
            if len(self.buffer_white) > 0:
                self.buffer_white = np.vstack((white_xy, self.buffer_white))
            else:
                self.buffer_white = white_xy
        if len(yellow_xy) > 0:
            if len(self.buffer_yellow) > 0:
                self.buffer_yellow = np.vstack((yellow_xy, self.buffer_yellow))
            else:
                self.buffer_yellow = yellow_xy

        # ########################################################
        # Trim training points to within a valid radius
        # ########################################################
        valid_white_xy = []
        valid_yellow_xy = []

        # Select points within rad
        if len(self.buffer_white) > 0:
            tf_valid_white = self.computeRad(self.buffer_white) <= valid_rad
            valid_white_xy = self.buffer_white[tf_valid_white, :]

        if len(self.buffer_yellow) > 0:
            tf_valid_yellow = self.computeRad(self.buffer_yellow) <= valid_rad
            valid_yellow_xy = self.buffer_yellow[tf_valid_yellow, :]

        # ########################################################
        # Fit GPs
        # ########################################################
        # Set up a linspace for prediction
        if len(valid_white_xy) > 0:
            x_pred_white = np.linspace(0, np.minimum(valid_rad, np.amax(valid_white_xy[:, 0])), \
                num=n_test_points+1).reshape(-1, 1)
        else:
            x_pred_white = np.linspace(0, valid_rad,
                                       num=n_test_points + 1).reshape(-1, 1)

        if len(valid_yellow_xy) > 0:
            x_pred_yellow = np.linspace(0, np.minimum(valid_rad, np.amax(valid_yellow_xy[:, 0])), \
                num=n_test_points+1).reshape(-1, 1)
        else:
            x_pred_yellow = np.linspace(0, valid_rad,
                                        num=n_test_points + 1).reshape(-1, 1)

        # Start with the prior
        y_pred_white = -lane_width / 2.0 * np.ones((len(x_pred_white), 1))
        y_pred_yellow = lane_width / 2.0 * np.ones((len(x_pred_yellow), 1))

        t_start = time.time()
        # White GP.  Note that we're fitting y = f(x)
        gpWhite = []
        if len(valid_white_xy) > 2:
            x_train_white = valid_white_xy[:, 0].reshape(-1, 1)
            y_train_white = valid_white_xy[:, 1]
            whiteKernel = C(0.01, (-lane_width, 0)) * RBF(5, (0.3, 0.4))
            # whiteKernel = C(1.0, (1e-3, 1e3)) * RBF(5, (1e-2, 1e2))
            gpWhite = GaussianProcessRegressor(kernel=whiteKernel,
                                               optimizer=None)
            # x = f(y)
            gpWhite.fit(x_train_white, y_train_white)
            # Predict
            y_pred_white = gpWhite.predict(x_pred_white)

        # Yellow GP
        gpYellow = []
        if len(valid_yellow_xy) > 2:
            x_train_yellow = valid_yellow_xy[:, 0].reshape(-1, 1)
            y_train_yellow = valid_yellow_xy[:, 1]
            # yellowKernel = C(lane_width / 2.0, (0, lane_width)) * RBF(5, (0.3,
            # 0.4))
            yellowKernel = C(0.01, (0, lane_width)) * RBF(5, (0.3, 0.4))
            gpYellow = GaussianProcessRegressor(kernel=yellowKernel,
                                                optimizer=None)
            gpYellow.fit(x_train_yellow, y_train_yellow)
            # Predict
            y_pred_yellow = gpYellow.predict(x_pred_yellow)
        t_end = time.time()
        # print("MODEL BUILDING TIME: ", t_end - t_start)

        # Make xy point arrays
        xy_gp_white = np.hstack((x_pred_white, y_pred_white.reshape(-1, 1)))
        xy_gp_yellow = np.hstack((x_pred_yellow, y_pred_yellow.reshape(-1, 1)))

        # Trim predicted values to valid radius
        # Logical conditions
        tf_valid_white = self.computeRad(xy_gp_white) <= valid_rad
        tf_valid_yellow = self.computeRad(xy_gp_yellow) <= valid_rad

        # Select points within rad
        valid_xy_gp_white = xy_gp_white[tf_valid_white, :]
        valid_xy_gp_yellow = xy_gp_yellow[tf_valid_yellow, :]

        # ########################################################
        # Display
        # ########################################################
        self.visualizeCurves(valid_xy_gp_white, valid_xy_gp_yellow)

        # ########################################################
        # Compute d and \phi
        # ########################################################
        # Evaluate each GP at the lookahead distance and average to get d
        # Start with prior
        y_white = -lane_width / 2
        y_yellow = lane_width / 2

        if gpWhite:
            y_white = gpWhite.predict(np.array([lookahead]).reshape(-1, 1))
        if gpYellow:
            y_yellow = gpYellow.predict(np.array([lookahead]).reshape(-1, 1))

        # Take the average, and negate
        disp = np.mean((y_white, y_yellow))
        d = -disp

        # Compute phi from the lookahead distance and d
        L = np.sqrt(d**2 + lookahead**2)
        phi = disp / L

        print("D is: ", d)
        print("phi is: ", phi)

        # ########################################################
        # Publish the lanePose message
        # ########################################################
        lanePose = LanePose()
        lanePose.header.stamp = segment_list_msg.header.stamp
        lanePose.d = d
        lanePose.phi = phi
        lanePose.in_lane = True
        lanePose.status = lanePose.NORMAL
        lanePose.curvature = 0
        self.pub_lane_pose.publish(lanePose)

        # ########################################################
        # Save valid training points to buffer
        # ########################################################
        # Cap the buffer at max_buffer_size
        white_max = np.minimum(len(self.buffer_white), max_buffer_size)
        yellow_max = np.minimum(len(self.buffer_yellow), max_buffer_size)
        self.buffer_white = self.buffer_white[0:white_max - 1]
        self.buffer_yellow = self.buffer_yellow[0:yellow_max - 1]
        # print ("SIZE of white buffer: ", len(self.buffer_white))
        # print ("YELLOW of yellow buffer: ", len(self.buffer_yellow))

        ## #######################################################

        # Step 1: predict
        current_time = rospy.get_time()
        dt = current_time - self.t_last_update
        v = self.velocity.v
        w = self.velocity.omega

        self.filter.predict(dt=dt, v=v, w=w)
        # self.t_last_update = current_time

        # Step 2: update

        self.filter.update(segment_list_msg.segments)

        # Step 3: build messages and publish things
        [d_max, phi_max] = self.filter.getEstimate()
        # print "d_max = ", d_max
        # print "phi_max = ", phi_max

        inlier_segments = self.filter.get_inlier_segments(
            segment_list_msg.segments, d_max, phi_max)
        inlier_segments_msg = SegmentList()
        inlier_segments_msg.header = segment_list_msg.header
        inlier_segments_msg.segments = inlier_segments
        self.pub_seglist_filtered.publish(inlier_segments_msg)

        max_val = self.filter.getMax()
        in_lane = max_val > self.filter.min_max
        # build lane pose message to send
        # lanePose = LanePose()
        # lanePose.header.stamp = segment_list_msg.header.stamp
        # lanePose.d = d_max[0]
        # lanePose.phi = phi_max[0]
        # lanePose.in_lane = in_lane
        # # XXX: is it always NORMAL?
        # lanePose.status = lanePose.NORMAL

        # if self.curvature_res > 0:
        #     lanePose.curvature = self.filter.getCurvature(d_max[1:], phi_max[1:])

        # self.pub_lane_pose.publish(lanePose)

        # TODO-TAL add a debug param to not publish the image !!
        # TODO-TAL also, the CvBridge is re instantiated every time...
        # publish the belief image
        bridge = CvBridge()
        belief_img = bridge.cv2_to_imgmsg(
            np.array(255 * self.filter.beliefArray[0]).astype("uint8"),
            "mono8")
        belief_img.header.stamp = segment_list_msg.header.stamp
        self.pub_belief_img.publish(belief_img)

        # Latency of Estimation including curvature estimation
        estimation_latency_stamp = rospy.Time.now() - timestamp_now
        estimation_latency = estimation_latency_stamp.secs + estimation_latency_stamp.nsecs / 1e9
        self.latencyArray.append(estimation_latency)

        if (len(self.latencyArray) >= 20):
            self.latencyArray.pop(0)

        # print "Latency of segment list: ", segment_latency
        # print("Mean latency of Estimation:................. %s" % np.mean(self.latencyArray))

        # also publishing a separate Bool for the FSM
        in_lane_msg = BoolStamped()
        in_lane_msg.header.stamp = segment_list_msg.header.stamp
        in_lane_msg.data = True  #TODO-TAL change with in_lane. Is this messqge useful since it is alwas true ?
        self.pub_in_lane.publish(in_lane_msg)
    def processSegments(self, segment_list_msg):
        # Get actual timestamp for latency measurement
        timestamp_now = rospy.Time.now()

        if not self.active:
            return

        # TODO-TAL double call to param server ... --> see TODO in the readme, not only is it never updated, but it is alwas 0
        # Step 0: get values from server
        if (rospy.get_param('~curvature_res') is not self.curvature_res):
            self.curvature_res = rospy.get_param('~curvature_res')
            self.filter.updateRangeArray(self.curvature_res)

        # Step 1: predict
        current_time = rospy.get_time()
        dt = current_time - self.t_last_update
        v = self.velocity.v
        w = self.velocity.omega

        # ==== HERE THE UPPER BOUNDS ========
        ub_d = dt * self.omega_max * self.gain * 1000
        ub_phi = dt * self.v_ref * self.gain * 1000

        self.filter.predict(dt=dt, v=v, w=w)
        self.t_last_update = current_time

        # Step 2: update

        self.filter.update(segment_list_msg.segments, self.lane_offset)

        # Step 3: build messages and publish things
        [d_max, phi_max] = self.filter.getEstimate()

        inlier_segments = self.filter.get_inlier_segments(
            segment_list_msg.segments, d_max, phi_max)
        inlier_segments_msg = SegmentList()
        inlier_segments_msg.header = segment_list_msg.header
        inlier_segments_msg.segments = inlier_segments
        self.pub_seglist_filtered.publish(inlier_segments_msg)

        max_val = self.filter.getMax()
        in_lane = max_val > self.filter.min_max
        # build lane pose message to send
        lanePose = LanePose()
        lanePose.header.stamp = segment_list_msg.header.stamp

        lanePose.d = d_max[0]
        if not self.last_d:
            self.last_d = lanePose.d
        if lanePose.d - self.last_d > ub_d:
            lanePose.d = self.last_d + ub_d
            rospy.loginfo("d changed too much")
        if lanePose.d - self.last_d < -ub_d:
            lanePose.d = self.last_d - ub_d
            rospy.loginfo("d changed too much")

        lanePose.phi = phi_max[0]
        if not self.last_phi:
            self.last_phi = lanePose.phi
        if lanePose.phi - self.last_phi > ub_phi:
            lanePose.phi = self.last_phi + ub_phi
            rospy.loginfo("phi changed too much")
        if lanePose.phi - self.last_phi < -ub_phi:
            lanePose.phi = self.last_phi - ub_phi
            rospy.loginfo("phi changed too much")

        lanePose.in_lane = in_lane
        # XXX: is it always NORMAL?
        lanePose.status = lanePose.NORMAL

        if self.curvature_res > 0:
            lanePose.curvature = self.filter.getCurvature(
                d_max[1:], phi_max[1:])

        self.pub_lane_pose.publish(lanePose)

        # Save for next iteration       <=========
        self.last_d = lanePose.d
        self.last_phi = lanePose.phi

        # publish the belief image
        bridge = CvBridge()
        belief_img = bridge.cv2_to_imgmsg(
            np.array(255 * self.filter.beliefArray[0]).astype("uint8"),
            "mono8")
        belief_img.header.stamp = segment_list_msg.header.stamp
        self.pub_belief_img.publish(belief_img)

        # Latency of Estimation including curvature estimation
        estimation_latency_stamp = rospy.Time.now() - timestamp_now
        estimation_latency = estimation_latency_stamp.secs + estimation_latency_stamp.nsecs / 1e9
        self.latencyArray.append(estimation_latency)

        if (len(self.latencyArray) >= 20):
            self.latencyArray.pop(0)

        # also publishing a separate Bool for the FSM
        in_lane_msg = BoolStamped()
        in_lane_msg.header.stamp = segment_list_msg.header.stamp
        in_lane_msg.data = True  #TODO-TAL change with in_lane. Is this messqge useful since it is alwas true ?
        self.pub_in_lane.publish(in_lane_msg)
    def processSegments(self,segment_list_msg):
        # Get actual timestamp for latency measurement
        timestamp_now = rospy.Time.now()

        if not self.active:
            return

        # Step 1: predict
        current_time = rospy.get_time()
        dt = current_time - self.t_last_update
        v = self.velocity.v
        w = self.velocity.omega

        self.filter.predict(dt=dt, v=v, w=w)
        self.t_last_update = current_time

        # Step 2: update
        self.filter.update(segment_list_msg.segments)

        # Step 3: build messages and publish things
        [d_max, phi_max] = self.filter.getEstimate()

        ## Inlier segments
        inlier_segments = self.filter.get_inlier_segments(segment_list_msg.segments, d_max, phi_max)
        inlier_segments_msg = SegmentList()
        inlier_segments_msg.header = segment_list_msg.header
        inlier_segments_msg.segments = inlier_segments
        self.pub_seglist_filtered.publish(inlier_segments_msg)

        ## Lane pose
        in_lane = self.filter.isInLane()
        lanePose = LanePose()
        lanePose.header.stamp = segment_list_msg.header.stamp
        lanePose.d = d_max
        lanePose.phi = phi_max
        lanePose.in_lane = in_lane
        lanePose.status = lanePose.NORMAL

        self.pub_lane_pose.publish(lanePose)

        ## Belief image
        bridge = CvBridge()
        if self.mode == 'histogram':
            belief_img = bridge.cv2_to_imgmsg(np.array(255 * self.filter.beliefArray).astype("uint8"), "mono8")
        elif self.mode == 'particle':
            belief_img = bridge.cv2_to_imgmsg(np.array(255 * self.filter.getBeliefArray()).astype("uint8"), "mono8")
        belief_img.header.stamp = segment_list_msg.header.stamp
        self.pub_belief_img.publish(belief_img)
        
        ## Latency of Estimation
        estimation_latency_stamp = rospy.Time.now() - timestamp_now
        estimation_latency = estimation_latency_stamp.secs + estimation_latency_stamp.nsecs/1e9
        self.latencyArray.append(estimation_latency)

        if (len(self.latencyArray) >= 20):
            self.latencyArray.pop(0)

        # Separate Bool for the FSM
        in_lane_msg = BoolStamped()
        in_lane_msg.header.stamp = segment_list_msg.header.stamp
        in_lane_msg.data = True #TODO-TAL change with in_lane. Is this messqge useful since it is alwas true ?
        self.pub_in_lane.publish(in_lane_msg)