Пример #1
0
 def is_enable_into_car(self):
     """
     是否允许进车
     """
     # 获取模型
     model = self.get_model()
     model = model_selection(model, axis=1, gt=W2)  # 3号堆模型,卸料区
     model = model_selection(model, axis=2, ge=H3)  # 卸料区高度大于H3(卸料区限高)
     if model.shape[0] == 0:
         # 无高于限高的料堆
         # 允许进车
         return True
     else:
         # 不允许进车
         return False
Пример #2
0
 def generate_data_2_db(self):
     """
     如果表为空,则生成数据
     :return: list类型的数据
     """
     # 获取模型
     model = self.get_model()
     # 记录当前时间
     date_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
     # 读取配置
     config_stack_boundary = self.get_stack_boundaries()
     # 插入数据
     generate_data = []
     for boundary in config_stack_boundary:
         # 筛选出模型
         model0 = model_selection(model,
                                  axis=1,
                                  ge=boundary[0],
                                  lt=boundary[1])
         # 空的条件是,该区域最高点小于H5
         is_empty = int(np.max(model0[:, 2]) < H5)
         # 插入新纪录
         sql = "insert into test(id, dust_warehouse_id, boundary_min, boundary_max, stack_time, is_empty) values(" \
               "%s, %s, %s,%s, %s,%s) "
         values = (str(uuid.uuid1()), self.dust_warehouse_id, boundary[0],
                   boundary[1], date_time, is_empty)
         generate_data.append(list(values))
         self.db_client.execute(sql, values)
     return generate_data
def cal_put_coordinates(boundary_center_coordinates, put_coordinates_array):
    """
    计算放料点,原则是先放中心区,从远至近
    :param boundary_center_coordinates: 该区域离上料口最近的边界中心点位置
    :param put_coordinates_array:  可放料点集合
    :return: 放料点坐标
    """
    # 在中心方向上的可放料点
    can_put_coordinate = model_selection(put_coordinates_array,
                                         axis=0,
                                         eq=boundary_center_coordinates[0])
    if can_put_coordinate.shape[0] != 0:
        # 在中心方向上有可放料点
        # 取距上料口最近的点
        put_coordinates = can_put_coordinate[np.argmin(can_put_coordinate[:,
                                                                          1])]
    else:
        # 在中心方向上无可放料点
        # 取距中心方向最近点放料
        put_coordinates = find_nearest_point(boundary_center_coordinates,
                                             put_coordinates_array)
    return put_coordinates
Пример #4
0
    def listen(self):
        """
        开始监听
        """
        status_reader = ModbusClient(port=status_port)  # 建立状态池连接

        # 放置次数
        put_times = 0

        # 无需倒料
        completed = True

        # 空置区域
        empty_area = None

        while not self.stop:
            # 当没有停止指令时
            # 开始监听除灰仓

            # 通过地址获取卸料口状态
            status_code = status_reader.get(
                self.dust_warehouse_address)  # 读取所有的设备状态
            status = dust_warehouse_status_dict[status_code]

            # 任务id
            task_id = str(uuid.uuid1())

            # 开始检测
            if completed and status == "allow":
                # 当前监听到需要倒料
                # 当检测到配置文件更改后,将表清零
                data = self.check_config()  # tuple类型

                if not data:
                    # 如果表为空,则根据模型插入数据至数据库中,并记录插入的数据
                    data = self.generate_data_2_db()  # list类型

                # 数据转为array
                data = np.array(data)[:, 2:]

                # 寻找一个最近的空置区域
                if empty_area is None:
                    # 判断条件:状态为空置
                    empty_area = data[data[:, 3] == empty][0:2][0]

            elif not completed and status == "allow":
                # 当前正在倒料中
                # 从卸料区的固定抓料点抓料
                get_coordinates = dust_warehouse_get_coordinates_dict[
                    self.dust_warehouse_id]  # 2维
                # 在空置区域里,横向X方向从最远至近依次放料
                x = self.x_range[0] + divmod(put_times,
                                             dust_stack_times)[0] * radius
                if x >= self.x_range[1]:
                    # 放完一层后,放中间
                    x = np.average(self.x_range)
                # y方向为区域的中心线
                y = np.average(empty_area)
                put_coordinates = [x, y]
                # 插入任务单
                # 抓料点和取料点之间的最高高度,从卸料区到缓冲区
                h = dust_stack_times * increase_height + safety_height

                # 放入任务
                p = task_priority.index('清理除尘仓')
                self.task_list[p][task_id] = [
                    get_coordinates, put_coordinates, h, active,
                    int(time.time())
                ]

                # 开始判断倒料任务是否完成
                while True:
                    try:
                        p = task_priority.index('已完成')
                        self.logger.info('任务已完成' +
                                         str(self.task_list[p][task_id]))
                    except KeyError:
                        # 任务未完成
                        time.sleep(1)
                        continue
                    else:
                        # 任务已完成
                        # 删除已完成任务
                        self.task_list[p].pop(task_id)
                        # 结束循环
                        break

                # 放置次数 +1
                put_times += 1

            elif not completed and status == "disallow":
                # 当前不允许倒料,但是任务未完成
                # 获取卸料区模型
                model = self.get_model()
                # 判断卸料区有无H4以上(可抓)的料堆
                can_get_coordinates = model_selection(model,
                                                      axis=1,
                                                      le=W3 - radius)
                can_get_coordinates = model_selection(can_get_coordinates,
                                                      axis=2,
                                                      ge=H4)
                if can_get_coordinates.shape[0] == 0:
                    # 当没有可抓点时
                    # 获取该区域的模型
                    empty_area_model = model_selection(model,
                                                       axis=1,
                                                       ge=empty_area[0],
                                                       lt=empty_area[1])
                    if np.max(empty_area_model[:, 2]) >= H5:
                        # 料场非空
                        # 堆放完毕,更新区域的堆放时间和非空
                        sql = 'UPDATE dust_warehouse SET stack_time = %s, is_empty = 0 where boundary_min = %s and ' \
                              'boundary_max = %s '
                        values = (datetime.datetime.now().strftime(
                            "%Y-%m-%d %H:%M:%S"), empty_area[0], empty_area[1])
                        self.db_client.execute(sql, values)
                        # 放置次数清零
                        put_times = 0

                        # 空置区域
                        empty_area = None

                    # 此次倒料完成,跳过以下步骤,进入下个循环,继续监听
                    # 状态更新为无需倒料
                    completed = True
                    continue

                else:
                    # 当有可抓点时
                    # 每次抓完一个最高点后,预测模型,然后再抓下一个最高点,直至预测模型中没有可抓点
                    while np.max(can_get_coordinates[:, 2]) >= H4:
                        # 先抓最高点
                        get_coordinates = can_get_coordinates[np.argmax(
                            can_get_coordinates[:, 2])][0:2]
                        # 在空置区域里,横向X方向从远至近依次放料
                        x = self.x_range[0] + divmod(
                            put_times, dust_stack_times)[0] * radius
                        if x >= self.x_range[1]:
                            # 放完一层后,放中间
                            x = np.average(self.x_range)
                        # y方向为区域的中心线
                        y = np.average(empty_area)
                        put_coordinates = [x, y]
                        # 插入任务单
                        # 抓料点和取料点之间的最高高度,从卸料区到缓冲区
                        h = dust_stack_times * increase_height + safety_height
                        # 放入任务
                        p = task_priority.index('清理除尘仓')
                        self.task_list[p][task_id] = [
                            get_coordinates, put_coordinates, h, active,
                            int(time.time())
                        ]

                        # 等待该倒料任务完成
                        while True:
                            try:
                                p = task_priority.index('已完成')
                                self.logger.info(
                                    '任务已完成' + str(self.task_list[p][task_id]))
                            except KeyError:
                                # 任务未完成
                                time.sleep(1)
                                continue
                            else:
                                # 任务已完成
                                # 删除已完成任务
                                self.task_list[p].pop(task_id)
                                # 结束循环
                                break

                        # 放置次数 +1
                        put_times += 1

                        # 预测模型
                        can_get_coordinates = predict_model(
                            get_coordinates, put_coordinates,
                            can_get_coordinates)

            # 任务未完成,还需要倒料
            completed = False
Пример #5
0
    def listen(self):
        """
        开始监听每个上料口
        """

        status_reader = ModbusClient(port=status_port)  # 建立状态池连接
        feed_type = None  # 初始化上料类型为空
        task_id_record = []  # 已安排的任务记录表,用于判断这些任务是否完成
        no_empty_area = None
        while not self.stop:
            # 当没有停止指令时

            # 先记录原先的上料类型
            feed_type_old = feed_type

            # 开始判断上料口状态

            # 通过地址获取状态
            status_code = status_reader.get(
                self.feed_status_address)  # 读取所有的设备状态
            status = feed_status_dict[status_code]

            # 获取当前的上料类型 ,先记录原来的上料类型

            feed_type_code = status_reader.get(
                self.feed_type_address)  # 读取所有的设备状态
            feed_type = feed_type_value_dict[feed_type_code]

            # 通过上料类型获取对应料场的范围
            x_range, y_range = ([], [])
            for key, value in sub_warehouse_type_dict.items():
                if value == feed_type:
                    x_range.append(sub_warehouse_range_dict[key][0])
                    y_range.append(sub_warehouse_range_dict[key][1])
            x_range = [x_range[0][0], x_range[-1][-1]]
            y_range = [y_range[0][0], y_range[-1][-1]]

            # 把任务id记录,用于后面判断是否完成
            task_id = str(uuid.uuid1())  # 任务id
            task_id_record.append(task_id)

            # 开始检测上料状态

            if status == "plug" or (feed_type_old is not None
                                    and feed_type_old != feed_type):
                # 当检测到堵料或者上料类型切换
                # 检查有没有紧急和一般上料任务
                priority = [
                    task_priority.index('紧急上料'),
                    task_priority.index('上料')
                ]
                is_exists_task, indexes = self.is_exists_task(priority,
                                                              x_range,
                                                              y_range,
                                                              task_type='feed')
                if is_exists_task:
                    # 任务已完成
                    for index in indexes:
                        # 修改任务优先级为已完成
                        self.task_list = change_task_priority(
                            self.task_list, index[0], index[1],
                            task_priority.index('已完成'))

            elif status == "emergency feed":
                # 当检测到紧急上料
                # 检查有没有紧急任务
                priority = [task_priority.index('紧急上料')]
                is_exists_emergency_feed_task = self.is_exists_task(
                    priority, x_range, y_range, task_type='feed')[0]
                if not is_exists_emergency_feed_task:
                    # 此时没有紧急上料任务
                    priority = [task_priority.index('上料')]
                    is_exists_feed_task, indexes = self.is_exists_task(
                        priority, x_range, y_range, task_type='feed')
                    if is_exists_feed_task:
                        # 若存在一般上料任务,优先级改为紧急
                        for index in indexes:
                            # 修改任务优先级为紧急
                            self.task_list = change_task_priority(
                                self.task_list, index[0], index[1],
                                task_priority.index('紧急上料'))
                    else:
                        # 若不存在一般上料任务,插入一条
                        # 先获取上料口关联的料场模型
                        model = self.get_model(feed_type, x_range, y_range)
                        # 筛选出主堆区的料堆,高度大于H4,要避开H1/2预留空间
                        model = model_selection(model, axis=1, lt=W1 - H1 / 2)
                        model = model_selection(model, axis=2, gt=H4)
                        # 计算取料点
                        get_coordinates = find_nearest_point(
                            self.feed_port_coordinate, model[:, 0:2])
                        # 放入字典
                        p = task_priority.index('紧急上料')
                        self.task_list[p][task_id] = [
                            get_coordinates, self.feed_port_coordinate,
                            feed_rise_height, active,
                            int(time.time())
                        ]

            elif status == "feed":
                # 当检测到上料
                # 检查有没有安排上料任务
                priority = [task_priority.index('上料')]
                is_exists_feed_task = self.is_exists_task(priority,
                                                          x_range,
                                                          y_range,
                                                          task_type='feed')[0]
                if not is_exists_feed_task:
                    # 若未安排一般上料任务
                    # 检查该上料口有无关联的除尘仓
                    dust_warehouse_id = feed_port_dust_warehouse_dict[
                        self.feed_port_id]
                    if dust_warehouse_id != -1:
                        # 关联除尘灰仓
                        # 放料点为上料口
                        put_coordinates = self.feed_port_coordinate  # 2维

                        # 任务优先级为普通上料
                        p = task_priority.index('上料')

                        # 获取区域模型
                        # 除尘灰的范围
                        sub_warehouse_no = dust_warehouse_sub_warehouse_dict[
                            dust_warehouse_id]
                        dust_warehouse_range = sub_warehouse_range_dict[
                            sub_warehouse_no]

                        # 已知可抓料区?
                        if not no_empty_area:
                            # 若此时不知道no_empty_area,求no_empty_area,可能出现的情况:1,首次;2,之前的no_empty_area复位
                            # 获取除尘区中24小时以上且不为空的区域
                            sql = "SELECT  *  FROM  dust_warehouse  WHERE  TO_DAYS(NOW()) - TO_DAYS(stack_time) >= 1 and is_empty = {0} and dust_warehouse_id = {1}".format(
                                not_empty, dust_warehouse_id)
                            data = self.db_client.query(sql)  # 满足条件的数据
                            if data:
                                # 存在满足条件的数据

                                # 获取不为空区域
                                no_empty_area = np.array(data)[0][2:4]

                                # 因为是首次对该区域抓料,先抓距上料口最远的点
                                get_coordinates = [
                                    dust_warehouse_range[0][0],
                                    np.average(no_empty_area)
                                ]
                                # 插入任务单
                                self.task_list[p][task_id] = [
                                    get_coordinates, put_coordinates,
                                    feed_rise_height, active,
                                    int(time.time())
                                ]
                                # 下个循环
                                continue
                        else:
                            # 若此时知道no_empty_area
                            # 判断料场是否为空
                            # 获取该非空置区域的模型
                            no_empty_area_model = self.get_model(
                                'chuchen', dust_warehouse_range[0],
                                no_empty_area)
                            if np.max(no_empty_area_model[:, 2]) <= H5:
                                # 区域置空
                                # 上料完毕,更新为空置
                                sql = 'UPDATE dust_warehouse SET is_empty = 1 where boundary_min = %s and ' \
                                      'boundary_max = %s '
                                values = (no_empty_area[0], no_empty_area[1])
                                self.db_client.execute(sql, values)

                                # 可抓取区复位
                                no_empty_area = None
                            else:
                                # 区域非空
                                # 抓料点集合
                                no_empty_area_get_coordinates = model_selection(
                                    no_empty_area_model, axis=2, gt=H5)
                                # 先抓最远点 ,x坐标最小
                                get_coordinates = no_empty_area_get_coordinates[
                                    np.argmin(
                                        no_empty_area_get_coordinates[:,
                                                                      0])][:,
                                                                           0:2]
                                # 插入任务单
                                self.task_list[p][task_id] = [
                                    get_coordinates, put_coordinates,
                                    feed_rise_height, active,
                                    int(time.time())
                                ]
                                # 下个循环
                                continue

                    # 若上述条件均不满足

                    # 开始寻找有无倒料的任务,准备合并
                    priority = [
                        task_priority.index('紧急清理卸料区'),
                        task_priority.index('清理卸料区'),
                        task_priority.index('清理缓冲区')
                    ]  # 可以被合并的倒料任务优先级
                    # 寻找有无倒料任务
                    is_exists_upload_task, indexes = self.is_exists_task(
                        priority, x_range, y_range, task_type='upload')
                    if is_exists_upload_task:
                        # 若存在倒料任务
                        # 将第一条倒料任务改为上料
                        index = indexes[0]
                        # 修改任务优先级为普通上料
                        self.task_list = change_task_priority(
                            self.task_list, index[0], index[1],
                            task_priority.index('上料'))
                        # 修改目的地为上料口
                        self.task_list[index[0]][
                            index[1]][1] = self.feed_port_coordinate
                        # 修改高度为上料高度
                        self.task_list[index[0]][
                            index[1]][2] = feed_rise_height
                    else:
                        # 若不存在倒料任务,插入一条上料
                        # 先获取上料口关联的料场模型
                        model = self.get_model(feed_type, x_range, y_range)
                        # 筛选出主堆区的料堆,高度大于H4,要避开H1/2预留空间
                        model = model_selection(model, axis=1, lt=W1 - H1 / 2)
                        model = model_selection(model, axis=2, gt=H4)
                        # 计算取料点
                        get_coordinates = find_nearest_point(
                            self.feed_port_coordinate, model[:, 0:2])
                        # 放入字典
                        p = task_priority.index('上料')
                        self.task_list[p][task_id] = [
                            get_coordinates, self.feed_port_coordinate,
                            feed_rise_height, active,
                            int(time.time())
                        ]
            else:
                # 此时为不上料
                # 删除已完成的该模块产生的上料任务
                for taskId in task_id_record:
                    try:
                        p = task_priority.index('已完成')
                        self.logger.info('任务已完成' +
                                         str(self.task_list[p][taskId]))
                        self.task_list[p].pop(taskId)
                    except KeyError:
                        continue
                    else:
                        task_id_record.remove(taskId)
    def generate(self):
        """
        开始产生任务
        """
        while not self.stop:
            # 当没有停止指令时
            # 开始规划任务
            perform_completed = False  # 规划的task_num任务执行完成数量
            generate_times = 0  # 规划的次数
            task_id_record = []  # 已安排的任务记录表,用于判断这些任务是否完成

            # 更新模型
            self.update_model()

            # 开始规划任务小于每批次产生的任务数量,由于任务规划中模型是靠预测出来的,所以此任务数量不宜设置过大
            while generate_times < task_num:
                # 规划的次数 +1
                generate_times += 1
                # 模型划分
                model3 = model_selection(self.model, axis=1,
                                         gt=W2)  # 3号堆模型,卸料区
                # 2号堆模型,缓冲区,前预留H2/2空间,防止坡度过大
                model2 = model_selection(self.model,
                                         axis=1,
                                         ge=W1 - radius,
                                         le=W2 - H2 / 2)
                model1 = model_selection(self.model, axis=1, le=W1 -
                                         H1 / 2)  # 1号堆模型,主堆区,预留H1/2空间,防止坡度过大

                # 需倒料点集
                unload_stock_emergency_clean_points = model_selection(
                    model3, axis=2, ge=H3)  # 紧急清理卸料区点集
                unload_stock_clean_points = model_selection(model3,
                                                            axis=2,
                                                            ge=H4,
                                                            lt=H3)  # 清理卸料区点集
                cache_stock_clean_points = model_selection(model2,
                                                           axis=2,
                                                           ge=H2)  # 清理缓冲区点集

                # 可堆放点集

                # 主堆区分三层
                if np.min(model1[:, 2]) < H1 / 3:
                    main_stock_can_stacked_points = model_selection(
                        model1, axis=2, lt=H1 / 3)[:, 0:2]  # 主堆区可堆放点(二维)

                elif 2 * H1 / 3 >= np.min(model1[:, 2]) >= H1 / 3:
                    # 主堆区可堆放点(二维)
                    main_stock_can_stacked_points = model_selection(model1,
                                                                    axis=2,
                                                                    lt=2 * H1 /
                                                                    3)[:, 0:2]

                else:
                    main_stock_can_stacked_points = model_selection(
                        model1, axis=2, lt=H1)[:, 0:2]  # 主堆区可堆放点(二维)

                # 缓冲区分二层
                if np.min(model2[:, 2]) < H2 / 2:
                    cache_stock_can_stacked_points = model_selection(
                        model2, axis=2, lt=H2 / 2)[:, 0:2]  # 缓冲区可堆放点(二维)

                else:
                    cache_stock_can_stacked_points = model_selection(
                        model2, axis=2, lt=H2)[:, 0:2]  # 缓冲区可堆放点(二维)

                # 提升高度
                h1 = np.max(
                    model1[:, 2]) + safety_height  # 送往1号堆的提升高度,1号堆最高+抓斗安全距离
                h2 = np.max(
                    model2[:, 2]) + safety_height  # 送往2号堆的提升高度,2号堆最高+抓斗安全距离

                # 开始产生任务
                get_coordinates = np.array([])
                put_coordinates = np.array([])
                task_id = str(uuid.uuid1())

                # 把任务id记录,用于后面判断是否完成
                task_id_record.append(task_id)

                # 有紧急清理卸料区点
                if unload_stock_emergency_clean_points.shape[0] >= 0:
                    # 先抓其中的最高点
                    get_coordinates = unload_stock_emergency_clean_points[
                        np.argmax(unload_stock_emergency_clean_points[:, 2])]
                    # 在缓冲区计算放料点
                    # 缓冲区边界中心点
                    boundary_center_coordinates = [
                        np.average(sub_warehouse_range_dict[
                            self.sub_warehouse_no][0]), W1
                    ]
                    put_coordinates = cal_put_coordinates(
                        boundary_center_coordinates,
                        cache_stock_can_stacked_points)
                    # 抓料点和取料点之间的最高高度,从卸料区到缓冲区
                    h = max(h2, get_coordinates[2] + safety_height)
                    # 插入任务
                    p = task_priority.index('紧急清理卸料区')
                    self.task_list[p][task_id] = [
                        get_coordinates[0:2], put_coordinates, h, active,
                        int(time.time())
                    ]
                    # 需要倒料,任务规划进行中
                    self.generate_completed = False

                # 有清理卸料区点
                elif unload_stock_clean_points.shape[0] >= 0:
                    # 先抓其中的最高点
                    get_coordinates = unload_stock_clean_points[np.argmax(
                        unload_stock_clean_points[:, 2])]
                    # 在主堆区计算放料点
                    boundary_center_coordinates = [
                        np.average(sub_warehouse_range_dict[
                            self.sub_warehouse_no][0]),
                        sub_warehouse_range_dict[self.sub_warehouse_no][1][0]
                    ]
                    put_coordinates = cal_put_coordinates(
                        boundary_center_coordinates,
                        main_stock_can_stacked_points)
                    # 抓料点和取料点之间的最高高度,从卸料区到主堆区
                    h = max(h1, h2, get_coordinates[2] + safety_height)
                    # 放入字典
                    p = task_priority.index('清理卸料区')
                    self.task_list[p][task_id] = [
                        get_coordinates[0:2], put_coordinates, h, active,
                        int(time.time())
                    ]
                    # 需要倒料,任务规划进行中
                    self.generate_completed = False

                # 有清理缓冲区点
                elif cache_stock_clean_points.shape[0] >= 0:
                    # 先抓其中的最高点
                    get_coordinates = cache_stock_clean_points[np.argmax(
                        cache_stock_clean_points[:, 2])]
                    # 在主堆区计算放料点
                    boundary_center_coordinates = [
                        np.average(sub_warehouse_range_dict[
                            self.sub_warehouse_no][0]),
                        sub_warehouse_range_dict[self.sub_warehouse_no][1][0]
                    ]
                    put_coordinates = cal_put_coordinates(
                        boundary_center_coordinates,
                        main_stock_can_stacked_points)
                    # 抓料点和取料点之间的最高高度,从缓冲区到主堆区
                    h = max(h1, get_coordinates[2] + safety_height)
                    # 放入字典
                    p = task_priority.index('清理缓冲区')
                    self.task_list[p][task_id] = [
                        get_coordinates[0:2], put_coordinates, h, active,
                        int(time.time())
                    ]
                    # 需要倒料,任务规划进行中
                    self.generate_completed = False

                # 无需倒料
                else:
                    self.generate_completed = True  # 任务规划完毕

                # 任务规划后的模型预测
                self.model = predict_model(get_coordinates, put_coordinates,
                                           self.model)

                # 判断任务是否规划完毕
                if not self.generate_completed:
                    continue
                else:
                    break

            # 开始判断任务是否完成
            while not perform_completed:
                for taskId in task_id_record:
                    try:
                        p = task_priority.index('已完成')
                        self.logger.info("子料仓" + str(self.sub_warehouse_no) +
                                         '任务已完成' +
                                         str(self.task_list[p][taskId]))
                    except KeyError:
                        perform_completed = False
                        break
                    else:
                        perform_completed = True
                time.sleep(1)

            # 删除已完成任务
            for taskId in task_id_record:
                p = task_priority.index('已完成')
                self.task_list[p].pop(taskId)