màj wiki avec retour MES lot-5 AD
This commit is contained in:
@@ -0,0 +1,323 @@
|
||||
---
|
||||
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 ES1–ES16, 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 |
|
||||
Reference in New Issue
Block a user