Дано: компания (наш клиент) продает стеллажные системы. Менеджер по продажам получает от клиента план склада в DXF или DWG. На выходе нужны варианты расстановки стеллажей, спецификация и чертёж — эти материалы сразу уходят в коммерческое предложение. До автоматизации этот путь занимал 2–3 дня инженерной работы на типовом объекте, и любая правка клиента запускала пересчёт почти с нуля.
Колонна, ширина проезда и тип балки на конкретном ярусе зависят друг от друга. Сдвинул ряд из-за колонны — изменилось число секций, поменялись балки, пересчиталась нагрузка на раму, смету нужно пересчитывать. “Нарисовать прямоугольники на плане и посчитать рамы” — это сильное упрощение реальной задачи, в которой каждая цифра тянет за собой остальные.
В продажах стеллажных систем клиент выбирает того подрядчика, кто быстро считает. Того, кто сделает расчет, за 2–3 дня заказчик. Скорость составления КП и пресейла прямо влияет на возможность продать или принять участие в тендере, а так же на загрузку инженерной команды, которую на этапе продажи приходится дёргать на каждый входящий план.

До автоматизации инженеры и менеджеры проходили один и тот же длинный путь на каждом проекте. Клиент присылает чертёж с планом помещения. Специалист вручную обводит зону, где можно ставить стеллажи, отмечает колонны и проезды, подбирает конфигурацию рам и балок под паллету и вес груза, расставляет секции в CAD, считает количество элементов и стоимость, готовит план и смету. На мелком складе это часы работы. На типовом объекте с десятками колонн, несколькими зонами и требованием сравнить варианты — уже дни, причем, значительная часть уходит не на проектирование, а на механическую проверку: влезает ли ряд, не попала ли стойка в колонну, хватает ли ширины проезда, совпадают ли стойки между рядами.
Универсальный “AI-проектировщик склада” для этой задачи не подойдет. Нужна система, которая кодирует экспертные правила производителя и умеет работать с реальной геометрией плана. Мы разработали как раз такую систему. Рассказываем, как.
Первая мысль — неправильная
Первая мысль в таком проекте — поставить стеллажи равномерной сеткой по всей доступной зоне. Для демо на прямоугольном зале без колонн это выглядит убедительно. На реальном плане не будет работать, и вот почему:
колонны режут ряды и заставляют убирать отдельные паллетоместа или разрывать цепочку секций
запретные зоны и проезды нельзя пересекать рамами
одинарные и двойные ряды требуют разной геометрии и перемычек между рядами
стойки в соседних рядах нужно выравнивать — это требование планировки для прямых проездов и движения погрузчиков
на разных ярусах могут стоять разные балки при одном числе палет в секции.
Сетка не знает ни про одно из этих правил.
Второй вариант — отдать всё одному крупному оптимизатору, который одновременно выбирает положение рядов, стоек и тип секции в каждой позиции. Число комбинаций при этом растёт быстрее, чем его можно перебрать: на каждую позицию накладываются сотни ограничений: зазоры к стенам и колоннам, ширина проездов, запрет на стойки в зонах движения техники, связность цепочек секций, приоритет паллетомест над стоимостью. И сплошной перебор, и попытка решить всё одним готовым оптимизатором упирались в одно и то же — расчёт получался слишком медленным и нестабильным.
Мы разбили задачу на этапы. Сначала определяем, где в зоне вообще помещаются ряды. Потом — где встают стойки. И только затем решаем, какие секции ставить в каждой позиции.
На входном эксперименте сравнивали два подхода: упаковку прямоугольников по жёстким правилам и обучение с подкреплением (RL) — модель, которая сама подбирает расстановку, оптимизируя награду на множестве прогонов. RL давал нестабильный результат на реальных планах, и главное — его решение нельзя проследить до конкретного правила. А расстановка должна соответствовать ГОСТу и собственным правилам монтажа производителя, то есть каждую секцию нужно уметь объяснить и проверить. Поэтому ядром стал детерминированный алгоритм на кодифицированных правилах.
Проблема в том, что раздел открывается «пользователем» без контекста — кто он и почему вообще зашла речь про шаги. Добавляю вводную и меняю заголовок на конкретного исполнителя.
Как менеджер по продажам взаимодействует с системой
Систему на этапе продажи использует не инженер, а менеджер. У него нет ни CAD-навыков, ни понимания, какая балка держит какой вес. Поэтому весь расчёт спрятан внутрь, а наружу выведен линейный процесс из шести шагов: менеджер идёт от загруженного файла до готовых материалов для КП.
Загрузить файл — план склада в DXF или DWG.
Доступные зоны — нарисовать полигоны, где разрешена расстановка, и задать высоту стеллажей.
Колонны — система ищет колонны внутри зон автоматически; менеджер проверяет и при необходимости правит.
Проезды и ограничения — отметить запретные области и проезды техники, задать ширину проездов и зазоры.
Груз и паллета — выбрать тип паллеты, параметры груза, число ярусов; получить подобранную конфигурацию рам и балок.
Расстановка — запустить расчёт, дождаться результата, сравнить варианты, скачать план и смету.

На выходе менеджер получает готовые материалы для продажи: превью на плане, до трёх вариантов расстановки с разным числом паллетомест, чертёж и спецификацию с ценами. Три варианта дают пространство для разговора с заказчиком: один с фокусом на максимум паллетомест, другой — на простую логистику, третий — на стоимость.

Ядро: алгоритм расстановки
Алгоритм не просто заполняет площадь максимумом секций. Он строит схему, которую можно смонтировать и эксплуатировать: с проездами для техники, выровненными стойками и допустимыми по нагрузке балками. Целевая функция в порядке убывания приоритета: максимум паллетомест, затем минимум стоимости при равном числе паллет, при равенстве — случайный выбор. Невалидные варианты отсекаются сразу: секция, у которой балка или стойка залезает в проезд, в итоговый вариент не идёт, даже если добавляет ещё одну паллету.
Подготовка геометрии
Перед планированием вход приводится к рабочему виду: читается контур доступной зоны, удаляются колонны вне зоны, обрезаются пересечения с запретными областями, учитываются зазоры к стенам и колоннам (минимум 50 мм вокруг колонны). Почти горизонтальные и почти вертикальные границы зоны выравниваются — ручные разметки не идеальны, а для стеллажей важны ортогональные ряды. Если колонна у стены ближе, чем требуемый проезд, участок границы зоны сдвигается внутрь, иначе система попытается поставить ряд туда, где его нельзя эксплуатировать.
Стрипы и двухэтапное планирование
Зона делится на стрипы — непрерывные свободные от колонн полосы по оси движения. Граница стрипа проходит по краю колонны, без зазоров. Минимальной ширины стрипа нет: даже узкая полоса может вместить половину раздвинутого двойного ряда. Ориентация на зону одна — горизонтальная или вертикальная; если она не задана, алгоритм считает оба варианта и берёт лучший.
Дальше задача решается в два шага.
Сначала ряды: алгоритм определяет, где в стрипе помещаются линии стеллажей по длине склада, с учётом ширины двойного ряда, расстояний между группами рядов и расположения колонн.
Затем стойки и секции: где конкретно встают рамы и какие секции занимают промежутки между ними.
Движение идёт от края зоны к концу. Первый стеллаж в зоне всегда одинарный и ставится вплотную к стене — без проезда со стороны границы, ради экономии пространства.
Дальше приоритет у двойных рядов: к двойному стеллажу техника подъезжает с двух сторон, поэтому проверяется условие
проезд + ширина_двойного + проезд
Если двойной не помещается — пробуется одинарный. Если не помещается ничего, позиция сдвигается вперёд до следующего валидного места.
Заполнение ряда секциями: предпросмотр на два шага
После того как ряд размещён, он заполняется секциями по 2, 3 или 4 паллеты. Если ставить секции жадно — «влезает 3 паллеты, ставлю» — теряется место. Пример: в ряду 6000 мм, евро-паллета. Жадно — 2700 + 2700, остаток 600 мм пропадает, итог 6 паллет. С предпросмотром на два шага — 3600 + 2300, остаток 100 мм, тоже 6 паллет, но длина ряда использована почти полностью. На длинных рядах эта разница накапливается в палетоместах.

Поэтому для каждой позиции алгоритм перебирает варианты секции и для каждого считает, что встанет в остаток после неё. Из вариантов выбирается тот, что даёт максимум паллет на два шага вперёд, затем минимум остатка, затем минимум стоимости балки. Глубина перебора ограничена пятью секциями, заведомо худшие ветки отсекаются.
Балки и стойки
Подбор привязан к справочнику.
Балки: длины 1850, 2300, 2700, 3300, 3600 мм, сечения от 85×1.5 до 160×2.0, грузоподъёмность задана таблично по длине.
Для евро-паллеты приоритетная балка 2700 мм, для американской — 3300 мм; для каждого типа груза свой набор допустимых балок, и грузоподъёмность балки проверяется против веса паллеты.
Стойки подбираются итеративно. Доступная высота считается как
высота_зоны − max(100, высота_зоны mod 500),
дальше — высота полки из высоты паллеты, балки и допуска, число полок, нагрузка на раму. Если стойка не выдерживает, число полок снижается на единицу и подбор повторяется. В справочнике около 60 типоразмеров стоек: 10 сечений на 6 вариантов высоты полки. Подбор по высоте, сечению и грузоподъёмности уходит из ручной работы инженера в расчёт.
Четыре режима обхода колонн
Самые трудные места — ряды, которые пересекают колонны. Их алгоритм рассчитывает первыми, потому что найденные здесь координаты стоек становятся опорной сеткой для остальных рядов. Дальше группы не считаются с нуля — переиспользуют уже найденные позиции стоек. Это даёт выровненные проезды и приближает план к тому, как проектируют вручную.
На ряду колонн алгоритм выбирает один из четырёх режимов, и каждый создаёт отдельную ветку в графе решений.
Раздвижение двойного ряда — когда колонна попадает между двумя рядами. Перемычка увеличивается по формуле базовая + ширина_колонны + 2×50 мм, колонна оказывается внутри. Предел перемычки — 1100 мм; если она хоть где-то пересекает колонну, режим запрещён.
Полный разрыв двойного ряда — когда колонна пересекает оба ряда. В месте колонны делается разрыв с зазором не менее 50 мм с каждой стороны, минимальный сегмент — одна секция.
Разрыв одного ряда — когда колонна задевает только один ряд двойного стеллажа: на нём убирается секция, второй ряд остаётся непрерывным.
Разрыв внутри секции — когда колонна задевает часть паллет: удаляются только пересекающиеся, симметрия не требуется. Альтернатива — удалить всю секцию, это отдельная ветка.
Жёсткое условие поверх всех режимов: колонна не должна попадать в проезд. Любое пересечение колонны с проездом делает вариант невалидным целиком.
Сквозные проезды
Сквозной проезд — проём внутри стеллажа под технику, который пользователь рисует линией на фронтенде. На пересечении с рядом нижние пролёты удаляются, и для проёма заново считаются балки и стойки. Балка проёма может отличаться от основной балки ряда: доступная длина теперь равна ширине проезда. Стойки не удаляются — на них держится весь ряд, — но пересчитываются под нагрузку оставшихся верхних пролётов.
Проверка: остаётся хотя бы один верхний пролёт, найдены подходящие балка и стойка, проезд не пересекается с колонной.
Граф решений и выбор варианта
Каждое локальное решение — ветка в графе: тип стеллажа, режим обхода колонны, комбинация секций, наличие или отсутствие сквозного проезда. Алгоритм собирает геометрически валидные ветки, отсекает те, что нарушают проезды или пересекают колонны, и сортирует по числу паллетомест, затем по стоимости. Возвращаются до трёх итоговых схем: лучшая по паллетоместам идёт основной, остальные — как альтернатива для заказчика.

Что разработали помимо алгоритма
Сам алгоритм — центр системы, но менеджер работает с продуктом, а не с расчётным модулем. Поэтому мы разработали:
Автоопределение колонн из DXF. Планы от проектировщиков неоднородны: колонна может быть четырьмя линиями, полилинией, замкнутым контуром или фрагментом границы зоны. Система разбирает чертёж и отбирает кандидатов по размерам и форме. Детектор не идеальный, но устойчивый первый проход, который снимает с пользователя самую скучную часть разметки.
Подбор номенклатуры. Отдельный расчёт по параметрам груза и паллеты подбирает рамы, балки по ярусам, перемычки и паллеты. Результат — не абстрактная «секция», а конкретные позиции каталога, которые попадут в смету. Менеджер видит фронтальную проекцию секции ещё до запуска расстановки.
Артефакты результата. После расстановки формируется DXF-план с блоками стеллажей и проекциями и смета в Excel: количество элементов, цены, итог.
История расчётов позволяет вернуться к проекту спустя время и снова скачать чертёж без повторного расчёта.
К чему мы не были готовы
Когда алгоритм заработал на чистых тестовых планах, казалось, что основное позади. На практике больше всего времени съели не правила расстановки, а две вещи на границах системы: качество входных DXF и конфликт между “оптимально по паллетоместо” и “удобно эксплуатировать”.
Грязные DXF. Самый неприятный класс ошибок — не алгоритм, а входные данные. Планы приходят от разных проектировщиков и в разных CAD, и одна и та же колонна на чертеже может быть оформлена четырьмя отдельными отрезками, замкнутой полилинией, блоком или просто фрагментом границы зоны. На одном плане колонны — аккуратные квадраты 400×400, на другом — незамкнутые линии вперемешку с мусорными контурами вентиляции и размерными выносками. Детектор отбирает кандидатов по геометрии: габариты в диапазоне реальных колонн, близость к прямоугольнику, замкнутость контура. Пороги этих фильтров пришлось многократно двигать: строгий набор пропускает реальные колонны, оформленные нестандартно, мягкий — принимает за колонну вентиляцию или текстовую рамку. Универсального порога, который одинаково хорошо работает на всех экспортах, найти не удалось, поэтому за детектором оставлен ручной шаг проверки — менеджер подтверждает или правит найденные колонны до расчёта.
Выравнивание стоек против паллетомест. Эти два требования тянут в разные стороны. Ровные проезды по всей длине склада нужны для прямого движения погрузчиков, но жёсткое выравнивание стоек по всем рядам иногда отнимает одну-две паллеты на ряд — стойка встаёт не там, где влезла бы лишняя секция. Считать полный перебор положений стоек по всем рядам сразу оказалось слишком дорого по времени. Компромисс: стойки выравниваются там, где их положение уже зафиксировано жёсткими ограничениями — колоннами и разрывами рядов, — а в свободных участках тип и длина секции подбираются локально через предпросмотр на два шага. Так проезды остаются проходимыми по основным линиям, а потеря паллетомест ограничена участками без колонн.
Как разрабатывали алгоритм без “живого склада”
Расстановка стеллажей — это набор связанных правил, и почти любое изменение одного из них тихо ломает поведение на других планах. Поправили логику обхода колонн ради одного объекта — на другом плане поехали паллетоместа в рядах без колонн. На одном тестовом чертеже такую регрессию не видно: он проходит, а десяток остальных — нет, и узнаёшь об этом уже на демонстрации заказчику.
Поэтому разработку завязали на набор сохранённых тестовых планов с эталонными зонами. Это реальные DXF разной сложности — от прямоугольного зала без колонн до планов с десятками колонн и несколькими зонами. На каждом прогоняется полный цикл: разбор чертежа, детекция колонн, расстановка, подбор балок и стоек, формирование плана и сметы. Любое изменение правил гоняется по всему набору сразу.
Это дало две вещи. Во-первых, цикл правок ускорился: новое правило проверяется на всех известных схемах за минуты, а не одним глазом на одном плане. Во-вторых, регрессии стали видны до заказчика — если паллетоместа «поехали» на каком-то из эталонных планов, это всплывает в прогоне, а не на встрече.
Набор тестов не заменяет приёмку на реальных объектах: новый план почти всегда приносит геометрию, которой в наборе не было. Но каждый разобранный сложный случай после этого добавляется в набор, и одна и та же ошибка второй раз уже не проходит незамеченной.
Выводы и открытые вопросы
В данном проекте продукт вырос не из “умного” алгоритма, а из довольно скучных вещей: кодификации экспертных правил производителя, разбивки задачи на этапы вместо монолитного солвера, понятного процесса для менеджера и документов, которые сразу идут заказчику. Продать проект под вывеской “AI-проектировщик склада” не сложно, но ценность оказалась в связке формализованных правил расстановки с автоматизацией ручной рутины, а не в самой по себе модели..
Главным решением по архитектуре стала именно поэтапность. Разделение на “где помещаются ряды → где встают стойки → какие секции ставить” сузило пространство перебора настолько, что расчёт стал быстрым и предсказуемым, а схему — можно проследить до конкретного правила. Один большой оптимизатор такого не давал.
Для производителя это переход от ручного проектирования каждого плана к воспроизводимому процессу: загрузил DXF, прошёл по шагам, получил варианты, отдал заказчику план и спецификацию. Подготовка проекта под КП сжалась с 2–3 дней до примерно 15 минут, и она больше не привязана к загрузке конкретного инженера.
Однако, часть решений пока не имеет однозначного ответа, и здесь интересно мнение тех, кто проектирует и эксплуатирует склады.
Размещение одинарных рядов. Сейчас одинарный стеллаж ставится только у стен, в середине зоны идут двойные, а в узких полосах между колоннами одинарный не разрешён вовсе. На части планов одинарный ряд в середине дал бы больше паллетомест. Это допустимо по логистике проездов или ломает движение погрузчиков?
Отступ между верхней балкой и грузом на паллете. Его хочется сократить ради лишнего яруса по высоте, но есть предел по безопасности и по заезду вил. Где этот предел проходит на практике и насколько он зависит от типа техники?
Типы препятствий. Какие зоны требуют не обхода, а полного запрета с проездом вокруг — пожарные шкафы, электрощитовые, зоны погрузки? И где проходит граница между «препятствием, которое можно подрезать рядом» и «зоной, которую трогать нельзя»?
Если вы проектируете стеллажные склады, поделитесь, пожалуйста, в комментариях, как вы решаете эти вопросы у себя.
