How could I use "batteryChart" to plot Simscape battery objects on UIAxes in AppDesigner?

Hi everyone,
the "batteryChart" command plots battery objects created with Simscape Battery (e.g. cell, module, pack).
However, when trying to use "batteryChart" in AppDesigner to plot on a UIAxes object, this does not work.
Assume that
cell
contains all relevant information on a cell object.
Then
batteryChart(app.UIAxes,app.cell)
yields the following error message:
simscape.battery.builder.BatteryChart cannot be a child of matlab.ui.control.UIAxes.
This is because the syntax of "batteryChart" is as follows:
chart = batteryChart(Parent,Battery)
where "Parent" is a Figure Object, according to MATLAB Help:
Parent Container for battery visualization
Figure object (default)
My problem is: I don't have figure objects in AppDesigner, as AppDesigner plots on UIAxes objects.
Any help or workaround would be highly appreciated!
Thanks in advance,
Hartmuth

4 Comments

Hi @ Hartmuth,
Could you please let me know if you need further assistance or help.
Hi Umar,
first of all: thanks for your efforts! At first sight, it looks great.
I will look into this in detail tomorrow, then I can give you a profound feedback!
Thanks,
Hartmuth.
Hi @Harmuth,
Thank you for your kind words and for taking the time to review my work. I appreciate your efforts in providing detailed feedback, and I look forward to hearing your thoughts after you have had a chance to examine everything closely.
Hi Hartmuth,
As I understand it from reading the doc, the uiaxes object has a parent container, which by default is created from uifigure. Does batteryChart work if the first argument is the handle to the parent of the uiaxes into which you want to plot, assuming the uiaxes were created using the default settings or specifying a figure as its parent?

Sign in to comment.

 Accepted Answer

Hi Hartmuth,
in the following I will provide information on how this works:
You are correct that the documentation shows only "figure" as a valid Parent. I will create an enhancement request for our development team to review this part of the documentation in order to make it easier to understand how this works and to also describe what is supported.
In general you can also input a uifigure or a different container, like uipanel or uigridlayout as a Parent.
So the following would work:
myCell = batteryCell(batteryCylindricalGeometry);
myUiFigure = uifigure;
batteryChart(myUiFigure,myCell);
or with uigridlayout
fig = uifigure('Position',[100 100 440 320]);
g = uigridlayout(fig);
g.RowHeight = {220,220,'1x'};
g.ColumnWidth = {1500,'1x'};
dd1 = uidropdown(g);
dd1.Items = {'Select a device'};
myCell = batteryCell(batteryCylindricalGeometry);
dd2 = batteryChart(g,myCell);
dd2.Layout.Row = 2;
dd2.Layout.Column = 1;
Thanks for reaching out to us in a Technical Support case.
If there are any further question, please let us know.
Best Regards,
Oliver

9 Comments

Thanks again Oliver for providing your quick and professional support, this perfectly solves my challenges.
Best regards,
Hartmuth
Is a "uifigure" distinct from a "figure" object? When I run the following code (2024a), the result is
>> g = uifigure;get(g,'Type')
ans =
'figure'
batteryChart should define/clarify the containers it can accept for Parent; other than that, what else needs to be clarified to show how this works?
Hi @Paul, you are correct. Nowadays uifigure and figure are not differing that much when querying the class/type information.
But sometimes features do not support uifigures or vice versa, for a simple example check the uigridlayout functionality:
"Parent container, specified as a Figure object created using the uifigure function or one of its child containers: Tab, Panel, ButtonGroup, or GridLayout. If you do not specify a parent container, MATLAB calls the uifigure function to create a new Figure object that serves as the parent container."
This feature only works with uifigures and with figures you get:
fig = figure;
g = uigridlayout(fig);
Error using uigridlayout (line 56)
Functionality not supported with figures created with the figure function.
I know that it is more general and good to simply say that Parents of type figure are supported since actually both works, but since also other container types are working, it was unclear at the beginning if this is supported by design. So in order to make it clearer I believe it would be good to point out in the doc, that figure/uifigure works and container objects of uifigure. Besides this a small example with uifigures can quickly highlight that this works.
I conveyed this to the development team and also pointed to this thread, so if you have any further recommendation, please comment here.
Oliver

Hi @Oliver Jaehrig ,

Thanks for responding and helping out resolving this issue. I agree with @Paul commenting, “ batteryChart should define/clarify the containers it can accept for Parent “. You did point out some essential information regarding figure and uifigure may appear similar at first glance, their functionalities diverge significantly, particularly when it comes to UI components like uigridlayout. By clarifying these distinctions in the documentation and providing illustrative examples, users will be better equipped to utilize MATLAB's GUI capabilities effectively. In my opinion, to enhance clarity in the documentation, it would be beneficial to explicitly state the following points:

Compatibility: Clearly indicate that uigridlayout and other UI-specific functionalities are only supported with uifigure objects. This will help users avoid confusion and errors when developing their applications.

Examples: Provide simple examples demonstrating the use of uigridlayout with uifigure. For instance:

% Creating a uifigure and using uigridlayout
uif = uifigure; % Creates a uifigure
g = uigridlayout(uif, [2, 2]); % Creates a 2x2 grid layout
% Adding UI components to the grid layout
btn1 = uibutton(g, 'Text', 'Button 1');
btn2 = uibutton(g, 'Text', 'Button 2');
btn3 = uibutton(g, 'Text', 'Button 3');
btn4 = uibutton(g, 'Text', 'Button 4');

This example illustrates how to create a uifigure, apply uigridlayout, and add buttons to the layout, showcasing the intended use of these functions. In my opinion, continuous improvement in documentation is essential for user experience.

I'm still confused as to whether or not a uifigure is an object distinct from a figure object, or if uifigure is a function that returns a figure object. Based on uifigure and my illustration in this comment I'm inclined to believe the latter, but your response above makes it sound like the former.
The uifigure and figure function both create figure objects, but the capabilities of these figures are different.
Please see this documentation:
which mentions:
"MATLAB® provides two functions to create a figure window: figure and uifigure. While both of these functions create a Figure object, there are some differences in the way that this object is configured and the capabilities it supports. Figures created using the uifigure function are configured primarily for app building, whereas figures created using the figure function are configured primarily for data exploration and visualization."
but also:
"The figure function will continue to be supported, but there are many new app building capabilities that can be used only with UI figures."
the latter was the main reason to speak about uifigures in a more distinct way.
So it is fine to only speak about figure objects in the batteryChart documentation and you were right with your linked comment. The only other workflow which I discussed was the use of other containers, which is not yet covered in the doc.
Also I maybe confused you, because I myself was not precise enough with my wording in the first comment when writing "You are correct that the documentation shows only "figure" as a valid Parent." since this is actually correct ☺and I should have worded it differently.
Thanks for clariying. I've never used uifigures before (perhaps obviously), but after reading the link in your comment and some other doc pages, it's apparent that a figure created by figure and a figure created by uifigure aren't the same type of object (as opposed to both being figure objects but with different parameter settings). But if that's the case, do you know why the Type parameter of the uifigure is 'figure'? I thought that would lead to confusion in some circumstances. For example
fig1 = figure; fig2 = figure;
uifig1 = uifigure; uifig2 = figure;
Now suppose I want to change the properties of the figures, but not the uifigures, perhaps with something like
hfig = findobj(0,'Type','figure');
set(hfig, ...);
I thought that hfig would have four elements, so whenever we call findobj like this, we'd have to slice off the uifigure handles, if we could figure out which elements of hfig to slice. But it turns out that hfig only has two elements, one for fig1 and one for fig2. So that's what we want, but why are the uifigure handles not returned insofar as they both have Type == 'figure'. Conversely, what should the findobj parameters be if we want to find the handles to all of the uifigures, but not the figures? (Apologies if this is discussed at findobj, I didn't see anything on point).
More generally, I'm quite curious about the design choice to make figures and uifigures both have the same Type, even though they are not really of the same type.
I hope the following provides some clarity to your open questions:
  1. Same Object Type: Both figure and uifigure commands create objects of the same type, matlab.ui.Figure. This is why they both have the Type property set to 'figure'. The distinction between them lies primarily in their default property values, such as HandleVisibility and AutoResizeChildren, rather than in their fundamental object type.
  2. Current Differences: While there are some differences in functionalities between figure and uifigure due to their historical development paths, these are temporary. The goal is to unify these functionalities in a future release.
  3. Using findobj: The results from using findobj are influenced by the HandleVisibility property. Typically, uifigure objects are created with different HandleVisibility (is "off" for uifigures, which is why you did not find these) settings compared to figure objects. This is intentional, as uifigure is often used for building apps where you might not want all components to appear in findobj results.
  4. In an upcoming release, the differences between figure and uifigure will mainly be about the default property values upon creation. The long-term aim is to make them functionally equivalent, making it unnecessary to differentiate between them.
For now, if you need to specifically target uifigure objects, you might consider checking their properties or default settings that are unique to them, such as AutoResizeChildren or their initial HandleVisibility.
Ok. Regarding 1 and 2: If they have different functionalities then it seems like they would be different types of objects. But I gather that this difference is temporary, so I can see why the current situation is what it is.
Regarding 3, thanks for that clarification.

Sign in to comment.

More Answers (1)

Hi @Hartmuth,

You mentioned, “Any help or workaround would be highly appreciated!”

After reviewing your comments, it sounds like that the challenge you are facing arises from the fact that the batteryChart function is designed to work with Figure objects, while AppDesigner primarily utilizes UIAxes for plotting. However, there are workarounds that can help you achieve your goal. One effective method is to create a hidden Figure object in the background, plot the battery chart there, and then transfer the visual output to the UIAxes. Below is a detailed step-by-step guide along with a complete code example.

Create a Hidden Figure: This figure will serve as the parent for the batteryChart.

Plot the Battery Chart: Use the batteryChart function to plot the battery data on the hidden figure.

Copy the Chart to UIAxes: Extract the chart data and render it on the UIAxes.

Here is a complete example that demonstrates how to implement this workaround in AppDesigner:

 classdef BatteryApp < matlab.apps.AppBase
    % Properties that correspond to app components
    properties (Access = public)
        UIFigure  matlab.ui.Figure
        UIAxes    matlab.ui.control.UIAxes
        PlotButton matlab.ui.control.Button
    end
    properties (Access = private)
        Cell % Battery cell object
    end
    methods (Access = private)
        % Button pushed function: PlotButton
        function PlotButtonPushed(app, event)
            % Create a hidden figure
            hiddenFig = figure('Visible', 'off');
            % Create a battery cell object (example parameters)
            app.Cell = simscape.battery.Cell('NominalVoltage', 3.7, ...
                                              'Capacity', 2.5, ...
                                              'InternalResistance', 0.05);
            % Plot the battery chart on the hidden figure
            batteryChart(hiddenFig, app.Cell);
            % Get the current axes from the hidden figure
            ax = hiddenFig.CurrentAxes;
            % Copy the chart data to the UIAxes
            copyobj(allchild(ax), app.UIAxes);
            % Close the hidden figure
            close(hiddenFig);
        end
    end
    % Construct app
    methods (Access = public)
        % Create UI components and initialize the app
        function app = BatteryApp
            % Create and configure components
            createComponents(app)
        end
        % Create UI components
        function createComponents(app)
            % Create UIFigure
            app.UIFigure = uifigure('Visible', 'off');
            app.UIFigure.Position = [100 100 400 300];
            app.UIFigure.Name = 'Battery Chart App';
            % Create UIAxes
            app.UIAxes = uiaxes(app.UIFigure);
            app.UIAxes.Position = [50 50 300 200];
            % Create PlotButton
            app.PlotButton = uibutton(app.UIFigure, 'push');
            app.PlotButton.Position = [150 10 100 30];
            app.PlotButton.Text = 'Plot Battery';
            app.PlotButton.ButtonPushedFcn = @(src, event) PlotButtonPushed(app, 
            event);
            % Show the figure after all components are created
            app.UIFigure.Visible = 'on';
        end
    end
  end

So, in the above code, the main application class inherits from matlab.apps.AppBase. The app contains properties for the UI components and the battery cell object. PlotButtonPushed Method is triggered when the button is pressed. It creates a hidden figure, plots the battery chart, and then copies the chart to the UIAxes and createComponents Method initializes the UI components, including the figure, axes, and button.

By following the above steps and utilizing the provided code, you can successfully plot battery objects using batteryChart within AppDesigner. This workaround will allow you to leverage the capabilities of batteryChart while adhering to the UI design principles of AppDesigner.

Hope this helps.

If you have any further questions or need additional assistance, feel free to ask!

5 Comments

Hi Umar,
thanks again for your efforts!
Unfortunately, this does not work. The problem is that the "BatterChart" class does not have the "Children" property. So the "allchild" command produces an error:
Error using simscape.battery.builder.BatteryChart/get
Unrecognized property Children for class simscape.battery.builder.BatteryChart.
So copyobj can't do its job to copy the contents of the figure to the UIAxes ...
any other suggestions?
Another thing: the line in your example code for the definition of the cell
app.Cell = simscape.battery.Cell(....
is not a valid syntax, it should be replaced by e.g.
geometry = batteryPouchGeometry;
app.Cell = batteryCell(geometry);
to define a generic Cell object.
Thanks,
Hartmuth

Hi @Hartmuth,

Thank you for your detailed feedback regarding the issues with the BatteryChart class and your clarification on cell object creation syntax. Let me address both concerns systematically. Since the BatteryChart class does not have a Children property, you cannot use copyobj to transfer its contents directly to UIAxes. Here are some alternative approaches you can consider: Instead of copying, you can create a new chart in your UIAxes by instantiating a new BatteryChart object directly in the desired axes. For example:

    % Assuming 'ax' is your UIAxes handle and 'pack' is your 
    battery pack object
    packChart = batteryChart(ax, pack);

If you are looking to visualize specific parameters over time (like state of charge or temperature), consider using data logging techniques. The batterySimulationLog object allows you to capture simulation data that can then be plotted independently of the BatteryChart. For more information on this object, please refer to

https://www.mathworks.com/help/simscape-battery/ref/simscape.battery.builder.batterysimulationlog.html?searchHighlight=batterySimulationLog&s_tid=srchtitle_support_results_1_batterySimulationLog

Regarding your point about cell creation syntax, you are correct that the line:

app.Cell = simscape.battery.Cell(....)

is incorrect. Instead, you should define your cell object as follows:

geometry = batteryPouchGeometry; % or any appropriate geometry 
function
app.Cell = batteryCell(geometry);

This change ensures that you're correctly instantiating a batteryCell object with the specified geometry.

If further challenges arise, feel free to ask for more specific guidance!

Okay, Umar ... so your ChatGPT answers fail here unfortunately.
The proposed syntax
packChart = batteryChart(ax, pack);
uses UIAxes objects and this does not work, because batteryChart needs a figure - if you read my initial question again, this was exactly the problem from the very beginning.
I also remind you that according to the Community Participation Guidelines of MATLAB Central, it is mandatory to "clearly indicate when AI generated content is incorporated into any post or submission on the platform, verify and test the AI generated content [...]".
Please consider this in your further contributions to MATLAB Central.

Hi @Hartmuth,

If that is the case then it should not have provided link to mathworks. I am trying to help you out here and this is how you are appreciating my contributions.

Sign in to comment.

Products

Release

R2024b

Asked:

on 22 Oct 2024

Commented:

on 31 Oct 2024

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!