@@ -409,7 +409,12 @@ def estimate_model(self):
409
409
print ("===============================================================================" )
410
410
print (" Preparing Model Features " )
411
411
print ("===============================================================================" )
412
- self .X , self .y , self .coef_name_list = self .assemble_regression_matrices (["lin" ,"rot" ])
412
+ configuration = []
413
+ if self .estimate_forces :
414
+ configuration .append ("lin" )
415
+ if self .estimate_moments :
416
+ configuration .append ("rot" )
417
+ self .X , self .y , self .coef_name_list = self .assemble_regression_matrices (configuration )
413
418
self .initialize_optimizer ()
414
419
self .optimizer .estimate_parameters (self .X , self .y )
415
420
self .generate_optimization_results ()
@@ -462,7 +467,8 @@ def generate_optimization_results(self):
462
467
metrics_dict = self .optimizer .compute_optimization_metrics ()
463
468
coef_list = self .optimizer .get_optimization_parameters ()
464
469
model_dict = {}
465
- model_dict .update (self .rotor_config_dict )
470
+ if hasattr (self , 'rotor_config_dict' ):
471
+ model_dict .update (self .rotor_config_dict )
466
472
if hasattr (self , 'aero_config_dict' ):
467
473
model_dict .update (self .aero_config_dict )
468
474
self .generate_model_dict (coef_list , metrics_dict , model_dict )
@@ -481,45 +487,49 @@ def generate_optimization_results(self):
481
487
def compute_residuals (self ):
482
488
483
489
y_pred = self .optimizer .predict (self .X )
484
- _ ,y_forces ,_ = self .assemble_regression_matrices (["lin" ])
485
- _ ,y_moments ,_ = self .assemble_regression_matrices (["rot" ])
486
-
487
- y_forces_measured = np .zeros (y_forces .shape )
488
- y_forces_measured [0 ::3 ] = y_forces [0 :int (y_forces .shape [0 ]/ 3 )]
489
- y_forces_measured [1 ::3 ] = y_forces [int (y_forces .shape [0 ]/ 3 ):int (2 * y_forces .shape [0 ]/ 3 )]
490
- y_forces_measured [2 ::3 ] = y_forces [int (2 * y_forces .shape [0 ]/ 3 ):y_forces .shape [0 ]]
491
-
492
- y_forces_pred = np .zeros (y_forces .shape )
493
- y_forces_pred [0 ::3 ] = y_pred [0 :int (y_forces .shape [0 ]/ 3 )]
494
- y_forces_pred [1 ::3 ] = y_pred [int (y_forces .shape [0 ]/ 3 ):int (2 * y_forces .shape [0 ]/ 3 )]
495
- y_forces_pred [2 ::3 ] = y_pred [int (2 * y_forces .shape [0 ]/ 3 ):y_forces .shape [0 ]]
496
-
497
- y_moments_measured = np .zeros (y_moments .shape )
498
- y_moments_measured [0 ::3 ] = y_moments [0 :int (y_moments .shape [0 ]/ 3 )]
499
- y_moments_measured [1 ::3 ] = y_moments [int (y_moments .shape [0 ]/ 3 ):int (2 * y_moments .shape [0 ]/ 3 )]
500
- y_moments_measured [2 ::3 ] = y_moments [int (2 * y_moments .shape [0 ]/ 3 ):y_moments .shape [0 ]]
501
-
502
- y_moments_pred = np .zeros (y_moments .shape )
503
- y_moments_pred [0 ::3 ] = y_pred [y_moments .shape [0 ]:int (4 * y_moments .shape [0 ]/ 3 )]
504
- y_moments_pred [1 ::3 ] = y_pred [int (4 * y_moments .shape [0 ]/ 3 ):int (5 * y_moments .shape [0 ]/ 3 )]
505
- y_moments_pred [2 ::3 ] = y_pred [int (5 * y_moments .shape [0 ]/ 3 ):]
506
-
507
- error_y_forces = y_forces_pred - y_forces_measured
508
- error_y_moments = y_moments_pred - y_moments_measured
509
-
510
- stacked_error_y_forces = np .array (error_y_forces )
511
- acc_mat = stacked_error_y_forces .reshape ((- 1 , 3 ))
512
- residual_force_df = pd .DataFrame (acc_mat , columns = [
513
- "residual_force_x" , "residual_force_y" , "residual_force_z" ])
514
- self .data_df = pd .concat (
515
- [self .data_df , residual_force_df ], axis = 1 , join = "inner" ).reindex (self .data_df .index )
490
+ if self .estimate_forces :
491
+ _ ,y_forces ,_ = self .assemble_regression_matrices (["lin" ])
492
+ y_forces_measured = np .zeros (y_forces .shape )
493
+ y_forces_measured [0 ::3 ] = y_forces [0 :int (y_forces .shape [0 ]/ 3 )]
494
+ y_forces_measured [1 ::3 ] = y_forces [int (y_forces .shape [0 ]/ 3 ):int (2 * y_forces .shape [0 ]/ 3 )]
495
+ y_forces_measured [2 ::3 ] = y_forces [int (2 * y_forces .shape [0 ]/ 3 ):y_forces .shape [0 ]]
516
496
517
- stacked_error_y_moments = np .array (error_y_moments )
518
- mom_mat = stacked_error_y_moments .reshape ((- 1 , 3 ))
519
- residual_moment_df = pd .DataFrame (mom_mat , columns = [
520
- "residual_moment_x" , "residual_moment_y" , "residual_moment_z" ])
521
- self .data_df = pd .concat (
522
- [self .data_df , residual_moment_df ], axis = 1 , join = "inner" ).reindex (self .data_df .index )
497
+ y_forces_pred = np .zeros (y_forces .shape )
498
+ y_forces_pred [0 ::3 ] = y_pred [0 :int (y_forces .shape [0 ]/ 3 )]
499
+ y_forces_pred [1 ::3 ] = y_pred [int (y_forces .shape [0 ]/ 3 ):int (2 * y_forces .shape [0 ]/ 3 )]
500
+ y_forces_pred [2 ::3 ] = y_pred [int (2 * y_forces .shape [0 ]/ 3 ):y_forces .shape [0 ]]
501
+
502
+ error_y_forces = y_forces_pred - y_forces_measured
503
+
504
+ stacked_error_y_forces = np .array (error_y_forces )
505
+ acc_mat = stacked_error_y_forces .reshape ((- 1 , 3 ))
506
+ residual_force_df = pd .DataFrame (acc_mat , columns = [
507
+ "residual_force_x" , "residual_force_y" , "residual_force_z" ])
508
+ self .data_df = pd .concat (
509
+ [self .data_df , residual_force_df ], axis = 1 , join = "inner" ).reindex (self .data_df .index )
510
+
511
+ if self .estimate_moments :
512
+ _ ,y_moments ,_ = self .assemble_regression_matrices (["rot" ])
513
+
514
+ y_moments_measured = np .zeros (y_moments .shape )
515
+ y_moments_measured [0 ::3 ] = y_moments [0 :int (y_moments .shape [0 ]/ 3 )]
516
+ y_moments_measured [1 ::3 ] = y_moments [int (y_moments .shape [0 ]/ 3 ):int (2 * y_moments .shape [0 ]/ 3 )]
517
+ y_moments_measured [2 ::3 ] = y_moments [int (2 * y_moments .shape [0 ]/ 3 ):y_moments .shape [0 ]]
518
+
519
+ y_moments_pred = np .zeros (y_moments .shape )
520
+ y_moments_pred [0 ::3 ] = y_pred [y_moments .shape [0 ]:int (4 * y_moments .shape [0 ]/ 3 )]
521
+ y_moments_pred [1 ::3 ] = y_pred [int (4 * y_moments .shape [0 ]/ 3 ):int (5 * y_moments .shape [0 ]/ 3 )]
522
+ y_moments_pred [2 ::3 ] = y_pred [int (5 * y_moments .shape [0 ]/ 3 ):]
523
+
524
+ error_y_moments = y_moments_pred - y_moments_measured
525
+
526
+
527
+ stacked_error_y_moments = np .array (error_y_moments )
528
+ mom_mat = stacked_error_y_moments .reshape ((- 1 , 3 ))
529
+ residual_moment_df = pd .DataFrame (mom_mat , columns = [
530
+ "residual_moment_x" , "residual_moment_y" , "residual_moment_z" ])
531
+ self .data_df = pd .concat (
532
+ [self .data_df , residual_moment_df ], axis = 1 , join = "inner" ).reindex (self .data_df .index )
523
533
524
534
def plot_model_predicitons (self ):
525
535
@@ -533,9 +543,14 @@ def plot_scatter(ax, title, dataframe_x, dataframe_y, dataframe_z, color='blue')
533
543
534
544
y_pred = self .optimizer .predict (self .X )
535
545
536
- if (self .estimate_forces and self .estimate_moments ):
546
+ fig = plt .figure ("Residual Visualization" )
547
+
548
+ model_plots .plot_airspeed_and_AoA (
549
+ self .data_df [["V_air_body_x" , "V_air_body_y" , "V_air_body_z" , "angle_of_attack" ]], self .data_df ["timestamp" ])
550
+
551
+ if (self .estimate_forces ):
537
552
_ ,y_forces ,_ = self .assemble_regression_matrices (["lin" ])
538
- _ , y_moments , _ = self . assemble_regression_matrices ([ "rot" ])
553
+
539
554
y_forces_measured = np .zeros (y_forces .shape )
540
555
y_forces_measured [0 ::3 ] = y_forces [0 :int (y_forces .shape [0 ]/ 3 )]
541
556
y_forces_measured [1 ::3 ] = y_forces [int (y_forces .shape [0 ]/ 3 ):int (2 * y_forces .shape [0 ]/ 3 )]
@@ -546,6 +561,19 @@ def plot_scatter(ax, title, dataframe_x, dataframe_y, dataframe_z, color='blue')
546
561
y_forces_pred [1 ::3 ] = y_pred [int (y_forces .shape [0 ]/ 3 ):int (2 * y_forces .shape [0 ]/ 3 )]
547
562
y_forces_pred [2 ::3 ] = y_pred [int (2 * y_forces .shape [0 ]/ 3 ):y_forces .shape [0 ]]
548
563
564
+ model_plots .plot_force_predictions (
565
+ y_forces_measured , y_forces_pred , self .data_df ["timestamp" ])
566
+
567
+ ax1 = fig .add_subplot (2 , 2 , 1 , projection = '3d' )
568
+ plot_scatter (ax1 , "Residual forces [N]" , "residual_force_x" ,
569
+ "residual_force_y" , "residual_force_z" , 'blue' )
570
+ ax3 = fig .add_subplot (2 , 2 , 3 , projection = '3d' )
571
+ plot_scatter (ax3 , "Measured Forces [N]" ,
572
+ "measured_force_x" , "measured_force_y" , "measured_force_z" , 'blue' )
573
+
574
+ if (self .estimate_moments ):
575
+ _ ,y_moments ,_ = self .assemble_regression_matrices (["rot" ])
576
+
549
577
y_moments_measured = np .zeros (y_moments .shape )
550
578
y_moments_measured [0 ::3 ] = y_moments [0 :int (y_moments .shape [0 ]/ 3 )]
551
579
y_moments_measured [1 ::3 ] = y_moments [int (y_moments .shape [0 ]/ 3 ):int (2 * y_moments .shape [0 ]/ 3 )]
@@ -556,46 +584,18 @@ def plot_scatter(ax, title, dataframe_x, dataframe_y, dataframe_z, color='blue')
556
584
y_moments_pred [1 ::3 ] = y_pred [int (4 * y_moments .shape [0 ]/ 3 ):int (5 * y_moments .shape [0 ]/ 3 )]
557
585
y_moments_pred [2 ::3 ] = y_pred [int (5 * y_moments .shape [0 ]/ 3 ):]
558
586
559
- model_plots .plot_force_predictions (
560
- y_forces_measured , y_forces_pred , self .data_df ["timestamp" ])
561
- model_plots .plot_moment_predictions (
562
- y_moments_measured , y_moments_pred , self .data_df ["timestamp" ])
563
- model_plots .plot_airspeed_and_AoA (
564
- self .data_df [["V_air_body_x" , "V_air_body_y" , "V_air_body_z" , "angle_of_attack" ]], self .data_df ["timestamp" ])
565
-
566
- elif (self .estimate_forces ):
567
- y_forces_pred = y_pred
568
- model_plots .plot_force_predictions (
569
- y_forces_measured , y_forces_pred , self .data_df ["timestamp" ])
570
- model_plots .plot_airspeed_and_AoA (
571
- self .data_df [["V_air_body_x" , "V_air_body_y" , "V_air_body_z" , "angle_of_attack" ]], self .data_df ["timestamp" ])
572
-
573
- elif (self .estimate_moments ):
574
- y_moments_pred = y_pred
575
587
model_plots .plot_moment_predictions (
576
588
y_moments_measured , y_moments_pred , self .data_df ["timestamp" ])
577
- model_plots .plot_airspeed_and_AoA (
578
- self .data_df [["V_air_body_x" , "V_air_body_y" , "V_air_body_z" , "angle_of_attack" ]], self .data_df ["timestamp" ])
579
-
580
- fig = plt .figure ("Residual Visualization" )
581
- ax1 = fig .add_subplot (2 , 2 , 1 , projection = '3d' )
582
- plot_scatter (ax1 , "Residual forces [N]" , "residual_force_x" ,
583
- "residual_force_y" , "residual_force_z" , 'blue' )
584
-
585
- ax2 = fig .add_subplot (2 , 2 , 2 , projection = '3d' )
586
-
587
- plot_scatter (ax2 , "Residual Moments [Nm]" , "residual_moment_x" ,
588
- "residual_moment_y" , "residual_moment_z" , 'blue' )
589
589
590
- ax3 = fig .add_subplot (2 , 2 , 3 , projection = '3d' )
590
+ ax2 = fig .add_subplot (2 , 2 , 2 , projection = '3d' )
591
591
592
- plot_scatter (ax3 , "Measured Forces [N] " ,
593
- "measured_force_x" , "measured_force_y " , "measured_force_z " , 'blue' )
592
+ plot_scatter (ax2 , "Residual Moments [Nm]" , "residual_moment_x " ,
593
+ "residual_moment_y " , "residual_moment_z " , 'blue' )
594
594
595
- ax4 = fig .add_subplot (2 , 2 , 4 , projection = '3d' )
595
+ ax4 = fig .add_subplot (2 , 2 , 4 , projection = '3d' )
596
596
597
- plot_scatter (ax4 , "Measured Moments [Nm]" ,
598
- "measured_moment_x" , "measured_moment_y" , "measured_moment_z" , 'blue' )
597
+ plot_scatter (ax4 , "Measured Moments [Nm]" ,
598
+ "measured_moment_x" , "measured_moment_y" , "measured_moment_z" , 'blue' )
599
599
600
600
linear_model_plots .plot_covariance_mat (self .X , self .coef_name_list )
601
601
0 commit comments