- Bloquants: mermaid 03-picking/_index reconstitue (archive 11-05), 13 liens vers pages squelette retires, 2 liens recibles (anoxie, application-dictionary) - Conventions: 910 em dashes -> tirets simples, 145 checklists -> puces question, 13 questions resolues barrees - Liens: 9 ancres reparees (slugs GitHub) - Delta: 12 standard_ref remappes, blocs Standard EasyWMS + sections References ajoutes, front matter complete - Glossaire: 15 termes standard deplaces en section rappel avec renvoi - Rapport: limagrain/_lint_report.md (Phase 1 + Phase 2 + re-scan final) - Inclut les pages des sessions precedentes non commitees + CLAUDE.md et consume.log en l'etat
20 KiB
title, tags, status, standard_ref, jira_refs, confluence_refs, sources, last_updated, author
| title | tags | status | standard_ref | jira_refs | confluence_refs | sources | last_updated | author | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Placement des palettes PS → PK (choix de table) |
|
draft | concepts/picking.md |
|
|
2026-07-20 | 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 : les palettes arrivent au PS déjà triées.
Standard EasyWMS : → voir Picking Ce qui suit documente les spécificités Limagrain par rapport au standard.
Statut (LIM-82) : dev terminé, en attente de déploiement pour test. Livré en préprod le 25/06/2026, revue de code validée le 03/07/2026 (après une itération NOK le 02/07). Ce ticket est la reprise de LIM-75 (V1 annulé). Positionnement dans la chaîne : LIM-80 assignation → LIM-84 séquençage TK → PS → LIM-82 placement PS → PK → Process picking au PK (LIM-91).
⚠️ LIM-95 (Annulé) mergé ici : le ticket LIM-95 « [JOB] génération des mouvements depuis les buffers » est Annulé(e) ; ses modifications ont été intégrées à LIM-82 (commentaire Maxime Halgand, 26/06). Ses deux demandes sont couvertes ici : (1) ne pas générer le mouvement d'une palette si une autre tâche du même OS a une séquence prioritaire → voir Gate de séquence (critère B) ; (2) contrôler la capacité de la TP (sous-emplacement) en plus de celle du PK → voir la note ci-dessous.
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 - ni par l'opérateur, ni par l'AGV. Une palette arrive sur une table et ne peut que repartir (évacuation)
- 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
[CUSTOM] Capacité TP (LIM-95) : dans tous les flux qui vérifient la capacité du PK, la capacité de la TP (sous-emplacement de la table) doit aussi être contrôlée. Attention : aucun capteur de présence n'est relié à Galileo - la capacité est donc suivie logiquement par le WMS, pas par un signal physique.
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.CstAttcroissant (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.
[CUSTOM] Capacité buffers PK → PK (LIM-116) : la génération de mouvement depuis le picking (
Task_GenerateMovement_PR_V2) contrôle la capacité des buffers lorsqu'une palette va d'un poste de picking à un autre. Les mouvements manuels du poste (appeler / renvoyer, filmage au retour) sont détaillés dans Process picking au PK.
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) :
- 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) | - |
Implémentation définitive (LIM-82)
Cette section reflète le code livré et validé (revue de code du 03/07/2026). Elle prime sur l'algorithme V1.0 ci-dessus en cas d'écart - ce dernier reste documenté comme référence de conception.
Records et workflows
| Élément AD | Type | Rôle |
|---|---|---|
TaskWF |
Record | Ajout d'un CstAtt de tâche (dont CstAtt3, flag « palette passée au shuttle »). |
CST_ChooseDestinationFromPS |
Workflow | Décision principale : table de picking (avec choix de la position), buffer ES si aucune place, ou attente au PS s'il n'y a plus de place (selon MAX_PRELOAD_PAR_PK). |
Container_MovedEventHandler_PS_PR |
Workflow | À l'arrivée d'une palette de tâche picking au PS, appelle CST_ChooseDestinationFromPS. |
Container_MovedEventHandler_ET_PR |
Workflow | Passe CstAtt3 de la tâche à True après que la palette a quitté le shuttle, pour autoriser la sortie des palettes suivantes du TK. |
Container_MovedEventHandler_MS_PR |
Workflow | Idem : passe CstAtt3 à True quand une palette atteint TS_12 (sortie du TK_01, qui ne passe pas par le shuttle). |
CST_Job_CheckPSBufferContainers |
Job | Ré-évalue les palettes en attente au PS et en buffer : quand une place picking se libère, envoie la bonne palette au picking. |
Queries
| Query | Rôle |
|---|---|
CST_Picking_GetSiblingTasks |
Récupère les tâches de picking du même ordre de sortie (OS). |
CST_GetTasksWaitingOnPSAndBufffer |
Récupère toutes les tâches sans mouvement présentes sur un PS ou un buffer (en attente de picking ou de stage). |
CST_GetStationRoutes_ToDisable |
Récupère les routes à désactiver pour le mouvement PS : route PS → PK, et routes PS → buffer plein. |
Gate de séquence (critère B)
Avant toute pose sur une table, le WMS vérifie via
CST_Picking_GetSiblingTasks s'il existe une autre palette du même OS
avec un Line.CstAtt (séquence, écrit par
LIM-84) inférieur
encore à traiter en amont (buffer / shuttle). Si oui, la palette qui arrive
n'est pas posée sur une table : elle part en buffer ES (ou en attente si
buffer indisponible).
Cette règle correspond à la 1re demande de LIM-95 (Annulé, mergé ici) : « le job traite chaque tâche une par une ; si une autre tâche de l'OS a une séquence prioritaire (
Task.CstAtt01plus faible), ne pas générer le mouvement ».Task.CstAtt01etLine.CstAttdésignent la même séquence de picking (voir ad-customs, CstAtt Tâche 01).
⚠️ Correction revue de code (02→03/07) : le contrôle portait initialement sur les tâches de la route ; il a été ramené au périmètre de l'OS. Vérifier sur la route provoquait un faux blocage quand deux OS d'une même route étaient préparés simultanément sur deux PK différents.
Gating shuttle (CstAtt3)
Le shuttle est le goulot d'ordonnancement entre le TK et les PS. Le flag
CstAtt3 de la tâche est mis à True une fois la palette sortie du shuttle
(handler ET) ou arrivée à TS_12 pour le TK_01 qui ne passe pas par le
shuttle (handler MS). Ce flag conditionne la sortie des palettes suivantes
du TK, garantissant l'ordre de passage (cf.
ad-customs CstAtt Tâche 03).
Écarts avec l'algorithme V1.0
- Les états
EN_ATTENTE_EVACUATIONet la « réactivation » d'unePALETTE_FILLE_EN_ATTENTEsont abandonnés dans LIM-82 (barrés dans la description du ticket). Les priorités V1.0 qui s'y réfèrent (ex. cas picking direct « adjacente en cours d'évacuation ») ne sont donc plus applicables. - Picking négatif (critère C) :
TABLE_CENTRElibre ET au moins une table de côté adjacente libre → palette source surTABLE_CENTRE; sinon buffer ES. Une seule palette négative à la fois par PK. - Picking direct (critère D) : table de côté libre adjacente à la
PALETTE_FILLE_ACTIVE; en cas de double disponibilité,TABLE_GAUCHEprioritaire surTABLE_DROITE; sinon buffer ES. - Les mécanismes
SEUIL_RECENTRAGE_PF(recentrage AGV) etCONTROLE_TRAITEMENT_COMMERCIALproviennent de la spec V1.0 et ne figurent pas dans les critères validés de LIM-82. → ⚠️ À confirmer côté implémentation.
Points d'attention
⚠️ L'implémentation livrée (LIM-82) prime sur l'algorithme V1.0 ci-dessus :
voir Implémentation définitive (LIM-82)
(états EN_ATTENTE_EVACUATION / réactivation abandonnés, gate de séquence
OS, gating shuttle CstAtt3).
⚠️ 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
- Big-bag : comportement attendu si une palette big-bag arrive et qu'aucun
PK
PK_BIGBAGautorisé n'est disponible (attente dédiée, refus, autre file) ? (question ouverte LIM-82) - Confirmer si les mécanismes V1.0
SEUIL_RECENTRAGE_PF(recentrage AGV) etCONTROLE_TRAITEMENT_COMMERCIALsont réellement implémentés (absents des critères validés LIM-82). - LIM-75 est cité comme pré-requis « Mini Job picking négatif » (évaluation
du
TaskTypeOrdinaryPicking/NegativePicking) alors qu'il est confirmé Annulé → LIM-82 : clarifier où leTaskTypeest réellement écrit.
Historique des modifications
| Date | Auteur | Modification |
|---|---|---|
| 2026-05-12 | Arthur | Création depuis spec "Logique combinatoire picking - PS vers PK - V1.0" |
| 2026-05-13 | Arthur | Correction règle déplacement palette (jamais déplacée, ni AGV ni opérateur), ajout jira_ref LIM-82 |
| 2026-07-17 | Arthur | Relecture revue de code LIM-82 (préprod, validée 03/07) : ajout section « Implémentation définitive » (WF CST_ChooseDestinationFromPS, Container_MovedEventHandler_PS/ET/MS_PR, job CST_Job_CheckPSBufferContainers, queries CST_Picking_GetSiblingTasks / CST_GetTasksWaitingOnPSAndBufffer / CST_GetStationRoutes_ToDisable) ; gate de séquence OS (correction route → OS) ; gating shuttle CstAtt3 ; abandon états EN_ATTENTE_EVACUATION + réactivation PF ; statut préprod ; questions big-bag / recentrage / TaskType LIM-75 |
| 2026-07-17 | Arthur | LIM-95 confirmé Annulé(e) → mergé dans LIM-82 (pattern V1/V2, pas de duplication) : note de supersession (chaîne), rattachement des 2 demandes (gate de séquence Task.CstAtt01=Line.CstAtt ; note capacité TP + absence capteurs Galileo), jira_refs/sources/Références |
| 2026-07-20 | Arthur | Note capacité buffers PK → PK (LIM-116, Task_GenerateMovement_PR_V2) + renvoi vers les mouvements manuels du poste (process-picking-pk.md) ; jira_refs +LIM-116, sources, last_updated, Références |
Références
| Source | Type | Date |
|---|---|---|
| Logique combinatoire picking - PS vers PK - V1.0 | Spécification technique | 27/04/2026 |
| LIM-82 | Ticket Jira (placement PS → PK, 5 commentaires, préprod) | 2026-06 → 07 |
| LIM-84 | Ticket Jira (séquençage TK → PS, écrit Line.CstAtt) |
2026 |
| LIM-75 | Ticket Jira (picking négatif TaskType, Annulé → LIM-82) | 2026 |
| LIM-95 | Ticket Jira ([JOB] mouvements depuis buffers, Annulé → mergé LIM-82) | 2026 |
| LIM-91 | Ticket Jira (workflow opérateur au PK) | 2026 |
| LIM-116 | Ticket Jira (LOT 3, mouvements manuels station picking - capacité buffers PK → PK Task_GenerateMovement_PR_V2) |
2026-07 |
| LIM-69 | Ticket Jira (modes PK) | 2026 |
| LIM-70 | Ticket Jira (Mega Job) | 2026 |