Challenge 2
Speed Runs: optimising truck payload and cycle speeds
Description
Challenge Statement
At the Cowal Gold Mine, trucks transport ore over many km’s from the open pit. The more ore they take, the slower they move. Can you optimise for speed and tonnage?
Background
The Cowal operation is an open pit mining operation with production from a number of different areas within a large, single pit. As a result of the general site configuration and layout, haul distances, in particular for waste disposal, is the longest of all open pit operations across the company. Material is typically hauled for a 4km distance at a 1:10 incline and thereafter another 1-3km on a reasonably flat surface to the crusher, stockpiles or waste rock dumps depending on material type. A fleet monitoring system (MineStar) is installed and fully operational with a significant amount of individual truck cycle data available. Mining is carried out with a company-owned fleet of mining equipment that includes 2 x Liebherr 994 backhoe excavators, 1 x Hitachi 3600 Excavator and 16 x Cat 789 dump trucks. The Challenge
The key question remains: What is the optimum payload vs haul speed trade-off and how does that change with increases to the depth of the pit and haulage distances to future waste dump locations? The Opportunity
At present the operating philosophy is to “light load” trucks to ensure they reach at least second gear on the way out on the ramp. Payloads are controlled, however given the haul distance required, every tonne counts. If the optimum cycle speeds and payload can be determined, there is potential to improve productivity and reduce costs across the haulage fleet. Considerations
Critical areas to consider include:
For any given haulage cycle, can payload be “calibrated” to a specific location using historical VIMS data?
In excess of two years VIMS data is available for analysis that could be “mined” to establish the optimum trade-off!
Can payload optimisation be done in real time and displayed to the operator?
Data Summary
TBC Mentors
Ryan Kare - Lead Mentor
Elam Athimoolam
In [153]:
import pandas
import json
In [ ]:
In [ ]:
In [154]:
pitconf = pandas.read_excel('/home/wcmckee/data/Truck_Spec.xlsx', sheetname='SiteInfo', index_col='Parameter')
In [155]:
rimpulldata = pandas.read_excel('/home/wcmckee/data/Truck_Spec.xlsx', sheetname='Rimpull')
In [156]:
print(rimpulldata)
In [114]:
rimpulldata
Out[114]:
In [151]:
def createtruckspec(truckid, trucktype, emptyweight, maxoperatingweight):
return({'truckid' : truckid, 'TruckType' : trucktype, 'EmptyWeight' : emptyweight, 'maxoperatingweight' : maxoperatingweight})
In [152]:
createtruckspec(450, "789C", 114114, 317514.85)
Out[152]:
In [ ]:
In [ ]:
@app.route('/getruckspec')
def getruckspec():
# give it truck id and returns back stats about that truck.
# todo: return back truck segment details also.
#localhost:5555/getruckspec?truckid=410
#returns back:
#{"EmptyWeight": 124114, "MaxOperatingWeight": 317514.85, "TruckType": "789C"}
truckid = request.args.get('truckid')
#truckid = request.args.get("truckid")
return(jsonify({'truckid' : truckid, 'EmptyWeight' : truckdicspec['EmptyWeight'][truckid],
'MaxOperatingWeight' : truckdicspec['MaxOperatingWeight'][truckid], 'TruckType' : truckdicspec['TruckType'][truckid]}))
In [104]:
with open('/home/wcmckee/rimpulldata.json', 'w') as rimwr:
rimwr.write(rimpulldata.to_json())
In [123]:
with open('/home/wcmckee/rimpulldata.json', 'r') as rimrd:
rimrda = (rimrd.read())
In [133]:
forjs = json.loads(rimrda)
In [135]:
forjs['Speed (km)']['12']
Out[135]:
In [139]:
forjs['Force (kgf)']['12']
Out[139]:
In [ ]:
In [ ]:
In [145]:
def lookrimid(rimid):
return({ 'speed' : forjs['Speed (km)'][str(rimid)], 'force' : forjs['Force (kgf)'][str(rimid)], 'id' : rimid})
In [146]:
lookrimid(12)
Out[146]:
In [148]:
with open('/home/wcmckee/rimpulldata.json', 'r') as rimrd:
rimjsconv = (rimrd.read())
forjs = json.loads(rimjsconv)
In [150]:
forjs['Force (kgf)']
Out[150]:
In [ ]:
In [ ]:
In [ ]:
In [137]:
lookrimid(12)
Out[137]:
In [ ]:
In [ ]:
In [129]:
print(forjs['Speed (km)'])
In [ ]:
In [ ]:
In [125]:
rimrda
Out[125]:
In [ ]:
In [ ]:
In [ ]:
In [121]:
for putf in pitconf.values:
print(putf)
In [ ]:
In [118]:
print(pitconf)
In [ ]:
In [95]:
import json
In [ ]:
In [96]:
with open('/home/wcmckee/pitconfig.json', 'w') as pitw:
pitw.write(pitconf.to_json())
In [97]:
with open('/home/wcmckee/pitconfig.json', 'r') as pitr:
pitjs = pitr.read()
pitlo = json.loads(pitjs)
In [98]:
print(pitlo)
In [88]:
pitlo.keys()
Out[88]:
In [92]:
for pitl in pitlo.values():
print(pitl['1'])
In [ ]:
In [ ]:
In [ ]:
In [ ]:
truk= pandas.read_excel('/home/wcmckee/data/Truck_Spec.xlsx', index_col='Truckid')
In [ ]:
In [ ]:
print(truk)
In [ ]:
with open('/home/wcmckee/truckspec.json', 'w') as truc:
truc.write(truk.to_json())
In [ ]:
cat /home/wcmckee/truckspec.json
In [ ]:
with open('/home/wcmckee/truckspec.json', 'r') as truatm:
tread = truatm.read()
#print(truatm.read())
In [ ]:
truckdicspec = json.loads(tread)
In [ ]:
In [ ]:
truckdicspec
In [ ]:
truckdicspec['TruckType']['418']
In [ ]:
def gettruck(truckid):
with open('/home/wcmckee/truckspec.json', 'r') as truatm:
tread = truatm.read()
truckdicspec = json.loads(tread)
return({'EmptyWeight' : truckdicspec['EmptyWeight'][truckid],
'MaxOperatingWeight' : truckdicspec['MaxOperatingWeight'][truckid], 'TruckType' : truckdicspec['TruckType'][truckid]})
In [ ]:
gettruck('410')
In [ ]:
import json
In [ ]:
tred = json.loads(trurd.read())
In [ ]:
#create database of trucks from existing file.
In [ ]:
somedict = dict()
In [ ]:
somedict.update({truk['Truck ID'] : dict({'test' : 'this is test'})})
In [ ]:
In [ ]:
for truk['Truck ID'] in truk:
print(truk['Truck ID'])
In [ ]:
In [ ]:
In [ ]:
truk.values
In [ ]:
truk.keys()
In [ ]:
In [ ]:
In [ ]:
In [ ]:
with open('/home/wcmckee/truckspec.json', 'r') as trurd:
#print(trurd.read())
tred = json.loads(trurd.read())
print(tred)
In [ ]:
import sqlite3
In [ ]:
connid = sqlite3.connect('identity.db')
In [ ]:
connid
In [ ]:
c = connid.cursor()
In [ ]:
def createdb(nameofdb):
connid = sqlite3.connect('{}.db'.format(nameofdb))
c.execute('''CREATE TABLE truckspec
(truckid, trucktype, emptyweight, maxgrossoperatingweight)''')
c = connid.cursor()
c.close()
return(nameofdb)
In [ ]:
createdb('testing')
In [ ]:
In [ ]:
createdb('truckspec')
In [ ]:
In [ ]:
c.execute('''CREATE TABLE truckspec
(truckid, trucktype, emptyweight, maxgrossoperatingweight)''')
In [ ]:
def createtruk(truckid, trucktype, emptyweight, maxgrossoperatingweight):
connid = sqlite3.connect('truckspec.db')
c = connid.cursor()
c.execute("INSERT INTO truckspec VALUES ('{}','{}','{}', '{}')".format(truckid, trucktype, emptyweight, maxgrossoperatingweight))
connid.commit()
connid.close()
return({truckid : dict({'trucktype' : trucktype, 'emptyweight' : emptyweight,
'maxgrossoperatingweight' : maxgrossoperatingweight})})
In [ ]:
def select_all_tasks():
"""
Query all rows in the tasks table
:param conn: the Connection object
:return:
"""
connid = sqlite3.connect('truckspec.db')
cur = connid.cursor()
cur.execute("SELECT * truckspec;")
rows = cur.fetchall()
for row in rows:
print(row)
In [ ]:
select_all_tasks()
In [ ]:
In [ ]:
In [ ]:
createtruk(420, '789C', 124114, 317514.85)
In [ ]:
createtruk(421, '789C', 114114, 317514.85)
In [ ]:
cat /home/wcmckee/truckspec.json
In [ ]:
truk.to_json()
In [ ]:
truk.sort_values(by='Truck ID')
an api on truck spec
{401 : dict({'type' : '789c', 'emptyweight' : 124114, 'maxweight' : 317514.85})}
In [ ]:
forohon = ({401 : dict({'type' : '789c', 'emptyweight' : 124114, 'maxweight' : 317514.85})})
In [ ]:
forohon
In [ ]:
tru.loc[tru['Truck'] == 'TRH404']
In [ ]:
tulo = tru.loc('TRH404')
In [ ]:
tulo.name
In [ ]:
print(tulo())
In [ ]:
roadsegdata = {'Road-segment-data' : dict({'Truck' : 'ID of the 16 CAT trucks',
'Description - CR' : 'Grade the truck needs to climb',
'Payload' : 'Weight in kg excluding truck weight.',
'Start velocity' : 'Force the truck starts the grade in km/hr.',
'End velocity' : 'Force the truck exits the grade in km/hr.',
'EfhLength' : 'Not valid as it is an old measure of distance.',
'Target duration' : 'Optimal time for the truck to cover the grade in seconds.',
'Duration calculated' : 'Actual time for the truck to cover the grade in seconds.',
'Slope length' : 'Slope length(curvature distance) in meters.',
'Rise height' : 'Measure of the slope in meters.',
'StartWayPoint X,Y,Z' : 'Starting location of the grade',
'EndWayPoint X,Y,Z' : 'Ending location of the grade.'})}
In [ ]:
print(roadsegdata)
In [ ]:
truckcycledict = {'Truck cycle' : dict({'Date' : 'Date the data was recorded.',
'Source stage' : 'Stage the truck starts from.',
'Source bench' : 'Bench the truck starts from.',
'Destination name' : 'Unloading dump.',
'Truck' : 'ID of the 16 CAT trucks',
'Travelling empty duration' : 'Travelling time in seconds when the truck is empty. (return time duration',
'Travelling full duration' : 'Travelling time in seconds when the truck is loaded.',
'Payload' : 'Weight in kg excluding truck weight.',
'Full slope length' : 'Distance in meters from bench to dump location.',
'Empty slope length' : 'Return distance in meters.',
'Inpit ramp length' : 'Distance from the bench to the exit of the pit in meters.',
'Inpit ramp grade' : 'Inclination angle of the in-pit grade in %',
'Dump ramp length' : 'Distance from the exit of pit to the dump location.',
'Dump ramp grade' : 'Inclination angle after the exit of pit to the dump location in %.'})}
In [ ]:
trucyc = truckcycledict['Truck cycle']
In [ ]:
print(trucyc)
In [ ]:
for truc in trucyc:
print(truc)
In [ ]:
truckcycledict.update(roadsegdata)
In [ ]:
truckcy = json.dumps(truckcycledict)
In [ ]:
with open('/home/wcmckee/truckscycroad.json', 'w') as t:
t.write(truckcy)
In [ ]:
In [159]:
with open('/home/wcmckee/truckscycroad.json', 'r') as r:
#print(r.read())
decjs = json.loads(r.read())
In [ ]:
print({410 : dict({'Truck' : 410, 'Payload' : 100, })})
In [160]:
print(decjs['Road-segment-data'])
In [161]:
print(decjs['Truck cycle'])
In [ ]:
cat /home/wcmckee/truckscycroad.json
In [ ]:
for trucy in truckcycledict['Road-segment-data']:
print({trucy : dict({'example' : 'l33t', 'Description' : 'this is an example'})})
In [ ]:
def createlocation(truck, longitude, latitude):
return({'truck' : truck, 'longitude' : longitude, 'latitude' : latitude})
In [ ]:
import pandas
In [ ]:
descri = pandas.read_excel('/home/wcmckee/data/Road Segment Data.xlsx')
In [ ]:
dropcol = descri.drop('Unnamed: 0', axis=1)
In [ ]:
with open('/home/wcmckee/roadsegdatatest.json', 'w') as roaddrop:
roaddrop.write(dropcol.to_json())
In [ ]:
with open('/home/wcmckee/roadsegdatatest.json', 'r') as roard:
roadjsconv = roard.read()
In [ ]:
import json
In [ ]:
roadjslod = json.loads(roadjsconv)
In [ ]:
import getpass
In [ ]:
getpass.getuser()
In [ ]:
In [ ]:
for paka in roadjslod.keys():
print(roadjslod[paka]['127'])
In [ ]:
startdict ={'StartWaypoint' : dict({'x' : int(samptru['StartWaypointCoordsX']),
'y' : int(samptru['StartWaypointCoordsY']),
'z' : int(samptru['StartWaypointCoordsZ']),
'velocity' : int(samptru['StartVelocity'])})}
In [ ]:
startdict
In [ ]:
def xyz(startx, starty, startz, startvelo, endx, endy, endz, endvelo):
return({'startwaypoint' : dict({'x' : startx,
'y' : starty,
'z' : startz,
'velocity' : startvelo}),
'endwaypoint' : dict({'x' : endx, 'y' : endy, 'z' : endz,
'velocity' : endvelo})})
In [ ]:
xyz(86545, 36238, 1097, 13, 86578, 36354, 1097, 13)
In [ ]:
endist = {'EndWaypoint' : dict({'x' : int(samptru['EndWaypointCoordsX']),
'y' : int(samptru['EndWaypointCoordsY']),
'z' : int(samptru['StartWaypointCoordsZ']),
'velocity' : int(samptru['EndVelocity'])})}
In [ ]:
startdict.update(endist)
In [ ]:
{'stats' : dict({'Description-CR' : samptru['Description-CR']})}
In [ ]:
samdes = samptru['Description-CR']
In [ ]:
import requests
In [ ]:
reqge = requests.get('https://geocode.xyz/51.50354,-0.12768')
In [ ]:
rejs = (reqge.json)
In [ ]:
print(str(rejs))
In [ ]:
print(dict({'truck' : truck, dict({'startwaypoint' : {'longitude' : int(samptru['StartWaypointCoordsX'], 'latitude' : int(samptru['StartWaypointCoordsY']))}}
In [ ]:
print ({'truck' : 402, dict({'startwaypoint' : dict({'longitude' : 1, 'latitude' : 3})})
In [ ]:
{'startwaypoint' : dict({'longitude' : 1, 'latitude' : 3})}
In [157]:
trukxlc = pandas.read_excel('/home/wcmckee/data/Scenario1.xlsx')
In [ ]:
In [158]:
print(trukxlc['Destination 1'])
In [ ]:
trukcyc = pandas.read_csv('/home/wcmckee/data/Truck Cycle.csv', index_col='Truck')
In [ ]:
for trkey in trukcyc.keys():
trk = (trkey.replace(' ', '-'))
print(trk.lower())
In [ ]:
import json
In [ ]:
import random
In [ ]:
print(truckdicspec)
In [ ]:
with open('/home/wcmckee/truckspec.json', 'r') as truatm:
tread = truatm.read()
truckdicspec = json.loads(tread)
truckid = random.choice(truckdicspec)
In [ ]:
truits = trukcyc.iteritems()
In [ ]:
somedict = dict()
In [ ]:
somedict
In [ ]:
somelis = list()
In [ ]:
In [ ]:
for tru in truits:
#print(tru)
somelis.append(tru)
#somedict.update({tru : tru})
In [ ]:
for somel in somelis:
print(somel)
In [ ]:
for somel in somelis:
print(somel)
In [ ]:
import random
In [ ]:
random.choice()
In [ ]:
def createtruckcyc(date, sourcestage, sourcebench, destinationname,
travellingemptyduration, travellingfullduration, payload,
fullslopelength, emptyslopelength, inpitramplength,
inpitrampgrade, dumpramplength, dumprampgrade):
return (dict({'date' : date, 'sourcestage' : sourcebench, 'sourcebench' : sourcebench,
'destinationname' : destinationname,
'travellingemptyduration' : travellingemptyduration,
'travellingfullduration' : travellingfullduration,
'payload' : payload, 'fullslopelength' : fullslopelength,
'emptyslopelength' : emptyslopelength,
'inpitramplength' : inpitramplength,
'inpitrampgrade' : inpitrampgrade, 'dumpramplength' : dumpramplength,
'dumprampgrade' : dumprampgrade}))
In [ ]:
import arrow
In [ ]:
timnow = arrow.now()
In [ ]:
print(timnow)
In [ ]:
str(timnow.date())
In [ ]:
'9.34%', 336.00, '8.33%'
In [ ]:
createtruckcyc('01/01/2017', 'Stage G', '920', 'MW_PRIME', 0.0, 1009, 179.7, 3888.21, 3888.21,
42.94, 3108.02, '9.34%', 336.00, '8.33%')
In [ ]:
trjs = trukcyc.to_json
In [ ]:
In [ ]:
In [ ]:
with open('/home/wcmckee/truckdetail.json', 'w') as truckdet:
truckdet.write(trjs)
In [ ]:
trukd = pandas.read_json('/home/wcmckee/truckdetail.json')
In [ ]:
trukcyc.to_json
In [ ]:
In [ ]:
trujsn = (trukcyc.to_json)
In [ ]:
trujsn
In [ ]:
trujsn
In [ ]:
with open('/home/wcmckee/truckinfo.json', 'w') as truwri:
truwri.write(str(trujsn))
In [ ]:
In [ ]:
cat /home/wcmckee/truckinfo.json
In [ ]:
import arrow
In [ ]:
In [ ]:
def mkblogpost(blogpath, postname, tagblog):
raw = arrow.now()
fultim = raw.datetime
if postname + '.md' not in os.listdir(blogpath + '/posts'):
with open(blogpath + '/posts/' + postname + '.meta', 'w') as daympo:
daympo.write('.. title: {}\n.. slug: {}\n.. date: {}\n.. tags: {}\n.. link:\n.. description:\n.. type: text'.format(postname, postname, fultim, tagblog))
with open(blogpath + '/posts/' + postname + '.md', 'w') as daymark:
for toar in os.listdir(blogpath + '/galleries/' + raw.strftime("%Y") + '/' + raw.strftime("%m") + '/' + raw.strftime('%d')):
daymark.write('![{}]({}{})\n\n'.format(toar.replace('.png', ''), '/galleries/' + raw.strftime("%Y") + '/' + raw.strftime("%m") + '/' + raw.strftime('%d') + '/', toar))
In [ ]:
print(trukcyc['Destination name'])
In [ ]:
from flask import Flask, request, jsonify
import json
import getpass
myusr = getpass.getuser()
homepath = '/home/{}'.format(myusr)
app = Flask(__name__)
In [ ]:
with open('{}/truckspec.json'.format(homepath), 'r') as truatm:
#opens the truck spec json file.
tread = truatm.read()
truckdicspec = json.loads(tread)
with open('{}/roadsegdatatest.json'.format(homepath), 'r') as roard:
#opens the road seg data
roadjsconv = roard.read()
roadjslod = json.loads(roadjsconv)
In [ ]:
In [ ]:
@app.route('/getruckspec')
def getruckspec():
# give it truck id and returns back stats about that truck.
# todo: return back truck segment details also.
#localhost:5555/getruckspec?truckid=410
#returns back:
#{"EmptyWeight": 124114, "MaxOperatingWeight": 317514.85, "TruckType": "789C"}
truckid = request.args.get('truckid')
#truckid = request.args.get("truckid")
return(jsonify({'EmptyWeight' : truckdicspec['EmptyWeight'][truckid],
'MaxOperatingWeight' : truckdicspec['MaxOperatingWeight'][truckid], 'TruckType' : truckdicspec['TruckType'][truckid]}))
In [ ]:
@app.route('/getroadsegid')
def getroadsegid():
#localhost:5555/getroadsegid?segid=95
#give it id and return back road segiment details.
'''
returns back: {
"Description-CR": "GRD25-GRD26",
"DurationCalculated": 28.0,
"EfhLength": 157.9984208252,
"EndVelocity": 21.9239999982,
"EndWaypointCoordsX": 85976.84,
"EndWaypointCoordsY": 36378.8,
"EndWaypointCoordsZ_Q-CR": 885.02,
"LoadStateDirection_D-CR": "Reverse traversal full",
"Payload": 170900,
"RiseHeight": 0.15,
"SlopeLength": 148.8954144547,
"StartVelocity": 13.3919999989,
"StartWaypointCoordsX": 85987.63,
"StartWaypointCoordsY": 36257.25,
"StartWaypointCoordsZ": 885.05,
"TargetDuration": 11,
"Truck": "TRH405"
}
'''
segid = request.args.get('segid')
newdict = dict()
for paka in roadjslod.keys():
newdict.update({paka : roadjslod[paka][segid]})
return(jsonify(newdict))
#return('everything worked')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5555)
In [ ]:
from flask import Flask, request, jsonify
import json
import getpass
myusr = getpass.getuser()
homepath = '/home/{}'.format(myusr)
app = Flask(__name__)
with open('{}/truckspec.json'.format(homepath), 'r') as truatm:
#opens the truck spec json file.
tread = truatm.read()
truckdicspec = json.loads(tread)
with open('{}/roadsegdatatest.json'.format(homepath), 'r') as roard:
#opens the road seg data
roadjsconv = roard.read()
roadjslod = json.loads(roadjsconv)
@app.route('/getruckspec')
def getruckspec():
# give it truck id and returns back stats about that truck.
# todo: return back truck segment details also.
#localhost:5555/getruckspec?truckid=410
#returns back:
#{"EmptyWeight": 124114, "MaxOperatingWeight": 317514.85, "TruckType": "789C"}
truckid = request.args.get('truckid')
#truckid = request.args.get("truckid")
return(jsonify({'EmptyWeight' : truckdicspec['EmptyWeight'][truckid],
'MaxOperatingWeight' : truckdicspec['MaxOperatingWeight'][truckid], 'TruckType' : truckdicspec['TruckType'][truckid]}))
@app.route('/getroadsegid')
def getroadsegid():
#localhost:5555/getroadsegid?segid=95
#give it id and return back road segiment details.
'''
returns back: {
"Description-CR": "GRD25-GRD26",
"DurationCalculated": 28.0,
"EfhLength": 157.9984208252,
"EndVelocity": 21.9239999982,
"EndWaypointCoordsX": 85976.84,
"EndWaypointCoordsY": 36378.8,
"EndWaypointCoordsZ_Q-CR": 885.02,
"LoadStateDirection_D-CR": "Reverse traversal full",
"Payload": 170900,
"RiseHeight": 0.15,
"SlopeLength": 148.8954144547,
"StartVelocity": 13.3919999989,
"StartWaypointCoordsX": 85987.63,
"StartWaypointCoordsY": 36257.25,
"StartWaypointCoordsZ": 885.05,
"TargetDuration": 11,
"Truck": "TRH405"
}
'''
segid = request.args.get('segid')
newdict = dict()
for paka in roadjslod.keys():
newdict.update({paka : roadjslod[paka][segid]})
return(jsonify(newdict))
#return('everything worked')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5555)