@@ -531,13 +531,14 @@ function BodePlot(handles, undock, exportData)
531531 Controller_PhaseResponse = angle(squeeze(Controller_FRF ))' *180 / pi ;
532532
533533 LoopGainFRF = freqresp(LoopGain , w );
534- LoopGainMagResponse = mag2db(squeeze(abs(LoopGainFRF )))' ;
534+ LoopGainMagResponseAbs = squeeze(abs(LoopGainFRF ))' ;
535+ LoopGainMagResponse = mag2db(LoopGainMagResponseAbs );
535536 LoopGainPhaseResponse = angle(squeeze(LoopGainFRF ))' *180 / pi ;
536537
537538 PlantFRF = freqresp(Plant , w );
538539 PlantMagResponse = mag2db(squeeze(abs(PlantFRF )))' ;
539540 PlantPhaseResponse = angle(squeeze(PlantFRF ))' *180 / pi ;
540-
541+
541542 % Ensure the data is always saved column-wise for single line plots
542543 if size(Controller_MagResponse , 1 ) == 1
543544 Controller_MagResponse = Controller_MagResponse(: );
@@ -547,6 +548,40 @@ function BodePlot(handles, undock, exportData)
547548 PlantMagResponse = PlantMagResponse(: );
548549 PlantPhaseResponse = PlantPhaseResponse(: );
549550 end
551+
552+ if get(handles .PlotLoopGain_checkbox ,' value' )
553+ legendMargins = cell(length(handles .SelectedListboxContents ), 6 );
554+ legendMargins(: ,1 ) = {' GM: ' };
555+ legendMargins(: ,3 ) = {' [dB] ' };
556+ legendMargins(: ,4 ) = {' PM: ' };
557+ legendMargins(: ,6 ) = {' [deg] ' };
558+ if length(handles .SelectedListboxContents ) == 1
559+ S = allmargin(LoopGainMagResponseAbs ,LoopGainPhaseResponse ,w ' );
560+ GM = S .GainMargin(1 );
561+ PM = S .PhaseMargin(1 );
562+ GMFreq = S .GMFrequency(1 );
563+ PMFreq = S .PMFrequency(1 );
564+
565+ legendMargins{2 } = num2str(mag2db(GM ));
566+ legendMargins{5 } = num2str(PM );
567+ legendMargins = strcat(legendMargins{1 }, legendMargins{2 }, ...
568+ legendMargins{3 }, legendMargins{4 }, legendMargins{5 }, ...
569+ legendMargins{6 });
570+ else
571+ for i = 1 : length(handles .SelectedListboxContents )
572+ S(i ) = allmargin(LoopGainMagResponseAbs(: ,i ),LoopGainPhaseResponse(: ,i ),w ' );
573+ GM(i ) = S(i ).GainMargin(1 );
574+ PM(i ) = S(i ).PhaseMargin(1 );
575+ GMFreq(i ) = S(i ).GMFrequency(1 );
576+ PMFreq(i ) = S(i ).PMFrequency(1 );
577+ legendMargins{i ,2 } = num2str(mag2db(GM(i )));
578+ legendMargins{i ,5 } = num2str(PM(i ));
579+ end
580+ legendMargins = strcat(legendMargins(: ,1 ), legendMargins(: ,2 ), ...
581+ legendMargins(: ,3 ), legendMargins(: ,4 ), legendMargins(: ,5 ), ...
582+ legendMargins(: ,6 ));
583+ end
584+ end
550585
551586 if exportData
552587 frd_Plant = frd(PlantFRF , w );
@@ -575,17 +610,23 @@ function BodePlot(handles, undock, exportData)
575610 h(i ) = semilogx(w , Controller_MagResponse(: ,i ), ' Color' , ones(1 ,3 )*plotCol(i ), ' LineStyle' , plotLineStyle{2 }, ' LineWidth' , plotLineWidth(2 ));
576611 hold on
577612 end
578- if get(handles .PlotLoopGain_checkbox , ' Value' ), hold on
613+ if get(handles .PlotLoopGain_checkbox , ' Value' )
579614 h(i ) = semilogx(w , LoopGainMagResponse(: ,i ), ' Color' , ones(1 ,3 )*plotCol(i ), ' LineStyle' , plotLineStyle{3 }, ' LineWidth' , plotLineWidth(3 ));
615+ hold on
616+ h(i ) = semilogx([GMFreq(i ) GMFreq(i )], [0 - mag2db(GM(i ))], ' Color' , [0 0.8 0 ], ' LineStyle' , plotLineStyle{2 }, ' LineWidth' , plotLineWidth(1 ));
617+ h(i ) = semilogx(GMFreq(i ), - mag2db(GM(i )), ' o' , ' Color' , [0 0.8 0 ], ' LineStyle' , plotLineStyle{1 }, ' LineWidth' , plotLineWidth(1 ));
580618 end
581619 end
582620 semilogx(w , zeros(1 ,length(w )), ' LineStyle' , ' --' , ' Color' , ' k' , ' LineWidth' , 0.5 )
583621 xticklabels([])
584622 ylabel(' Magnitude [dB]' )
585623 set(gca , ' XScale' , ' log' )
586624 grid on
625+
626+ legendEntry = handles .SelectedListboxContents ;
627+ legendEntry = strcat(legendEntry ,legendMargins );
587628 if exist(' h' , ' var' )
588- legend(h , handles . SelectedListboxContents , ' Location' , ' SouthWest' )
629+ legend(h , legendEntry , ' Location' , ' SouthWest' )
589630 end
590631
591632 if undock
@@ -595,13 +636,24 @@ function BodePlot(handles, undock, exportData)
595636 end
596637 for i = 1 : length(handles .SelectedListboxContents )
597638 if get(handles .PlotNom_checkbox , ' Value' )
598- semilogx(w , PlantPhaseResponse(: ,i ), ' Color' , ones(1 ,3 )*plotCol(i ), ' LineStyle' , plotLineStyle{1 }, ' LineWidth' , plotLineWidth(1 )), hold on
639+ semilogx(w , PlantPhaseResponse(: ,i ), ' Color' , ones(1 ,3 )*plotCol(i ), ' LineStyle' , plotLineStyle{1 }, ' LineWidth' , plotLineWidth(1 ));
640+ hold on
599641 end
600642 if not(AllDisabled )
601- semilogx(w , Controller_PhaseResponse(: ,i ), ' Color' , ones(1 ,3 )*plotCol(i ), ' LineStyle' , plotLineStyle{2 }, ' LineWidth' , plotLineWidth(2 )), hold on
643+ semilogx(w , Controller_PhaseResponse(: ,i ), ' Color' , ones(1 ,3 )*plotCol(i ), ' LineStyle' , plotLineStyle{2 }, ' LineWidth' , plotLineWidth(2 ));
644+ hold on
602645 end
603646 if get(handles .PlotLoopGain_checkbox , ' Value' )
604- semilogx(w , LoopGainPhaseResponse(: ,i ), ' Color' , ones(1 ,3 )*plotCol(i ), ' LineStyle' , plotLineStyle{3 }, ' LineWidth' , plotLineWidth(3 )), hold on
647+ semilogx(w , LoopGainPhaseResponse(: ,i ), ' Color' , ones(1 ,3 )*plotCol(i ), ' LineStyle' , plotLineStyle{3 }, ' LineWidth' , plotLineWidth(3 ));
648+ hold on
649+ if PM(i ) >= 0
650+ dotPM = - 180 + PM(i );
651+ else
652+ dotPM = 180 + PM(i );
653+ end
654+ linePM = [-180 dotPM ];
655+ h(i ) = semilogx([PMFreq(i ) PMFreq(i )], linePM , ' Color' , [0 0.8 0 ], ' LineStyle' , plotLineStyle{2 }, ' LineWidth' , plotLineWidth(1 ));
656+ h(i ) = semilogx(PMFreq(i ), dotPM , ' o' , ' Color' , [0 0.8 0 ], ' LineStyle' , plotLineStyle{1 }, ' LineWidth' , plotLineWidth(1 ));
605657 end
606658 end
607659 semilogx(w , 180 * ones(1 ,length(w )), w , - 180 * ones(1 ,length(w )), ' LineStyle' , ' --' , ' Color' , ' k' , ' LineWidth' , 0.5 )
0 commit comments