def render(fname): with open(fname, 'rb') as fh: noisy_model, _loaded_sm_noise = pickle.load(fh) render_engine.load_object(objloader.ShapeModel(data=noisy_model), obj_idx, smooth=sm.asteroid.render_smooth_faces) return cv2.resize( ab.render(shadows=True, reflection=RenderEngine.REFLMOD_LUNAR_LAMBERT), size)
def apply_noise(model, support=None, L=None, len_sc=SHAPE_MODEL_NOISE_LEN_SC, noise_lv=SHAPE_MODEL_NOISE_LV['lo'], only_z=False): noisy_points, avg_dev, L = points_with_noise(points=np.array(model.vertices), support=support, L=L, len_sc=len_sc, noise_lv=noise_lv, only_z=only_z) data = model.as_dict() data['vertices'] = noisy_points from iotools import objloader noisy_model = objloader.ShapeModel(data=data) noisy_model.recalc_norms() return noisy_model, avg_dev, L
def load_noisy_shape_model(self, sm, i): try: if self._constant_sm_noise: if self._loaded_sm_noise is not None: return self._loaded_sm_noise fname = sm.asteroid.constant_noise_shape_model[self._smn_cache_id] else: fname = self._cache_file(i, prefix=self.noisy_sm_prefix)+'_'+self._smn_cache_id+'.nsm' with open(fname, 'rb') as fh: noisy_model, self._loaded_sm_noise = pickle.load(fh) self.render_engine.load_object(objloader.ShapeModel(data=noisy_model), self.obj_idx, smooth=self._smooth_faces) except (FileNotFoundError, EOFError): self._loaded_sm_noise = None return self._loaded_sm_noise
def loadObject(self, noisy_model=None): genList = self.gl.glGenLists(1) self.gl.glNewList(genList, self.gl.GL_COMPILE) self.gl.glBegin(self.gl.GL_TRIANGLES) # GL_POLYGON? self.setColor(self._fgColor) #self.gl.glEnable(self.gl.GL_COLOR_MATERIAL); #self.gl.glMaterialfv(self.gl.GL_FRONT, self.gl.GL_SPECULAR, (0,0,0,1)); #self.gl.glMaterialfv(self.gl.GL_FRONT, self.gl.GL_SHININESS, (0,)); if self.systemModel.asteroid.real_shape_model is None: rsm = self.systemModel.asteroid.real_shape_model = objloader.ShapeModel( fname=self.systemModel.asteroid.target_model_file) else: rsm = self.systemModel.asteroid.real_shape_model if noisy_model is not None: sm = noisy_model # elif self._add_shape_model_noise and not BATCH_MODE: #sup = objloader.ShapeModel(fname=SHAPE_MODEL_NOISE_SUPPORT) #sm, noise, L = tools.apply_noise(rsm, support=np.array(sup.vertices)) # sm, noise, L = tools.apply_noise(rsm) else: sm = rsm for triangle, norm, tx in sm.faces: self.triangle(sm.vertices[triangle[0]], sm.vertices[triangle[1]], sm.vertices[triangle[2]], sm.normals[norm]) self.gl.glEnd() self.gl.glEndList() if DEBUG: # assume all 32bit (4B) variables, no reuse of vertices # => triangle count x (3 vertices + 1 normal) x 3d vectors x bytes per variable mem_needed = len(sm.faces) * 4 * 3 * 4 print('3D model mem use: %.0fx %.0fB => %.1fMB' % (len(sm.faces), 4 * 3 * 4, mem_needed / 1024 / 1024)) self._object = genList
if __name__ == '__main__': if len(sys.argv) < 3 or sys.argv[2] not in ('hi', 'med', 'lo'): print('USAGE: python %s <mission> <sm-quality: hi|med|lo>' % (sys.argv[0], )) quit() mission = sys.argv[1] sm_quality = sys.argv[2] noise = {'hi': '', 'med': 'lo', 'lo': 'hi'}[sm_quality] sm = get_system_model(mission) with open(sm.asteroid.constant_noise_shape_model[noise], 'rb') as fh: noisy_model, sm_noise = pickle.load(fh) renderer = RenderEngine(sm.view_width, sm.view_height, antialias_samples=0) obj_idx = renderer.load_object(objloader.ShapeModel(data=noisy_model), smooth=sm.asteroid.render_smooth_faces) algo = AlgorithmBase(sm, renderer, obj_idx) cache_path = os.path.join(CACHE_DIR, mission) # i = 0 for fn in os.listdir(cache_path): m = re.match('^(' + mission + r'_(\d+))\.lbl$', fn) if m and float(m[2]) < 2000: base_path = os.path.join(cache_path, m[1]) sm.load_state(base_path + '.lbl') # save state in a more user friendly way sm.export_state(base_path + '_meta.csv') # render
def __init__(self, hi_res_shape_model=False, rosetta_batch='default'): super(ChuryumovGerasimenko, self).__init__() self.name = '67P/Churyumov-Gerasimenko' # from http://imagearchives.esac.esa.int/index.php?/category/167/start-224 # self._image_db_path = os.path.join(SCRIPT_DIR, '../data/rosetta-mtp017') self.rosetta_batch = 'mtp006' if rosetta_batch == 'default' else rosetta_batch self.image_db_path = os.path.join(BASE_DIR, 'data/rosetta-' + self.rosetta_batch) self.target_model_file = os.path.join(BASE_DIR, 'data/67p-17k.obj') xtra_hires = os.path.join( BASE_DIR, 'data/original-shapemodels/67P_C-G_shape_model_MALMER_2015_11_20-in-km.obj' ) if os.path.exists(xtra_hires): self.hires_target_model_file = xtra_hires else: self.hires_target_model_file = os.path.join( BASE_DIR, 'data/67p-83k-b.obj') print(('Using lower quality shape model for synthetic navcam ' + 'images as highest quality shape model not found: %s') % xtra_hires) self.hires_target_model_file_textures = False self.render_smooth_faces = False self.reflmod_params = { 1: ChuryumovGerasimenko.LUNAR_LAMBERT_PARAMS, # REFLMOD_LUNAR_LAMBERT 2: ChuryumovGerasimenko.HAPKE_PARAMS, # REFLMOD_HAPKE } # done using `make-const-noise-shapemodel.py data/67p-83k-b.obj data/67p-17k.obj data/67p-17k.nsm` self.constant_noise_shape_model = { '': os.path.join( BASE_DIR, 'data/67p-17k.nsm' ), # same as target_model_file but includes error estimate 'lo': os.path.join(BASE_DIR, 'data/67p-4k.nsm'), # 1/4 the vertices 'hi': os.path.join(BASE_DIR, 'data/67p-1k.nsm'), # 1/17 the vertices } sample_image = { 'mtp006': 'ROS_CAM1_20140808T140718', 'mtp007': 'ROS_CAM1_20140902T113852', # ROS_CAM1_20140902T113852, ROS_CAM1_20140923T060854 'mtp017': 'ROS_CAM1_20150630T230217', # ROS_CAM1_20150603T094509, ROS_CAM1_20150612T230217 'mtp024': 'ROS_CAM1_20160112T230217', # ROS_CAM1_20151216T060218, ROS_CAM1_20160112T230217 'mtp025': 'ROS_CAM1_20160209T231753', # ROS_CAM1_20160113T060218, ROS_CAM1_20160209T231753 'mtp026': 'ROS_CAM1_20160301T131104', # ROS_CAM1_20160210T060423, ROS_CAM1_20160301T131104, ROS_CAM1_20160308T231754 }[self.rosetta_batch] self.sample_image_file = os.path.join(self.image_db_path, sample_image + '_P.png') self.sample_image_meta_file = os.path.join(self.image_db_path, sample_image + '.LBL') self.real_shape_model = objloader.ShapeModel( fname=self.hires_target_model_file if hi_res_shape_model else self. target_model_file) self.max_radius = 3000 # in meters, maximum extent of object from asteroid frame coordinate origin self.mean_radius = 2000 # for cross section, assume spherical object and 2km radius self.mean_cross_section = math.pi * self.mean_radius**2 # epoch for orbital elements, 2010-Oct-22.0 TDB self.oe_epoch = Time(2455491.5, format='jd') # orbital elements (from https://ssd.jpl.nasa.gov/sbdb.cgi) # reference: JPL K154/1 (heliocentric ecliptic J2000) self.eccentricity = .6405823233437267 self.semimajor_axis = 3.464737502510219 * const.au self.inclination = math.radians(7.043680712713979) self.longitude_of_ascending_node = math.radians(50.18004588418096) self.argument_of_periapsis = math.radians(12.69446409956478) self.mean_anomaly = math.radians(91.76808585530111) # other self.aphelion = 5.684187101644357 * const.au self.perihelion = 1.245287903376082 * const.au self.orbital_period = 2355.612944885578 * 24 * 3600 # seconds # self.true_anomaly = math.radians(145.5260853202137 ??) # rotation period # from http://www.aanda.org/articles/aa/full_html/2015/11/aa26349-15/aa26349-15.html # - 12.4043h (2014 aug-oct) # from http://www.sciencedirect.com/science/article/pii/S0019103516301385?via%3Dihub # - 12.4304h (19 May 2015) # - 12.305h (10 Aug 2015) self.rot_epoch = Time('J2000') # self.rotation_velocity = 2*math.pi/12.4043/3600 # prograde, in rad/s # --- above seems incorrect based on the pics, own estimate # based on ROS_CAM1_20150720T165249 - ROS_CAM1_20150721T075733 if False: self.rotation_velocity = 2 * math.pi / 12.4043 / 3600 else: # variable rotation velocity correction in degrees per day correction = { 'default': -0.4 / 25, # 2014-08-01 - 2014-09-02 'mtp006': 0.006088, # 2014-08-01 - 2014-09-02 'mtp007': 0.011987, # 2014-09-02 - 2014-09-23 'mtp017': -0.652648, # 2015-06-03 - 2015-06-30 'mtp024': 19.170419, # 2015-12-16 - 2016-01-12 'mtp025': 19.623067, # 2016-01-13 - 2016-02-09 'mtp026': 19.857628, # 2016-02-10 - 2016-03-08 }[rosetta_batch] self.rotation_velocity = 2 * math.pi / 12.4043 / 3600 + math.radians( correction) / 24 / 3600 # 0.3754 # for rotation phase shift, will use as equatorial longitude of # asteroid zero longitude (cheops) at J2000, based on 20150720T165249 # papar had 114deg in it # for precession cone center (J2000), paper had 69.54, 64.11 if False: tlat, tlon, tpm = 69.54, 64.11, 114 else: # rotation phase shift in degrees for different batches tpm = { 'default': -9, # 2014-08-01 - 2014-09-02 'mtp006': -127.05, # 2014-08-01 - 2014-09-02 'mtp007': -158.68, # 2014-09-02 - 2014-09-23 'mtp017': -150.09, # 2015-06-03 - 2015-06-30 'mtp024': 83.90, # 2015-12-16 - 2016-01-12 'mtp025': -46.27, # 2016-01-13 - 2016-02-09 'mtp026': 13.40, # 2016-02-10 - 2016-03-08 }[rosetta_batch] tlat, tlon = 64.11, 69.54 self.rotation_pm = math.radians(tpm) self.axis_latitude, self.axis_longitude = \ tuple(map(math.radians, (tlat, tlon) if USE_ICRS else \ tools.equatorial_to_ecliptic(tlat * units.deg, tlon * units.deg))) self.precession_cone_radius = math.radians( 0.14) # other paper 0.15+-0.03 deg self.precession_period = 10.7 * 24 * 3600 # other paper had 11.5+-0.5 days self.precession_pm = math.radians(0.288) self.set_defaults()
res = tools.poly_line_intersect(((0, 0, 1), (0, 1, 1), (1, 0, 1)), ((0, 0, 0), (.3, .7, 1))) print('%s' % res) quit() assert len( sys.argv ) == 4, 'USAGE: %s [full-res-model] [target-model] [output]' % sys.argv[0] full_res_model = os.path.join(BASE_DIR, sys.argv[1]) infile = os.path.join(BASE_DIR, sys.argv[2]) outfile = os.path.join(BASE_DIR, sys.argv[3]) sc = 1000 # bennu in meters, ryugu & 67P in km # load shape models obj_fr = objloader.ShapeModel(fname=full_res_model) obj = objloader.ShapeModel(fname=infile) faces = np.array([f[0] for f in obj.faces], dtype='uint') vertices = np.array(obj.vertices) full_vertices = np.array(obj_fr.vertices) timer = tools.Stopwatch() timer.start() devs = get_model_errors(full_vertices, vertices, faces) timer.stop() # doesnt work: tools.intersections.parallel_diagnostics(level=4) p50 = np.median(devs) p68, p95, p99 = np.percentile(np.abs(devs - p50), (68, 95, 99.7))
def __init__(self, hi_res_shape_model=False): super(DidymosSecondary, self).__init__() self.name = 'Didymos Secondary' self.image_db_path = None # use ryugu model for this, ryugu ~162m diameter, ryugu-big ~772m diameter (Didy2 & Didy1) self.target_model_file = os.path.join(BASE_DIR, 'data/ryugu+tex-d2-16k.obj') self.hires_target_model_file = os.path.join(BASE_DIR, 'data/ryugu+tex-d2-98k.obj') self.constant_noise_shape_model = { '' : os.path.join(BASE_DIR, 'data/ryugu+tex-d2-16k.nsm'), # same as target_model_file but includes error estimate 'lo': os.path.join(BASE_DIR, 'data/ryugu+tex-d2-4k.nsm'), # 1/3 the vertices 'hi': '', #os.path.join(BASE_DIR, 'data/ryugu+tex-d2-4k.nsm'), # 1/10 the vertices } self.sample_image_file = None self.sample_image_meta_file = None self.real_shape_model = objloader.ShapeModel( fname=self.hires_target_model_file if hi_res_shape_model else self.target_model_file) self.render_smooth_faces = False if hi_res_shape_model else True self.reflmod_params = { 1: DidymosPrimary.LUNAR_LAMBERT_PARAMS, # REFLMOD_LUNAR_LAMBERT 2: DidymosPrimary.HAPKE_PARAMS, # REFLMOD_HAPKE } # for cross section, assume spherical object self.max_radius = 85 # in meters, maximum extent of object from asteroid frame coordinate origin self.mean_radius = 163/2 # in meters self.mean_cross_section = math.pi * self.mean_radius ** 2 # epoch for orbital elements, 2019-Apr-27.0 TDB self.oe_epoch = Time(2458600.5, format='jd') # orbital elements (from https://ssd.jpl.nasa.gov/sbdb.cgi?sstr=2065803#content) # reference: JPL 134 (heliocentric ecliptic J2000) self.eccentricity = .3840204901532592 self.semimajor_axis = 1.644267950023408 * const.au self.inclination = math.radians(3.408560852149408) self.longitude_of_ascending_node = math.radians(73.20707998527304) self.argument_of_periapsis = math.radians(319.3188822767833) self.mean_anomaly = math.radians(124.6176776030496) # other, not used self.aphelion = 2.275700534134692 * const.au self.perihelion = 1.012835365912124 * const.au self.orbital_period = 770.1180709731267 * 24 * 3600 # seconds # self.true_anomaly = math.radians(145.5260853202137 ??) # rotation period 11.92h from https://ssd.jpl.nasa.gov/sbdb.cgi?sstr=2065803#content self.rot_epoch = Time('J2000') self.rotation_velocity = 2 * math.pi / (11.92 * 3600) # rad/s # asteroid rotation axis in equatorial coordinates ra, de, tpm = 310, -84, 0 # ra=lon, de=lat self.rotation_pm = math.radians(tpm) self.axis_latitude, self.axis_longitude = \ tuple(map(math.radians, (de, ra) if USE_ICRS else \ tools.equatorial_to_ecliptic(de * units.deg, ra * units.deg))) self.precession_cone_radius = None self.precession_period = None self.precession_pm = None self.set_defaults()