| import numpy |
| import cv2 |
| import time |
| import sys |
| import os |
| import random |
| from airsim import * |
|
|
| def radiance(absoluteTemperature, emissivity, dx=0.01, response=None): |
| """ |
| title:: |
| radiance |
| |
| description:: |
| Calculates radiance and integrated radiance over a bandpass of 8 to 14 |
| microns, given temperature and emissivity, using Planck's Law. |
| |
| inputs:: |
| absoluteTemperature |
| temperture of object in [K] |
| |
| either a single temperature or a numpy |
| array of temperatures, of shape (temperatures.shape[0], 1) |
| emissivity |
| average emissivity (number between 0 and 1 representing the |
| efficiency with which it emits radiation; if 1, it is an ideal |
| blackbody) of object over the bandpass |
| |
| either a single emissivity or a numpy array of emissivities, of |
| shape (emissivities.shape[0], 1) |
| dx |
| discrete spacing between the wavelengths for evaluation of |
| radiance and integration [default is 0.1] |
| response |
| optional response of the camera over the bandpass of 8 to 14 |
| microns [default is None, for no response provided] |
| |
| returns:: |
| radiance |
| discrete spectrum of radiance over bandpass |
| integratedRadiance |
| integration of radiance spectrum over bandpass (to simulate |
| the readout from a sensor) |
| |
| author:: |
| Elizabeth Bondi |
| """ |
| wavelength = numpy.arange(8,14,dx) |
| c1 = 1.19104e8 |
| |
| |
| c2 = 1.43879e4 |
| if response is not None: |
| radiance = response * emissivity * (c1 / ((wavelength**5) * \ |
| (numpy.exp(c2 / (wavelength * absoluteTemperature )) - 1))) |
| else: |
| radiance = emissivity * (c1 / ((wavelength**5) * (numpy.exp(c2 / \ |
| (wavelength * absoluteTemperature )) - 1))) |
| if absoluteTemperature.ndim > 1: |
| return radiance, numpy.trapz(radiance, dx=dx, axis=1) |
| else: |
| return radiance, numpy.trapz(radiance, dx=dx) |
|
|
|
|
| def get_new_temp_emiss_from_radiance(tempEmissivity, response): |
| """ |
| title:: |
| get_new_temp_emiss_from_radiance |
| |
| description:: |
| Transform tempEmissivity from [objectName, temperature, emissivity] |
| to [objectName, "radiance"] using radiance calculation above. |
| |
| input:: |
| tempEmissivity |
| numpy array containing the temperature and emissivity of each |
| object (e.g., each row has: [objectName, temperature, emissivity]) |
| response |
| camera response (same input as radiance, set to None if lacking |
| this information) |
| |
| returns:: |
| tempEmissivityNew |
| tempEmissivity, now with [objectName, "radiance"]; note that |
| integrated radiance (L) is divided by the maximum and multiplied |
| by 255 in order to simulate an 8 bit digital count observed by the |
| thermal sensor, since radiance and digital count are linearly |
| related, so it's [objectName, simulated thermal digital count] |
| |
| author:: |
| Elizabeth Bondi |
| """ |
| numObjects = tempEmissivity.shape[0] |
|
|
| L = radiance(tempEmissivity[:,1].reshape((-1,1)).astype(numpy.float64), |
| tempEmissivity[:,2].reshape((-1,1)).astype(numpy.float64), |
| response=response)[1].flatten() |
| L = ((L / L.max()) * 255).astype(numpy.uint8) |
|
|
| tempEmissivityNew = numpy.hstack(( |
| tempEmissivity[:,0].reshape((numObjects,1)), |
| L.reshape((numObjects,1)))) |
|
|
| return tempEmissivityNew |
|
|
| def set_segmentation_ids(segIdDict, tempEmissivityNew, client): |
| """ |
| title:: |
| set_segmentation_ids |
| |
| description:: |
| Set stencil IDs in environment so that stencil IDs correspond to |
| simulated thermal digital counts (e.g., if elephant has a simulated |
| digital count of 219, set stencil ID to 219). |
| |
| input:: |
| segIdDict |
| dictionary mapping environment object names to the object names in |
| the first column of tempEmissivityNew |
| tempEmissivityNew |
| numpy array containing object names and corresponding simulated |
| thermal digital count |
| client |
| connection to AirSim (e.g., client = MultirotorClient() for UAV) |
| |
| author:: |
| Elizabeth Bondi |
| """ |
|
|
| |
| success = client.simSetSegmentationObjectID("[\w]*", 0, True); |
| if not success: |
| print('There was a problem setting all segmentation object IDs to 0. ') |
| sys.exit(1) |
|
|
| |
| |
| for key in segIdDict: |
| objectID = int(tempEmissivityNew[numpy.where(tempEmissivityNew == \ |
| segIdDict[key])[0],1][0]) |
|
|
| success = client.simSetSegmentationObjectID("[\w]*"+key+"[\w]*", |
| objectID, True); |
| if not success: |
| print('There was a problem setting {0} segmentation object ID to {1!s}, or no {0} was found.'.format(key, objectID)) |
| |
| time.sleep(0.1) |
|
|
|
|
| if __name__ == '__main__': |
|
|
| |
| client = MultirotorClient() |
| client.confirmConnection() |
| |
| |
| cubeList = client.simListSceneObjects('.*?Cube.*?') |
| cubeDict = {} |
| for x in cubeList: |
| cubeDict[x] = 'tree' |
| |
|
|
| segIdDict = { |
| 'Floor':'soil', |
| } |
| |
| segIdDict.update(cubeDict) |
| |
| |
| |
| tempEmissivity = numpy.array([['elephant',290,0.96], |
| ['zebra',298,0.98], |
| ['rhinoceros',291,0.96], |
| ['hippopotamus',290,0.96], |
| ['crocodile',295,0.96], |
| ['human',292,0.985], |
| ['tree',273,0.952], |
| ['grass',273,0.958], |
| ['soil',278,0.914], |
| ['shrub',300,0.3], |
| ['truck',273,0.8], |
| ['water',273,0.96]]) |
| |
| """ |
| #summer |
| tempEmissivity = numpy.array([['elephant',298,0.96], |
| ['zebra',307,0.98], |
| ['rhinoceros',299,0.96], |
| ['hippopotamus',298,0.96], |
| ['crocodile',303,0.96], |
| ['human',301,0.985], |
| ['tree',293,0.952], |
| ['grass',293,0.958], |
| ['soil',288,0.914], |
| ['shrub',293,0.986], |
| ['truck',293,0.8], |
| ['water',293,0.96]]) |
| """ |
|
|
| |
| response = None |
| camResponseFile = 'camera_response.npy' |
| try: |
| numpy.load(camResponseFile) |
| except: |
| print("{} not found. Using default response.".format(camResponseFile)) |
|
|
| |
| tempEmissivityNew = get_new_temp_emiss_from_radiance(tempEmissivity, |
| response) |
|
|
| |
| set_segmentation_ids(segIdDict, tempEmissivityNew, client) |