Files
mcp-wms-wiki/wiki/limagrain/03-picking/.fuse_hidden0000003700000014
2026-05-20 09:41:27 +02:00

324 lines
11 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: "Placement des palettes PS → PK (choix de table)"
tags: [picking, placement, table, buffer, ping-pong, algorithme]
status: draft
standard_ref: concepts/picking.md
jira_refs: []
confluence_refs: []
sources: ["Logique combinatoire picking - PS vers PK - V1.0.md"]
last_updated: 2026-05-12
author: Arthur
---
# Placement des palettes PS → PK (choix de table)
> **Résumé** : algorithme exécuté par le WMS lorsqu'une palette source
> arrive au poste de sortie (PS). Il décide sur quelle table du PK la
> poser, ou la redirige vers un buffer ES. Ce process s'exécute **en
> aval** du [séquençage TK → PS](sequencage-tk-ps.md) : les palettes
> arrivent au PS déjà triées.
> **Standard EasyWMS** : → voir [Picking](../../concepts/picking.md)
> Ce qui suit documente les **spécificités Limagrain** par rapport au
> standard.
## Contexte projet
Chaque PK dispose de **3 tables** soumises à une contrainte d'adjacence
stricte :
```
TABLE_GAUCHE ←→ TABLE_CENTRE ←→ TABLE_DROITE
✅ adjacentes ✅ adjacentes
TABLE_GAUCHE ←————————————————→ TABLE_DROITE
❌ INTERDIT
```
Règles de mouvement :
- Le stock est **toujours sur une palette**, jamais posé directement sur
la table
- L'opérateur peut déplacer du **stock** (sacs, colis) d'une palette à
une autre **uniquement entre deux tables adjacentes**
- Il est **interdit de déplacer une palette d'une table à une autre** —
seul l'AGV peut déplacer une palette (arrivée, évacuation, recentrage)
- **TABLE_CENTRE** est le pivot : seule table adjacente aux deux autres
## Déclenchement
L'algorithme est appelé **à chaque arrivée physique d'une palette au
PS**. Le PS interroge le WMS qui retourne une réponse parmi :
- **TABLE_GAUCHE**, **TABLE_CENTRE** ou **TABLE_DROITE** → la palette
est envoyée sur cette table
- **Buffer ESx** → aucune table n'est disponible, la palette est
redirigée vers un emplacement buffer
- **Attente** → ni table ni buffer disponible, la palette reste au PS
## Entrées de l'algorithme
| Donnée | Source |
|--------|--------|
| Tâche courante : palette source, article, quantité, type de picking (NÉGATIF / DIRECT), `Line.CstAtt` (séquence) | Tâche associée à la palette |
| État des 3 tables du PK : VIDE, PALETTE_FILLE_ACTIVE, PALETTE_FILLE_EN_ATTENTE, PALETTE_SOURCE_EN_PICKING, PALETTE_SOURCE_EN_ATTENTE, EN_ATTENTE_EVACUATION | État temps réel du PK |
| Tâches suivantes de l'OS (triées par `Line.CstAtt` croissant) | OS en base |
| Buffers ES disponibles : parmi ES1ES16, ceux non occupés ni ciblés | État temps réel des buffers |
| Nombre de buffers déjà affectés à ce PK vs `MAX_PRELOAD_PAR_PK` (défaut : 3) | Compteur par PK |
## Décision niveau 1 : table du PK ou buffer ?
```
FONCTION décider_destination(palette, PK) :
table_cible ← choisir_table(palette, PK)
SI table_cible ≠ NULL :
RETOURNER table_cible
// Aucune table disponible → tenter un buffer
SI nb_buffers_affectés(PK) < MAX_PRELOAD_PAR_PK :
buffer ← premier ES libre
SI buffer existe :
RETOURNER buffer
// Ni table ni buffer disponible
RETOURNER ATTENTE
```
## Décision niveau 2 : choix de la table
Le choix dépend du **type de picking** de la tâche associée.
### Cas PICKING_NÉGATIF
En picking négatif, la palette source arrive sur une table, l'opérateur
retire l'excédent sur une palette posée sur une **table adjacente**,
puis échange d'étiquettes. La palette a besoin de **2 tables** : une
pour elle, une adjacente libre pour l'excédent.
```
FONCTION choisir_table_picking_négatif(PK) :
// Priorité 1 : centre + un côté libre
SI TABLE_CENTRE == VIDE ET (TABLE_GAUCHE == VIDE
OU TABLE_DROITE == VIDE) :
RETOURNER TABLE_CENTRE
// Priorité 2 : côté + centre libre
SI (TABLE_GAUCHE == VIDE OU TABLE_DROITE == VIDE)
ET TABLE_CENTRE == VIDE :
RETOURNER côté vide
// Priorité 3 : centre libre + un côté libérable
SI TABLE_CENTRE == VIDE ET un côté est libérable :
évacuer(côté libérable)
RETOURNER TABLE_CENTRE
// Priorité 4 : un côté libre + centre libérable
SI un côté == VIDE ET TABLE_CENTRE est libérable :
évacuer(TABLE_CENTRE)
RETOURNER côté vide
// Dernier recours : évacuation forcée
évacuer_table_prioritaire(PK)
RETOURNER choisir_table_picking_négatif(PK) // rappel
```
### Cas PICKING_DIRECT
La palette source doit être posée sur une table **adjacente à la
palette fille active**. Le choix se fait en fonction de l'emplacement
de la palette fille.
```
FONCTION choisir_table_picking_direct(tâche, PK) :
// Étape 1 : localiser la palette fille compatible
table_fille ← localiser_palette_fille(tâche, PK)
SI table_fille == NULL :
table_fille ← choisir_table_nouvelle_palette_fille(PK)
// Étape 2 : choisir une table adjacente
tables_adj ← tables_adjacentes(table_fille)
// Prio A : palette source déjà sur une adjacente
// (multi-tâches même palette)
POUR chaque t DANS tables_adj :
SI t contient tâche.PALETTE_SOURCE :
RETOURNER t
// Prio B : adjacente VIDE
// Si 2 adjacentes libres (PF au centre) → ping-pong
adjacentes_vides ← [t POUR t DANS tables_adj SI t == VIDE]
SI len(adjacentes_vides) == 2 :
RETOURNER choisir_côté_ping_pong(PK)
SI len(adjacentes_vides) == 1 :
RETOURNER adjacentes_vides[0]
// Prio C : adjacente en cours d'évacuation (AGV en route)
POUR chaque t DANS tables_adj :
SI t == EN_ATTENTE_EVACUATION :
RETOURNER t
// Prio D : forcer l'évacuation d'une adjacente
t_à_libérer ← choisir_table_à_évacuer(tables_adj)
évacuer(t_à_libérer)
RETOURNER t_à_libérer
```
### Localisation de la palette fille compatible
```
FONCTION localiser_palette_fille(tâche, PK) :
// Parmi les PF actives
POUR chaque table :
SI table.état == PALETTE_FILLE_ACTIVE :
RETOURNER table
// Note : CONTROLE_TRAITEMENT_COMMERCIAL = false,
// donc pas de filtre TC
// Puis parmi les PF en attente
POUR chaque table :
SI table.état == PALETTE_FILLE_EN_ATTENTE :
RETOURNER table
RETOURNER NULL
```
### Choix de table pour une nouvelle palette fille
```
FONCTION choisir_table_nouvelle_palette_fille(PK) :
// TABLE_CENTRE = pivot → maximise la flexibilité
SI TABLE_CENTRE == VIDE : RETOURNER TABLE_CENTRE
SI TABLE_GAUCHE == VIDE : RETOURNER TABLE_GAUCHE
SI TABLE_DROITE == VIDE : RETOURNER TABLE_DROITE
// Aucune table vide → forcer une évacuation
évacuer_table_prioritaire(PK)
RETOURNER choisir_table_nouvelle_palette_fille(PK)
```
## Optimisation ping-pong
Le ping-pong est l'optimisation principale pour le débit. Il n'est
possible que lorsque la **palette fille est au centre** : les palettes
sources alternent alors entre TABLE_GAUCHE et TABLE_DROITE, de sorte
que la palette suivante est déjà en place quand l'opérateur termine.
```
FONCTION choisir_côté_ping_pong(PK) :
SI TABLE_GAUCHE.état ∈ {PALETTE_SOURCE_EN_PICKING,
PALETTE_SOURCE_EN_ATTENTE} :
RETOURNER TABLE_DROITE
SI TABLE_DROITE.état ∈ {PALETTE_SOURCE_EN_PICKING,
PALETTE_SOURCE_EN_ATTENTE} :
RETOURNER TABLE_GAUCHE
// Aucun côté occupé → choix arbitraire
RETOURNER TABLE_GAUCHE
```
**Recentrage** : si la palette fille est sur un côté (issue d'un
picking négatif), le ping-pong est impossible. Si le nombre de
PICKING_DIRECT restants ≥ `SEUIL_RECENTRAGE_PF` (défaut : 3), le WMS
peut déclencher un mouvement AGV pour recentrer la PF sur
TABLE_CENTRE.
## Évacuation des tables — Priorité
Lorsqu'aucune table n'est libre et qu'il faut en libérer une :
```
FONCTION évacuer_table_prioritaire(PK) :
// 1. Palette vide → retrait manuel (pas d'AGV)
// 2. Table déjà en attente d'évacuation → attendre AGV
// 3. Palette source en attente, non réutilisée par
// la prochaine tâche → AGV vers buffer/ASRS
// 4. Palette fille en attente → AGV vers image de quai
// 5. Palette source en attente (même si réutilisée)
// → AGV vers buffer ES
```
## Gestion des buffers ES → PK
Quand une table se libère au PK, le WMS choisit parmi les palettes en
buffer affectées à ce PK :
- Tri par `Line.CstAtt` **croissant** (plus petit = plus prioritaire)
- La première palette compatible avec la table libérée est envoyée
**Règle critique** : l'ordre de sortie des buffers est dicté par
`Line.CstAtt`, **pas** par l'ordre d'arrivée physique en buffer.
## Palettes multi-commandes
Une palette source peut être assignée à plusieurs OS.
Après picking de la commande en cours :
- Si la palette a encore des tâches pour d'autres OS → marquée
`MULTI_COMMANDE`, envoyée vers un buffer ES libre
- Elle reste en buffer jusqu'au lancement de l'OS suivant
- Une palette multi-commande au PK ou en mouvement compte comme une
place buffer occupée dans le calcul de `MAX_PRELOAD_PAR_PK`
## Priorité d'accès aux buffers entre PK
Lorsque les buffers ES sont saturés, la priorité est définie par la
séquence du mode "Picking" dans `MODES_PKxx`
(voir [Modes de travail PK](stations-picking.md)) :
- Séquence 1 = priorité la plus haute
- Quand un buffer se libère → affecté en priorité au PK avec la
séquence la plus basse parmi ceux qui ont des palettes en attente
## Paramètres WMS
| Paramètre | Description | Défaut |
|-----------|-------------|--------|
| `MAX_PRELOAD_PAR_PK` | Nombre max de palettes pré-chargées en buffer ES par PK | 3 |
| `SEUIL_RECENTRAGE_PF` | Nombre min de PICKING_DIRECT restants pour recentrer la PF au centre | 3 |
| `CONTROLE_TRAITEMENT_COMMERCIAL` | Séparer ou non les articles par TC sur les palettes filles | `false` (V1.1) |
| `MODES_PKxx` | Modes autorisés + priorité par PK (LIM-69) | — |
| `PK_BIGBAG` | Autorise ou non les big-bags par PK (LIM-70) | — |
## Points d'attention
⚠️ La contrainte d'adjacence est **physique** : l'opérateur ne peut pas
déplacer de sacs entre TABLE_GAUCHE et TABLE_DROITE directement.
⚠️ Le picking négatif nécessite 2 tables (palette source + adjacente
pour l'excédent), ce qui complique la gestion des cas saturés.
⚠️ Le recentrage de la palette fille (AGV) n'est déclenché que si
suffisamment de tâches de picking direct restent (≥ SEUIL_RECENTRAGE_PF).
⚠️ L'ordre de sortie des buffers suit `Line.CstAtt`, pas l'ordre FIFO
d'entrée en buffer.
## Questions ouvertes
(Aucune identifiée — algorithme V1.0 complet)
## Historique des modifications
| Date | Auteur | Modification |
|------|--------|--------------|
| 2026-05-12 | Arthur | Création depuis spec "Logique combinatoire picking - PS vers PK - V1.0" |
## Références
| Source | Type | Date |
|--------|------|------|
| Logique combinatoire picking - PS vers PK - V1.0 | Spécification technique | 27/04/2026 |
| [LIM-69](https://easywmsfrance.atlassian.net/browse/LIM-69) | Ticket Jira (modes PK) | 2026 |
| [LIM-70](https://easywmsfrance.atlassian.net/browse/LIM-70) | Ticket Jira (Mega Job) | 2026 |