def post_process(self): """ Generate the metrics from the stored raw ray trace results. """ data = self.traverse_results ## Check raw traverse results for continguous regions of no ground coverage. none_runs = [ len(list(grp)) for k, grp in itertools.groupby(data, lambda x: x) if k is None ] if none_runs and max(none_runs) >= self.contiguous: ## Fail because there is a contiguous region larger than allowed fwd = "Fail" aft = "Fail" no_fire_area = "Fail" else: trav_cen = get_translation(self.weapon.trans_trav) angles = np.array([x[0] for x in data if x[1] is not None]) muz_pts = np.array([x[1][0] for x in data if x[1] is not None]) gnd_pts = np.array([x[1][1] for x in data if x[1] is not None]) ## Distance along the ground gnd_dist = np.sqrt((trav_cen[0] - gnd_pts[:, 0])**2 + (trav_cen[2] - gnd_pts[:, 2])**2) ## Calculate the minimum shoot distance over contiguous regions mod_dist = grey_erosion(gnd_dist, self.contiguous, mode="wrap") ## Calculate an area metric (A = 0.5 * a.b.sin(c_ang)) num_tris = len(angles) no_fire_area = 0.0 for i in xrange(num_tris): next_ang = (angles[0] + 2 * pi) if i + 1 >= num_tris else angles[i + 1] c_ang = next_ang - angles[i] a = gnd_dist[i] b = gnd_dist[(i + 1) % num_tris] no_fire_area += 0.5 * a * b * sin(c_ang) ## Calculate min forward and aft shoot distance. fwd = np.max(mod_dist[np.where((angles >= 3 * pi / 2) | (angles <= pi / 2))]) aft = np.max(mod_dist[np.where((angles <= 3 * pi / 2) & (angles >= pi / 2))]) self.post_process_2d(angles, gnd_dist, mod_dist, no_fire_area, fwd, aft) if self.show_3d: self.post_process_3d(muz_pts, gnd_pts) ## Write results to json file and echo to log. out = { "min_fire_dist_fore_180": fwd, "min_fire_dist_aft_180": aft, "no_fire_area": no_fire_area } tba.write_results(out)
def post_process(self): """ Generate the metrics from the stored raw ray trace results. """ data = self.traverse_results ## Check raw traverse results for continguous regions of no ground coverage. none_runs = [len(list(grp)) for k, grp in itertools.groupby(data, lambda x:x) if k is None] if none_runs and max(none_runs) >= self.contiguous: ## Fail because there is a contiguous region larger than allowed fwd = "Fail" aft = "Fail" no_fire_area = "Fail" else: trav_cen = get_translation(self.weapon.trans_trav) angles = np.array([x[0] for x in data if x[1] is not None]) muz_pts = np.array([x[1][0] for x in data if x[1] is not None]) gnd_pts = np.array([x[1][1] for x in data if x[1] is not None]) ## Distance along the ground gnd_dist = np.sqrt((trav_cen[0] - gnd_pts[:, 0]) ** 2 + (trav_cen[2] - gnd_pts[:, 2]) ** 2) ## Calculate the minimum shoot distance over contiguous regions mod_dist = grey_erosion(gnd_dist, self.contiguous, mode="wrap") ## Calculate an area metric (A = 0.5 * a.b.sin(c_ang)) num_tris = len(angles) no_fire_area = 0.0 for i in xrange(num_tris): next_ang = (angles[0] + 2 * pi) if i + 1 >= num_tris else angles[i+1] c_ang = next_ang - angles[i] a = gnd_dist[i] b = gnd_dist[(i + 1) % num_tris] no_fire_area += 0.5 * a * b * sin(c_ang) ## Calculate min forward and aft shoot distance. fwd = np.max(mod_dist[np.where((angles >= 3 * pi / 2) | (angles <= pi / 2))]) aft = np.max(mod_dist[np.where((angles <= 3 * pi / 2) & (angles >= pi / 2))]) self.post_process_2d(angles, gnd_dist, mod_dist, no_fire_area, fwd, aft) if self.show_3d: self.post_process_3d(muz_pts, gnd_pts) ## Write results to json file and echo to log. out = { "min_fire_dist_fore_180" : fwd, "min_fire_dist_aft_180" : aft, "no_fire_area" : no_fire_area } tba.write_results(out)
def post_process(self): """ Generate the metrics from the stored raw ray trace results. """ out = {} for man in self.manikins: vis_mask = sum( [2**p for p, vis in enumerate(man.vision_devices) if vis]) horizon_fraction = 0.0 num_pts = np.shape(self.hor_sweep)[0] for i in xrange(num_pts): if self.target_points_horizon[i] & vis_mask: horizon_fraction += 1.0 / num_pts fore_aft_arr = np.array(self.fore_aft) pfx = man.vehicle_role if any(man.vision_devices): out.update({ pfx + "_horizon_percentage": horizon_fraction, pfx + "_fore_closest_visible_point": np.min(fore_aft_arr[np.array(man.vision_devices), 0]), pfx + "_aft_closest_visible_point": np.min(fore_aft_arr[np.array(man.vision_devices), 1]), pfx + "_max_uplook": np.max(self.uplook[np.array(man.vision_devices)]), }) else: out.update({ pfx + "_horizon_percentage": horizon_fraction, pfx + "_fore_closest_visible_point": "Fail", pfx + "_aft_closest_visible_point": "Fail", pfx + "_max_uplook": "Fail", }) ## Write results and echo to log. tba.write_results(out) if self.show_3d: self.post_process_3d()
def post_process(self): """ Generate the metrics from the stored raw ray trace results. """ out = {} for man in self.manikins: vis_mask = sum([2 ** p for p, vis in enumerate(man.vision_devices) if vis]) horizon_fraction = 0.0 num_pts = np.shape(self.hor_sweep)[0] for i in xrange(num_pts): if self.target_points_horizon[i] & vis_mask: horizon_fraction += 1.0 / num_pts fore_aft_arr = np.array(self.fore_aft) pfx = man.vehicle_role if any(man.vision_devices): out.update( { pfx + "_horizon_percentage": horizon_fraction, pfx + "_fore_closest_visible_point": np.min(fore_aft_arr[np.array(man.vision_devices), 0]), pfx + "_aft_closest_visible_point": np.min(fore_aft_arr[np.array(man.vision_devices), 1]), pfx + "_max_uplook": np.max(self.uplook[np.array(man.vision_devices)]), } ) else: out.update( { pfx + "_horizon_percentage": horizon_fraction, pfx + "_fore_closest_visible_point": "Fail", pfx + "_aft_closest_visible_point": "Fail", pfx + "_max_uplook": "Fail", } ) ## Write results and echo to log. tba.write_results(out) if self.show_3d: self.post_process_3d()
# Exit availability checks: TB034 and 035 exit_checks = tb_034_035_exit_checks(assembly, vehicle) logging.info("Detailed list of exit availability results: ") logging.info(exit_checks) exit_ok = tb_034(exit_checks) evac_ok = tb_035(exit_checks) ## TB036: Does litter fit in the assigned spot without collisions if valid_litter_found: litter_status = tb_036(assembly, vehicle, SETTINGS) else: # Let remainder of TB fail when no litter is present, but failing metric is meaningless logging.error( "Litter evaluation could not be run, because no Litter_Open was found" ) litter_status = False ### Combine results for final output tb_results = { "total_exit_time_tb033": total_exit_time, "egress_overview_passed_tb034": exit_ok, "crew_evac_passed_tb035": evac_ok, "litter_fits_tb036": litter_status } # Write JSON file with results tba.write_results(tb_results) logging.info("All egress test bench calculations complete. Exiting.")
all_results["Metrics"][rr.part_id] = {"Max act. force": max(act_forces), "Max act. length": max(act_lengths), "Act force req met": force_ok, "Act length req met": length_ok} if SETTINGS['show_2d']: ## Load in geometry for plotting #geo = {} #for t in ramp_types: # geo.update(tba.load_geometry({t})) # Plot 2d line graphs of results plt_ramp_results(rr, act_forces, act_lengths) plt_ramp(rr) # Show the 5 hatch mount points + center position on the plot #this_geom = geo[rr.part_id] #plt_ramp(rr, this_geom) ## Show all plots when done #plt.show() # Update all results dict with overall info about run all_results["RequirementsMet"] = all_tests_ok all_results["TestBench"] = "Closures" all_results["DesignName"] = SETTINGS["design_name"] tba.write_results(all_results)
# Results dict for this hatch hatch_res = {"MAX HATCH FORCE (N)": np.max(hatch_force_net), "MIN HATCH FORCE (N)": np.min(hatch_force_net)} if h.spr_tors: # Results dict includes whether all tbars were under their max stress hatch_res["TORSION BAR STRESS OK"] = all(tbar_stresses) logging.info("Results calculated for hatch: {}".format(h.part_id)) logging.info(hatch_res) all_results["Metrics"][h.part_id] = hatch_res if SETTINGS['show_2d']: ## After running hatch, create results images for debugging this_geom = geo[h.part_id] plt_res_graphs(h, torques, this_geom) ## View all plots #plt.show() # Add final status of all tests to output all_results["RequirementsMet"] = all_stress_ok all_results["TestBench"] = "Closures" all_results["DesignName"] = SETTINGS["design_name"] ############# ## Save output data tba.write_results(all_results) logging.info("Done with test bench calculations. Exiting.")
logging.info("Calculated best pose of manikin overall at each point in vehicle") # TB033: Exit time calculations total_exit_time = tb_033(assembly, SETTINGS, vehicle) # Exit availability checks: TB034 and 035 exit_checks = tb_034_035_exit_checks(assembly, vehicle) logging.info("Detailed list of exit availability results: ") logging.info(exit_checks) exit_ok = tb_034(exit_checks) evac_ok = tb_035(exit_checks) ## TB036: Does litter fit in the assigned spot without collisions if valid_litter_found: litter_status = tb_036(assembly, vehicle, SETTINGS) else: # Let remainder of TB fail when no litter is present, but failing metric is meaningless logging.error("Litter evaluation could not be run, because no Litter_Open was found") litter_status = False ### Combine results for final output tb_results = {"total_exit_time_tb033": total_exit_time, "egress_overview_passed_tb034": exit_ok, "crew_evac_passed_tb035": evac_ok, "litter_fits_tb036": litter_status} # Write JSON file with results tba.write_results(tb_results) logging.info("All egress test bench calculations complete. Exiting.")
def __init__(self, settings): """ Setup vehicle metrics based on settings read in from file. """ ## Essential test bench settings self.output_json_file = settings["output_json_file"] ##testbench specific settings transport_dimensions = settings["transport_dimensions"] self.up_direction = settings.get("up_direction", np.array([0, 1.0, 0])) self.fore_direction = settings.get("fore_direction", np.array([0, 0, 1.0])) self.ground = settings.get("ground", np.array([0, 1.0, 0])) self.curb_mass = tba.get_veh_mass() self.cent_grav = tba.get_veh_cg() try: self.up_direction, self.ground_plane, _ = tba.get_up_vector() except: self.up_direction = settings.get("up_direction", np.array([0, 1.0, 0])) trans_data = tba.get_data(parts_of_interest) ## Define dictionaries for each lifting and tie down class self.eye_weld = {} self.eye_bolt = {} self.ring_hoist = {} self.d_ring = {} self.dbar_weld = {} self.dbar_bolt = {} self.dbar_eye = {} self.pintle = {} self.cleat = {} self.eye_weld = trans_data[ "Eye_Welded"] # TODO: does this crash on empty list? self.eye_bolt = trans_data["Eye_Bolted"] self.ring_hoist = trans_data["Ring_Hoist"] self.d_ring = trans_data["D_Ring_Lashing"] self.pintle = trans_data["Pintle_Tow"] self.cleat = trans_data["Cleat_Mooring"] self.dbar_weld = trans_data["Drawbar_Welded"] self.dbar_bolt = trans_data["Drawbar_Bolted"] self.dbar_eye = trans_data["Drawbar_Eyebolt"] ## Define set of classes to get geometry for all_class_set = tba.get_all_geom_set() ## Class sets and geometry for approach angles class_set = all_class_set - tba.geom_sets["never_exterior_classes"] - \ {"Roadwheel", "Trailing_Arm_Hydropneumatic_Rh", "Trailing_Arm_Hydropneumatic_Lh", "Track", "Sprocket_And_Carrier_Drive", "Wheel_Idler"} surface = tba.load_geometry(class_set, single_file=True) self.surface_coords = np.vstack( [surface["x"], surface["y"], surface["z"]]).T wheel_set = {"Roadwheel", "Sprocket_And_Carrier_Drive", "Wheel_Idler"} wheels = tba.load_geometry(wheel_set, single_file=True) track_set = {"Track"} track = tba.load_geometry(track_set, single_file=True) ## Class set and geometry for container fitting trans_class_set = all_class_set trans_geom = tba.load_geometry(trans_class_set, single_file=True) ## Class sets and geometry for lift eyes and tie_downs lift_set = {"Eye_Welded"} tie_down_set = {"Ring_Hoist"} lift_geom = tba.load_geometry(lift_set, single_file=True) tie_down_geom = tba.load_geometry(tie_down_set, single_file=True) self.trans_dict = vehicle_fit(surface, self.up_direction, self.fore_direction, transport_dimensions) self.trans_dict["Lifting_Metrics"] = self.lifting_metrics() self.trans_dict["Tie_Down_Metrics"] = self.tie_down_metrics() self.trans_dict["Approach_Angles"] = approach_angles( surface, wheels, track) pintle_count = len(self.pintle) cleat_count = len(self.cleat) tow_count = len(self.eye_bolt) + len(self.eye_weld) + len(self.dbar_bolt) + \ len(self.dbar_eye) + len(self.dbar_weld) + len(self.pintle) lift_count = len(self.eye_bolt) + len(self.eye_weld) self.trans_dict["Count_for_components_in_towing_class"] = tow_count self.trans_dict["Count_for_components_in_lifting_class"] = lift_count self.trans_dict["Count_for_components_in_pintle_class"] = pintle_count self.trans_dict["Count_for_components_in_mooring_class"] = cleat_count plot_vehicle(trans_geom, transport_dimensions) plot_lift_tie_down(trans_geom, lift_geom, tie_down_geom) tba.write_results(self.trans_dict)
def __init__(self, settings): """ Setup vehicle metrics based on settings read in from file. """ ## Essential test bench settings self.output_json_file = settings["output_json_file"] ##testbench specific settings transport_dimensions = settings["transport_dimensions"] self.up_direction = settings.get("up_direction", np.array([0, 1.0, 0])) self.fore_direction = settings.get("fore_direction", np.array([0, 0, 1.0])) self.ground = settings.get("ground", np.array([0, 1.0, 0])) self.curb_mass = tba.get_veh_mass() self.cent_grav = tba.get_veh_cg() try: self.up_direction, self.ground_plane, _ = tba.get_up_vector() except: self.up_direction = settings.get("up_direction", np.array([0, 1.0, 0])) trans_data = tba.get_data(parts_of_interest) ## Define dictionaries for each lifting and tie down class self.eye_weld = {} self.eye_bolt = {} self.ring_hoist = {} self.d_ring = {} self.dbar_weld = {} self.dbar_bolt = {} self.dbar_eye = {} self.pintle = {} self.cleat = {} self.eye_weld = trans_data["Eye_Welded"] # TODO: does this crash on empty list? self.eye_bolt = trans_data["Eye_Bolted"] self.ring_hoist = trans_data["Ring_Hoist"] self.d_ring = trans_data["D_Ring_Lashing"] self.pintle = trans_data["Pintle_Tow"] self.cleat = trans_data["Cleat_Mooring"] self.dbar_weld = trans_data["Drawbar_Welded"] self.dbar_bolt = trans_data["Drawbar_Bolted"] self.dbar_eye = trans_data["Drawbar_Eyebolt"] ## Define set of classes to get geometry for all_class_set = tba.get_all_geom_set() ## Class sets and geometry for approach angles class_set = all_class_set - tba.geom_sets["never_exterior_classes"] - \ {"Roadwheel", "Trailing_Arm_Hydropneumatic_Rh", "Trailing_Arm_Hydropneumatic_Lh", "Track", "Sprocket_And_Carrier_Drive", "Wheel_Idler"} surface = tba.load_geometry(class_set, single_file=True) self.surface_coords = np.vstack([surface["x"], surface["y"], surface["z"]]).T wheel_set = {"Roadwheel", "Sprocket_And_Carrier_Drive", "Wheel_Idler"} wheels = tba.load_geometry(wheel_set, single_file=True) track_set = {"Track"} track = tba.load_geometry(track_set, single_file=True) ## Class set and geometry for container fitting trans_class_set = all_class_set trans_geom = tba.load_geometry(trans_class_set, single_file=True) ## Class sets and geometry for lift eyes and tie_downs lift_set = {"Eye_Welded"} tie_down_set = {"Ring_Hoist"} lift_geom = tba.load_geometry(lift_set, single_file=True) tie_down_geom = tba.load_geometry(tie_down_set, single_file=True) self.trans_dict = vehicle_fit(surface, self.up_direction, self.fore_direction, transport_dimensions) self.trans_dict["Lifting_Metrics"] = self.lifting_metrics() self.trans_dict["Tie_Down_Metrics"] = self.tie_down_metrics() self.trans_dict["Approach_Angles"] = approach_angles(surface, wheels, track) pintle_count = len(self.pintle) cleat_count = len(self.cleat) tow_count = len(self.eye_bolt) + len(self.eye_weld) + len(self.dbar_bolt) + \ len(self.dbar_eye) + len(self.dbar_weld) + len(self.pintle) lift_count = len(self.eye_bolt) + len(self.eye_weld) self.trans_dict["Count_for_components_in_towing_class"] = tow_count self.trans_dict["Count_for_components_in_lifting_class"] = lift_count self.trans_dict["Count_for_components_in_pintle_class"] = pintle_count self.trans_dict["Count_for_components_in_mooring_class"] = cleat_count plot_vehicle(trans_geom, transport_dimensions) plot_lift_tie_down(trans_geom, lift_geom, tie_down_geom) tba.write_results(self.trans_dict)