Conveyor class, ConveyorSegments/Segment, and the Conveyor.builderrequestConveyor, rideConveyor, exitConveyor, convey, transferTo) to move entitiesConveyor modeling is roughly classified as:
Performance measures to consider when designing conveyor systems:
You do not always need specialized constructs:
A gravity conveyor can be modeled with a deterministic delay
The front of a conveyor can be modeled as a resource plus a small load delay
Use conveyor constructs when the space allocated to the conveyor is important to system operation
The KSL maps space/distance to resources called cells
A conveyor conceptualized as a set of contiguous cells
seize() and release() calls that depends on entity size and number of cellsNon-accumulating — items stop when the conveyor stops
Accumulating — the conveyor is always running
When an entity stops (e.g. to be processed), entities behind it queue up on the conveyor; entities in front continue moving
Spacing decreases at the blockage until entities bump together; when the blockage ends, blocked entities move once cells free up
Analogy: wearing roller blades on an airport people mover, everyone piling up behind a bar placed across it — an accumulating conveyor
Segments; each has an origin and destination given as String locations (a conveyor uses no spatial model)ConveyorSegments collection of Segment data objects, or fluently via Conveyor.builder(...)maxEntityCellsAllowed; each segment length is an integer multiple of the cell sizeConveyor segments
Conveyor.builder Fluent APIfirstSegment reused as the last nextSegment makes the conveyor circularStrings — using a model element’s name gives a unique location stringloopConveyor = Conveyor.builder(this, "LoopConveyor")
.conveyorType(Conveyor.Type.NON_ACCUMULATING)
.velocity(30.0)
.cellSize(10)
.maxCellsAllowed(2)
.firstSegment(myDrillingResource.name, myMillingResource.name, 70)
.nextSegment(myPlaningResource.name, 90)
.nextSegment(myGrindingResource.name, 50)
.nextSegment(myInspectionResource.name, 180)
.nextSegment(myDrillingResource.name, 250)
.build()ConveyorRequestIfc — like an Allocation, it is the “ticket” to ride and is required when exitingrequestConveyor(conveyor, entryLocation, numCellsNeeded) — returns a ConveyorRequestIfc; waits for the cells, then holds them (not yet riding)rideConveyor(conveyorRequest, destination) — moves the item to the destination cellexitConveyor(conveyorRequest) — moves through and releases the cellsconvey(conveyor, entryLocation, destination, numCellsNeeded) — combines request + ride + exittransferTo(conveyorRequest, nextConveyor, entryLocation) — transfers to another conveyorConveyorRequestIfc InterfaceConveyor requests
delays (distance / velocity)Tandem queue with conveyors
private inner class Part : Entity() {
val tandemQProcess: KSLProcess = process(isDefaultProcess = true) {
wip.increment()
timeStamp = time
delay(delayDuration = 70.0/30.0) // 30 fpm for 70 ft
use(resource = worker1, delayDuration = st1)
delay(delayDuration = 40.0/30.0) // 30 fpm for 40 ft
use(resource = worker2, delayDuration = st2)
delay(delayDuration = 60.0/30.0) // 30 fpm for 60 ft
timeInSystem.value = time - timeStamp
wip.decrement()
}
}Conveyor.builder: velocity 30, cellSize(1), maxCellsAllowed(1), segments firstSegment(enter, station1, 70), nextSegment(station2, 40), nextSegment(exit, 60)convey() combines requestConveyor + rideConveyor + exitConveyor into one call, shortening the processprivate inner class Part : Entity() {
val tandemQProcess: KSLProcess = process(isDefaultProcess = true) {
wip.increment()
timeStamp = time
convey(conveyor = conveyor, entryLocation = enter, destination = station1)
use(resource = worker1, delayDuration = st1)
convey(conveyor = conveyor, entryLocation = station1, destination = station2)
use(resource = worker2, delayDuration = st2)
convey(conveyor = conveyor, entryLocation = station2, destination = exit)
timeInSystem.value = time - timeStamp
wip.decrement()
}
}conveyorRequest, rideConveyor between stations, and exitConveyor only at the end — the part stays on the conveyor while being processedconvey() (it exits every time); the use() calls happen while the part still occupies its cellsval conveyorRequest = requestConveyor(conveyor = conveyor, entryLocation = enter, numCellsNeeded = 1)
rideConveyor(conveyorRequest = conveyorRequest, destination = station1)
use(resource = worker1, delayDuration = st1)
rideConveyor(conveyorRequest = conveyorRequest, destination = station2)
use(resource = worker2, delayDuration = st2)
rideConveyor(conveyorRequest = conveyorRequest, destination = exit)
exitConveyor(conveyorRequest = conveyorRequest)Working on the conveyor
cellSize(1), 5 segments totaling 130 feet) links diagnostics, the three test stations, and repairmaxCellsAllowed(2)names; loopConveyor.accessQueueAt(myRepair.name).defaultReportingOption = false turns off unused access-queue stats// parts following different test plans need different cell counts
private val cellSizes = mapOf(testPlan1 to 1, testPlan2 to 1, testPlan3 to 2, testPlan4 to 2)
val cellsNeeded = cellSizes[plan]!!
val testAndRepairProcess: KSLProcess = process(isDefaultProcess = true) {
use(resource = myDiagnostics, delayDuration = diagnosticTime)
var entryLocation = myDiagnostics.name
for (tp in plan) {
convey(conveyor = loopConveyor, entryLocation = entryLocation,
destination = tp.resource.name, numCellsNeeded = cellsNeeded)
use(resource = tp.resource, delayDuration = tp.processTime)
entryLocation = tp.resource.name
}
}Conveyor instances share a location; transferTo() moves the entity onto the next conveyor and returns a new ConveyorRequestIfc for the ride (a feeder can also merge into the mid-point of a main conveyor)if/when picks which conveyor to transferToval cr = requestConveyor(conveyor = conveyor1, entryLocation = areaA, numCellsNeeded = 1)
rideConveyor(conveyorRequest = cr, destination = sorting)
val tr = transferTo(conveyorRequest = cr, nextConveyor = conveyor3, entryLocation = sorting)
rideConveyor(conveyorRequest = tr, destination = areaC)
exitConveyor(conveyorRequest = tr)Conveyor.builder or ConveyorSegments + Segment; a conveyor is circular when its start and end locations coinciderequestConveyor, rideConveyor, exitConveyor, convey (request + ride + exit), and transferTo (move between conveyors)exitConveyor; non-accumulating conveyors are a poor fit for work-on-conveyor unless perfectly balancedtransferTo and from circular conveyors