def result_plots_mintime(pars: dict, reftrack: np.ndarray, s: np.ndarray, t: np.ndarray, x: np.ndarray, u: np.ndarray, ax: np.ndarray, ay: np.ndarray, atot: np.ndarray, tf: np.ndarray, ec: np.ndarray, pwr: dict = None) -> None: """ Created by: Fabian Christ Extended by: Thomas Herrmann ([email protected]) Documentation: This function plots several figures containing relevant trajectory information after trajectory optimization. Inputs: pars: parameters dictionary reftrack: contains the information of the reftrack -> [x, y, w_tr_right, w_tr_left] s: contains the curvi-linear distance along the trajectory t: contains the time along the trajectory x: contains all state variables along the trajectory u: contains all control variables along the trajectory ax: contains the longitudinal acceleration along the trajectory ay: contains the lateral acceleration along the trajectory atot: contains the total acceleration along the trajectory tf: contains all tire forces along the trajectory ec: contains the used energy along the trajectory """ # ------------------------------------------------------------------------------------------------------------------ # PLOT OPTIONS ----------------------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------------------------------------------ plt.rcParams['axes.labelsize'] = 10.0 plt.rcParams['axes.titlesize'] = 11.0 plt.rcParams['legend.fontsize'] = 10.0 plt.rcParams['figure.figsize'] = 25 / 2.54, 20 / 2.54 plot_opts = {"v_a_t": True, "general": True, "lateral_distance": True, "power": True, "kamm_circle": True, "tire_forces": True, "tire_forces_longitudinal": True, "tire_forces_dynamic": True, "energy_consumption": True, "pwr_states": True, "pwr_soc": True, "pwr_losses": True} # ------------------------------------------------------------------------------------------------------------------ # EXTRACT PLOT DATA ------------------------------------------------------------------------------------------------ # ------------------------------------------------------------------------------------------------------------------ # state variables v = x[:, 0] beta = x[:, 1] omega_z = x[:, 2] n = x[:, 3] xi = x[:, 4] if pars["pwr_params_mintime"]["pwr_behavior"]: temp_mot = x[:, 5] temp_batt = x[:, 6] temp_inv = x[:, 7] temp_radiators_cool_mi = x[:, 8] temp_radiators_cool_b = x[:, 9] soc_batt = x[:, 10] # control variables delta = np.append(u[:, 0], u[0, 0]) f_drive = np.append(u[:, 1], u[0, 1]) f_brake = np.append(u[:, 2], u[0, 2]) gamma_y = np.append(u[:, 3], u[0, 3]) # tire forces tf_x_fl = tf[:, 0] tf_y_fl = tf[:, 1] tf_z_fl = tf[:, 2] tf_x_fr = tf[:, 3] tf_y_fr = tf[:, 4] tf_z_fr = tf[:, 5] tf_x_rl = tf[:, 6] tf_y_rl = tf[:, 7] tf_z_rl = tf[:, 8] tf_x_rr = tf[:, 9] tf_y_rr = tf[:, 10] tf_z_rr = tf[:, 11] # parameters g = pars["veh_params"]["g"] veh = pars["vehicle_params_mintime"] tire = pars["tire_params_mintime"] # ------------------------------------------------------------------------------------------------------------------ # PLOT: VELOCITY + LONGITUDINAL ACCELERATION + LATERAL ACCELERATION + TOTAL ACCELERATION + TIME -------------------- # ------------------------------------------------------------------------------------------------------------------ if plot_opts["v_a_t"]: plt.figure(1) plt.clf() plt.plot(s, v) plt.plot(s, ax) plt.plot(s, ay) plt.plot(s, atot) plt.plot(s, t) plt.grid() plt.ylim(bottom=-15) plt.xlabel('distance ' + r'$\it{s}$' + ' in ' + r'$\it{m}$') plt.legend([r'$\it{v}$' + ' in ' + r'$\it{\frac{m}{s}}$', r'$\it{a_x}$' + ' in ' + r'$\it{\frac{m}{s^2}}$', r'$\it{a_y}$' + ' in ' + r'$\it{\frac{m}{s^2}}$', r'$\it{a_{tot}}$' + ' in ' + r'$\it{\frac{m}{s^2}}$', r'$\it{t}$' + ' in ' + r'$\it{s}$']) plt.show() # ------------------------------------------------------------------------------------------------------------------ # PLOT: SIDE SLIP ANGLE + YAW RATE + RELATIVE ANGLE TO TANGENT ON REFLINE + STEERING ANGLE ------------------------- # ------------------------------------------------------------------------------------------------------------------ if plot_opts["general"]: plt.figure(2) plt.clf() plt.subplot(221) plt.plot(s, beta * 180 / np.pi) plt.xlabel('distance ' + r'$\it{s}$' + ' in ' + r'$\it{m}$') plt.ylabel('side slip angle ' + r'$\beta$' + ' in ' + r'$\it{°}$') plt.grid() plt.subplot(222) plt.plot(s, omega_z * 180 / np.pi) plt.xlabel('distance ' + r'$\it{s}$' + ' in ' + r'$\it{m}$') plt.ylabel('yaw rate ' + r'$\omega_{z}$' + ' in ' + r'$\it{\frac{°}{s}}$') plt.grid() plt.subplot(223) plt.plot(s, xi * 180 / np.pi) plt.xlabel('distance ' + r'$\it{s}$' + ' in ' + r'$\it{m}$') plt.ylabel('relative angle to tangent on reference line ' + r'$\xi$' + ' in ' + r'$\it{°}$') plt.grid() plt.subplot(224) plt.step(s, delta * 180 / np.pi, where='post') plt.xlabel('distance ' + r'$\it{s}$' + ' in ' + r'$\it{m}$') plt.ylabel('steering angle ' + r'$\delta$' + ' in ' + r'$\it{°}$') plt.grid() plt.show() # ------------------------------------------------------------------------------------------------------------------ # PLOT: LATERAL DISTANCE TO REFERENCE LINE + ROAD BOUNDARIES ------------------------------------------------------- # ------------------------------------------------------------------------------------------------------------------ if plot_opts["lateral_distance"]: plt.figure(3) plt.clf() plt.plot(s, n) reftrack_cl = np.vstack((reftrack, reftrack[0, :])) plt.plot(s, reftrack_cl[:, 3], color='black') plt.plot(s, reftrack_cl[:, 3] - pars["optim_opts"]["width_opt"] / 2, color='grey') plt.plot(s, -reftrack_cl[:, 2], color='black') plt.plot(s, -reftrack_cl[:, 2] + pars["optim_opts"]["width_opt"] / 2, color='grey') plt.xlabel('distance ' + r'$\it{s}$' + ' in ' + r'$\it{m}$') plt.ylabel('lateral distance to reference line ' + r'$\it{n}$' + ' in ' + r'$\it{m}$') plt.legend(['raceline', 'road boundaries', 'road boundaries - safety margin'], ncol=1, loc=4) plt.grid() plt.show() # ------------------------------------------------------------------------------------------------------------------ # PLOT: KAMM's CIRCLE ---------------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------------------------------------------ if plot_opts["kamm_circle"]: plt.figure(5) plt.clf() plt.suptitle("Kamm's Circle") plt.subplot(221) circle1 = plt.Circle((0, 0), 1, fill=False) fig = plt.gcf() ax = fig.gca() ax.add_artist(circle1) plt.plot(tf_y_fl / (tf_z_fl * pars["optim_opts"]["mue"]), tf_x_fl / (tf_z_fl * pars["optim_opts"]["mue"]), '^:') plt.xlim(-1.2, 1.2) plt.ylim(-1.2, 1.2) plt.xlabel(r'$\it{\frac{F_{y}}{F_{ymax}}}$') plt.ylabel(r'$\it{\frac{F_{x}}{F_{xmax}}}$') plt.axis('equal') plt.grid() plt.subplot(222) circle1 = plt.Circle((0, 0), 1, fill=False) fig = plt.gcf() ax = fig.gca() ax.add_artist(circle1) plt.plot(tf_y_fr / (tf_z_fr * pars["optim_opts"]["mue"]), tf_x_fr / (tf_z_fr * pars["optim_opts"]["mue"]), '^:') plt.xlim(-1.2, 1.2) plt.ylim(-1.2, 1.2) plt.xlabel(r'$\it{\frac{F_{y}}{F_{ymax}}}$') plt.ylabel(r'$\it{\frac{F_{x}}{F_{xmax}}}$') plt.axis('equal') plt.grid() plt.subplot(223) circle1 = plt.Circle((0, 0), 1, fill=False) fig = plt.gcf() ax = fig.gca() ax.add_artist(circle1) plt.plot(tf_y_rl / (tf_z_rl * pars["optim_opts"]["mue"]), tf_x_rl / (tf_z_rl * pars["optim_opts"]["mue"]), '^:') plt.xlim(-1.2, 1.2) plt.ylim(-1.2, 1.2) plt.xlabel(r'$\it{\frac{F_{y}}{F_{ymax}}}$') plt.ylabel(r'$\it{\frac{F_{x}}{F_{xmax}}}$') plt.axis('equal') plt.grid() plt.subplot(224) circle1 = plt.Circle((0, 0), 1, fill=False) fig = plt.gcf() ax = fig.gca() ax.add_artist(circle1) plt.plot(tf_y_rr / (tf_z_rr * pars["optim_opts"]["mue"]), tf_x_rr / (tf_z_rr * pars["optim_opts"]["mue"]), '^:') plt.xlim(-1.2, 1.2) plt.ylim(-1.2, 1.2) plt.xlabel(r'$\it{\frac{F_{y}}{F_{ymax}}}$') plt.ylabel(r'$\it{\frac{F_{x}}{F_{xmax}}}$') plt.axis('equal') plt.grid() plt.show() # ------------------------------------------------------------------------------------------------------------------ # PLOT: TIRE FORCES (LONGITUDINAL + LATERAL + NORMAL) -------------------------------------------------------------- # ------------------------------------------------------------------------------------------------------------------ if plot_opts["tire_forces"]: plt.figure(6) plt.clf() plt.suptitle("Tire Forces") plt.subplot(221) plt.plot(s, tf_x_fl) plt.plot(s, tf_y_fl) plt.plot(s, tf_z_fl) plt.xlabel('distance ' + r'$\it{s}$' + ' in ' + r'$\it{m}$') plt.ylabel(r'$\it{F_{i}}$' + ' in ' + r'$\it{N}$') plt.legend([r'$\it{F_{x}}$', r'$\it{F_{y}}$', r'$\it{F_{z}}$'], ncol=3, loc=4) plt.grid() plt.subplot(222) plt.plot(s, tf_x_fr) plt.plot(s, tf_y_fr) plt.plot(s, tf_z_fr) plt.xlabel('distance ' + r'$\it{s}$' + ' in ' + r'$\it{m}$') plt.ylabel(r'$\it{F_{i}}$' + ' in ' + r'$\it{N}$') plt.legend([r'$\it{F_{x}}$', r'$\it{F_{y}}$', r'$\it{F_{z}}$'], ncol=3, loc=4) plt.grid() plt.subplot(223) plt.plot(s, tf_x_rl) plt.plot(s, tf_y_rl) plt.plot(s, tf_z_rl) plt.xlabel('distance ' + r'$\it{s}$' + ' in ' + r'$\it{m}$') plt.ylabel(r'$\it{F_{i}}$' + ' in ' + r'$\it{N}$') plt.legend([r'$\it{F_{x}}$', r'$\it{F_{y}}$', r'$\it{F_{z}}$'], ncol=3, loc=4) plt.grid() plt.subplot(224) plt.plot(s, tf_x_rr) plt.plot(s, tf_y_rr) plt.plot(s, tf_z_rr) plt.xlabel('distance ' + r'$\it{s}$' + ' in ' + r'$\it{m}$') plt.ylabel(r'$\it{F_{i}}$' + ' in ' + r'$\it{N}$') plt.legend([r'$\it{F_{x}}$', r'$\it{F_{y}}$', r'$\it{F_{z}}$'], ncol=3, loc=4) plt.grid() plt.show() # ------------------------------------------------------------------------------------------------------------------ # PLOT: TIRE FORCES (LONGITUDINAL) --------------------------------------------------------------------------------- # ------------------------------------------------------------------------------------------------------------------ if plot_opts["tire_forces_longitudinal"]: plt.figure(7) plt.step(s, f_drive / 1000, where="post") plt.step(s, f_brake / 1000, where='post') plt.step(s, (f_drive + f_brake) / 1000, where='post') plt.plot(s, veh["power_max"] / (v * 1000), linewidth=0.5) plt.xlabel('distance ' + r'$\it{s}$' + ' in ' + r'$\it{m}$') plt.ylabel(r'$\it{F}$' + ' in ' + r'$\it{kN}$') plt.legend([r'$\it{F_{drive}}$', r'$\it{F_{brake}}$', r'$\it{F_{drive}}$' + " + " + r'$\it{F_{brake}}$', r'$\it{F_{P_{max}}}$'], ncol=1, loc=4) plt.grid() plt.show() # ------------------------------------------------------------------------------------------------------------------ # PLOT: DYNAMIC WHEEL LOAD TRANSFER -------------------------------------------------------------------------------- # ------------------------------------------------------------------------------------------------------------------ if plot_opts["tire_forces_dynamic"]: f_xroll = tire["c_roll"] * pars["veh_params"]["mass"] * g f_xdrag = pars["veh_params"]["dragcoeff"] * v ** 2 f_zlift_fl = 0.5 * veh["liftcoeff_front"] * v ** 2 f_zlift_fr = 0.5 * veh["liftcoeff_front"] * v ** 2 f_zlift_rl = 0.5 * veh["liftcoeff_rear"] * v ** 2 f_zlift_rr = 0.5 * veh["liftcoeff_rear"] * v ** 2 f_zlong_fl = -0.5 * veh["cog_z"] / veh["wheelbase"] * (f_drive + f_brake - f_xroll - f_xdrag) f_zlong_fr = -0.5 * veh["cog_z"] / veh["wheelbase"] * (f_drive + f_brake - f_xroll - f_xdrag) f_zlong_rl = 0.5 * veh["cog_z"] / veh["wheelbase"] * (f_drive + f_drive - f_xroll - f_xdrag) f_zlong_rr = 0.5 * veh["cog_z"] / veh["wheelbase"] * (f_drive + f_drive - f_xroll - f_xdrag) f_zlat_fl = - veh["k_roll"] * gamma_y f_zlat_fr = veh["k_roll"] * gamma_y f_zlat_rl = - (1 - veh["k_roll"]) * gamma_y f_zlat_rr = (1 - veh["k_roll"]) * gamma_y plt.figure(8) plt.suptitle("Dynamic Wheel Load") plt.subplot(221) plt.plot(s, f_zlift_fl) plt.plot(s, f_zlong_fl) plt.plot(s, f_zlat_fl) plt.plot(s, f_zlift_fl + f_zlong_fl + f_zlat_fl, color='black') plt.xlabel('distance ' + r'$\it{s}$' + ' in ' + r'$\it{m}$') plt.ylabel(r'$\it{F_{i}}$' + ' in ' + r'$\it{N}$') plt.grid() plt.subplot(222) plt.plot(s, f_zlift_fr) plt.plot(s, f_zlong_fr) plt.plot(s, f_zlat_fr) plt.plot(s, f_zlift_fr + f_zlong_fr + f_zlat_fr, color='black') plt.xlabel(r'$\it{s}$' + ' in ' + r'$\it{m}$') plt.ylabel(r'$\it{F_{i}}$' + ' in ' + r'$\it{N}$') plt.grid() plt.subplot(223) plt.plot(s, f_zlift_rl) plt.plot(s, f_zlong_rl) plt.plot(s, f_zlat_rl) plt.plot(s, f_zlift_rl + f_zlong_rl + f_zlat_rl, color='black') plt.xlabel('distance ' + r'$\it{s}$' + ' in ' + r'$\it{m}$') plt.ylabel(r'$\it{F_{i}}$' + ' in ' + r'$\it{N}$') plt.grid() plt.subplot(224) plt.plot(s, f_zlift_rr) plt.plot(s, f_zlong_rr) plt.plot(s, f_zlat_rr) plt.plot(s, f_zlift_rr + f_zlong_rr + f_zlat_rr, color='black') plt.xlabel('distance ' + r'$\it{s}$' + ' in ' + r'$\it{m}$') plt.ylabel(r'$\it{F_{i}}$' + ' in ' + r'$\it{N}$') plt.legend([r'$\it{F_{lift}}$', r'$\it{F_{dyn,long}}$', r'$\it{F_{dyn,lat}}$', r'$\it{F_{lift}}$' + ' + ' + r'$\it{F_{dyn,long}}$' + ' + ' + r'$\it{F_{dyn,lat}}$'], ncol=2, loc=4) plt.grid() plt.show() # ------------------------------------------------------------------------------------------------------------------ # PLOT: ENERGY CONSUMPTION ----------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------------------------------------------ if plot_opts["energy_consumption"]: plt.figure(9) plt.clf() plt.plot(s, ec) plt.xlabel('distance ' + r'$\it{s}$' + ' in ' + r'$\it{m}$') plt.ylabel('energy consumption ' + r'$\it{ec}$' + ' in ' + r'$\it{Wh}$') plt.grid() plt.show() # ------------------------------------------------------------------------------------------------------------------ # PLOT: POWER ------------------------------------------------------------------------------------------------------ # ------------------------------------------------------------------------------------------------------------------ if plot_opts["power"]: plt.figure(4) plt.clf() plt.plot(s, v * (f_drive + f_brake) / 1000.0) plt.xlabel('distance ' + r'$\it{s}$' + ' in ' + r'$m$') plt.ylabel('power ' + r'$\it{P}$' + ' in ' + r'$kW$') plt.grid() plt.legend(r'$\it{P_{wheel}}$') if pwr is not None: plt.plot(s[:-1], pwr["batt"].p_loss_total + pwr["batt"].p_out_batt) plt.legend([r'$\it{P_{wheel}}$', r'$\it{P_{system}}$']) plt.show() # ------------------------------------------------------------------------------------------------------------------ # PLOT: POWERTRAIN TEMPERATURES ------------------------------------------------------------------------------------ # ------------------------------------------------------------------------------------------------------------------ if pars["pwr_params_mintime"]["pwr_behavior"] and plot_opts["pwr_states"]: plt.figure(10) plt.plot(s, temp_mot) plt.plot(s, temp_batt) plt.plot(s, temp_inv) plt.plot(s, temp_radiators_cool_mi) plt.plot(s, temp_radiators_cool_b) plt.xlabel('distance ' + r'$\it{s}$' + ' in ' + r'$\it{m}$') plt.ylabel('component temperatures ' + r'$\it{T}$' + ' in ' + r'°C') plt.legend([r'$\it{T_\mathrm{Machine}}$', r'$\it{T_\mathrm{Battery}}$', r'$\it{T_\mathrm{Inverter}}$', r'$\it{T_\mathrm{Fluid_{MI}}}$', r'$\it{T_\mathrm{Fluid_B}}$']) plt.grid() plt.show() # ------------------------------------------------------------------------------------------------------------------ # PLOT: SOC BATTERY ------------------------------------------------------------------------------------------------ # ------------------------------------------------------------------------------------------------------------------ if pars["pwr_params_mintime"]["pwr_behavior"] and plot_opts["pwr_soc"]: plt.figure(11) plt.plot(s, soc_batt) plt.xlabel('distance ' + r'$\it{s}$' + ' in ' + r'$\it{m}$') plt.ylabel('SOC battery [1 - 0]') plt.grid() plt.show() # ------------------------------------------------------------------------------------------------------------------ # PLOT: POWER LOSSES ----------------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------------------------------------------ if pars["pwr_params_mintime"]["pwr_behavior"] and plot_opts["pwr_losses"]: if pars["pwr_params_mintime"]["simple_loss"]: plt.figure(12) plt.plot(s[:-1], pwr["machine"].p_loss_total) plt.plot(s[:-1], pwr["inverter"].p_loss_total) plt.plot(s[:-1], pwr["batt"].p_loss_total) plt.legend([r'$\it{P_\mathrm{loss,machine}}$', r'$\it{P_\mathrm{loss,inverter}}$', r'$\it{P_\mathrm{loss,battery}}$']) plt.ylabel('Power loss ' + r'$\it{P_\mathrm{loss}}$' + ' in ' + r'kW') else: plt.figure(12) plt.subplot(311) plt.plot(s[:-1], pwr["machine"].p_loss_total) plt.plot(s[:-1], pwr["machine"].p_loss_copper) plt.plot(s[:-1], pwr["machine"].p_loss_stator_iron) plt.plot(s[:-1], pwr["machine"].p_loss_rotor) plt.ylabel('Power loss single machine\n' + r'$\it{P_\mathrm{loss}}$' + ' in ' + r'kW') plt.legend([r'$\it{P_\mathrm{loss,total}}$', r'$\it{P_\mathrm{loss,copper}}$', r'$\it{P_\mathrm{loss,statorIron}}$', r'$\it{P_\mathrm{loss,rotor}}$']) plt.grid() plt.subplot(312) plt.plot(s[:-1], pwr["inverter"].p_loss_total) plt.plot(s[:-1], pwr["inverter"].p_loss_switch) plt.plot(s[:-1], pwr["inverter"].p_loss_cond) plt.legend([r'$\it{P_\mathrm{loss,total}}$', r'$\it{P_\mathrm{loss,switching}}$', r'$\it{P_\mathrm{loss,conducting}}$']) plt.ylabel('Power loss single inverter\n' + r'$\it{P_\mathrm{loss}}$' + ' in ' + r'kW') plt.grid() plt.subplot(313) plt.plot(s[:-1], pwr["batt"].p_loss_total) plt.ylabel('Power loss battery\n' + r'$\it{P_\mathrm{loss}}$' + ' in ' + r'kW') plt.xlabel('distance ' + r'$\it{s}$' + ' in ' + r'$\it{m}$') plt.grid() plt.show() # testing -------------------------------------------------------------------------------------------------------------- if __name__ == "__main__": pass