Announcing the Release of Apache Flink 1.15
May 5, 2022 - Joe Moser (@JoemoeAT) Yun Gao (@YunGao16)Thanks to our well-organized and open community, Apache Flink continues to grow as a technology and remain one of the most active projects in the Apache community. With the release of Flink 1.15, we are proud to announce a number of exciting changes.
One of the main concepts that makes Apache Flink stand out is the unification of batch (aka bounded) and stream (aka unbounded) data processing, which helps reduce the complexity of development. A lot of effort went into this unification in the previous releases, and you can expect more efforts in this direction.
Apache Flink is not only growing when it comes to contributions and users, but also out of the original use cases. We are seeing a trend towards more business/analytics use cases implemented in low-/no-code. Flink SQL is the feature in the Flink ecosystem that enables such uses cases and this is why its popularity continues to grow.
Apache Flink is an essential building block in data pipelines/architectures and is used with many other technologies in order to drive all sorts of use cases. While new ideas/products may appear in this domain, existing technologies continue to establish themselves as standards for solving mission-critical problems. Knowing that we have such a wide reach and play a role in the success of many projects, it is important that the experience of integrating Apache Flink with the cloud infrastructures and existing systems is as seamless and easy as possible.
In the 1.15 release the Apache Flink community made significant progress across all these areas. Still those are not the only things that made it into 1.15. The contributors improved the experience of operating Apache Flink by making it much easier and more transparent to handle checkpoints and savepoints and their ownership, making auto scaling more seamless and complete, by removing side effects of use cases in which different data sources produce varying amounts of data, and - finally - the ability to upgrade SQL jobs without losing the state. By continuing on supporting checkpoints after tasks finished and adding window table valued functions in batch mode, the experience of unified stream and batch processing was once more improved making hybrid use cases way easier. In the SQL space, not only the first step in version upgrades have been added but also JSON functions to make it easier to import and export structured data in SQL. Both will allow users to better rely on Flink SQL for production use cases in the long term. To establish Apache Flink as part of the data processing ecosystem we improved the cloud interoperability and added more sink connectors and formats. And yes we enabled a Scala-free runtime (the hype is real).
Operating Apache Flink with ease #
Even Flink jobs that have been built and tuned by the best engineering teams still need to be operated, usually on a long-term basis. The many deployment patterns, APIs, tunable configs, and use cases covered by Apache Flink mean that operation support is vital and can be burdensome.
In this release, we listened to user feedback and now operating Flink is made much
easier. It is now more transparent in terms of handling checkpoints and savepoints and their ownership,
which makes auto-scaling more seamless and complete (by removing side effects of use cases
where different data sources produce varying amounts of data) and enables the
ability to upgrade SQL jobs without losing the state.
Clarification of checkpoint and savepoint semantics #
An essential cornerstone of Flink’s fault tolerance strategy is based on checkpoints and savepoints (see the comparison). The purpose of savepoints has always been to put transitions, backups, and upgrades of Flink jobs in the control of users. Checkpoints, on the other hand, are intended to be fully controlled by Flink and guarantee fault tolerance through fast recovery, failover, etc. Both concepts are quite similar, and the underlying implementation also shares aspects of the same ideas.
However, both concepts grew apart by following specific feature requests and sometimes neglecting the overarching idea and strategy. Based on user feedback, it became apparent that this should be aligned and harmonized better and, above all, to make more clear!
There have been situations in which users relied on checkpoints to stop/restart jobs when savepoints would have been the right way to go. It was also not clear that savepoints are slower since they don’t include some of the features that make taking checkpoints so fast. In some cases like resuming from a retained checkpoint - where the checkpoint is somehow considered as a savepoint - it is unclear to the user when they can actually clean it up.
With FLIP-193 (Snapshots ownership) the community aims to make ownership the only difference between savepoints and checkpoints. In the 1.15 release the community has fixed some of those shortcomings by supporting native and incremental savepoints. Savepoints always used to use the canonical format which made them slower. Also writing full savepoints for sure takes longer than doing it in an incremental way. With 1.15 if users use the native format to take savepoints as well as the RocksDB state backend, savepoints will be automatically taken in an incremental manner. The documentation has also been clarified to provide a better overview and understanding of the differences between checkpoints and savepoints. The semantics for resuming from savepoint/retained checkpoint have also been clarified introducing the CLAIM and NO_CLAIM mode. With the CLAIM mode Flink takes over ownership of an existing snapshot, with NO_CLAIM it creates its own copy and leaves the existing one up to the user. Please note that NO_CLAIM mode is the new default behavior. The old semantic of resuming from savepoint/retained checkpoint is still accessible but has to be manually selected by choosing LEGACY mode.
Elastic scaling with reactive mode and the adaptive scheduler #
Driven by the increasing number of cloud services built on top of Apache Flink, the project is becoming more and more cloud native which makes elastic scaling even more important.
This release improves metrics for the reactive mode, which is a job-scope mode where the JobManager will try to use all TaskManager resources available. To do this, we made all the metrics in the Job scope work correctly when reactive mode is enabled.
We also added an exception history for the adaptive scheduler, which is a new scheduler that first declares the required resources and waits for them before deciding on the parallelism with which to execute a job.
Furthermore, downscaling is sped up significantly. The TaskManager now has a dedicated shutdown code path, where it actively deregisters itself from the cluster instead of relying on heartbeats, giving the JobManager a clear signal for downscaling.
Adaptive batch scheduler #
In 1.15, we introduced a new scheduler to Apache Flink: the Adaptive Batch Scheduler. The new scheduler can automatically decide parallelisms of job vertices for batch jobs, according to the size of data volume each vertex needs to process.
Major benefits of this scheduler includes:
- Ease-of-use: Batch job users can be relieved from parallelism tuning.
- Adaptive: Automatically tuned parallelisms can better fit consumed datasets which have a varying volume size every day.
- Fine-grained: Parallelism of each job vertex will be tuned individually. This allows vertices of SQL batch jobs to be automatically assigned different proper parallelisms.
Watermark alignment across data sources #
Having data sources that increase watermarks at different paces could lead to problems with downstream operators. For example, some operators might need to buffer excessive amounts of data which could lead to huge operator states. This is why we introduced watermark alignment in this release.
For sources based on the new source interface, watermark alignment can be activated. Users can define alignment groups to pause consuming from sources which are too far ahead from others. The ideal scenario for aligned watermarks is when there are two or more sources that produce watermarks at a different speed and when the source has the same parallelism as splits/shards/partitions.
SQL version upgrades #
The execution plan of SQL queries and its resulting topology is based on optimization rules and a cost model. This means that even minimal changes could introduce a completely different topology. This dynamism makes guaranteeing snapshot compatibility very challenging across different Flink versions. In the efforts of 1.15, the community focused on keeping the same query (via the same topology) up and running even after upgrades.
At the core of SQL upgrades are JSON plans (please note that we only have documentation in our JavaDocs for now and are still working on updating the documentation), which are JSON functions that make it easier to import and export structured data in SQL. This has been introduced for internal use already in previous releases and will now be exposed externally. Both the Table API and SQL will provide a way to compile and execute a plan which guarantees the same topology throughout different versions. This feature will be released as an experimental MVP. Users who want to give it a try already can create a JSON plan that can then be used to restore a Flink job based on the old operator structure. The full feature can be expected in Flink 1.16.
Reliable upgrades makes Flink SQL more dependable for production use cases in the long term.
Changelog state backend #
In Flink 1.15, we introduced the MVP feature of the changelog state backend, which aims at making checkpoint intervals shorter and more predictable with the following advantages:
- Shorter end-to-end latency: end-to-end latency mostly depends on the checkpointing mechanism, especially for transactional sinks. Transactional sinks commit on checkpoints, so faster checkpoints mean more frequent commits.
- More predictable checkpoint intervals: currently checkpointing time largely depends on the size of the artifacts that need to be persisted on the checkpoint storage. By keeping the size consistently small, checkpointing time becomes more predictable.
- Less work on recovery: with more frequently checkpoints are taken, less data need to be re-processed after each recovery.
The changelog state backend helps achieve the above by continuously persisting state changes on non-volatile storage while performing state materialization in the background.
Repeatable cleanup #
In previous releases of Flink, cleaning up job-related artifacts was done only once which might have resulted in abandoned artifacts in case of an error. In this version, Flink will try to run the cleanup again to avoid leaving artifacts behind. This retry mechanism runs until it was successful, by default. Users can change this behavior by configuring the repeatable cleanup options. Disabling the retry strategy will lead to Flink behaving like in previous releases.
There is still work in progress around cleaning up checkpoints, which is covered by FLINK-26606.
OpenAPI #
Flink is now providing an experimental REST API specification following the OpenAPI standard. This allows the REST API to be used with standard tools that are implementing the OpenAPI standard. You can find the specification here.
Improvements to application mode #
When running Flink in application mode, it can now be guaranteed that jobs will take a savepoint after they are completed if they have been configured to do so (see execution.shutdown-on-application-finish).
The recovery and clean up of jobs running in application mode has also been improved. The local state can be persisted in the working directory, which makes recovering from local storage easier.
Unification of stream and batch processing - more progress #
In the latest release, we picked up new efforts and continued some previous ones in the goal of unifying stream and batch processing.
Final checkpoints #
In Flink 1.14, final checkpoints were added as a feature that had to be enabled manually. Since the last release, we listened to user feedback and decided to enable it by default. For more information and how to disable this feature, please refer to the documentation. This change in configuration can prolong the shutting down sequence of bounded streaming jobs because jobs have to wait for a final checkpoint before being allowed to finish.
Window table-valued functions #
Window table-valued functions have only been available for unbounded data streams. With this release they will also be usable in BATCH mode. While working on this, change window table-valued functions have also been improved in general by implementing a dedicated operator which no longer requires those window functions to be used with aggregators.
Flink SQL #
Community metrics indicate that Flink SQL is widely used and becomes more popular every day. The community made several improvements but we’d like to go into two in more detail.
CAST/Type system enhancements #
Data appears in all sorts and shapes but is often not in the type that you need it to be, which is why casting is one of the most common operations in SQL. In Flink 1.15, the default behavior of a failing CAST has changed from returning a null to returning an error, which makes it more compliant with the SQL standard. The old casting behavior can still be used by calling the newly introduced TRY_CAST function or restored via a configuration flag.
In addition, many bugs have been fixed and improvements made to the casting functionality, to ensure correct results.
JSON functions #
JSON is one of the most popular data formats and SQL users increasingly need to build and read these data structures. Multiple JSON functions have been added to Flink SQL according to the SQL 2016 standard. It allows users to inspect, create, and modify JSON strings using the Flink SQL dialect.
Community enablement #
Enabling people to build streaming data pipelines to solve their use cases is our goal. The community is well aware that a technology like Apache Flink is never used on its own and will always be part of a bigger architecture. Thus, it is important that Flink operates well in the cloud, connects seamlessly to other systems, and continues to support programming languages like Java and Python.
Cloud interoperability #
There are users operating Flink deployments in cloud infrastructures from various cloud providers. There are also services that offer to manage Flink deployments for users on their platform.
In Flink 1.15, a recoverable writer for Google Cloud Storage has been added. We also organized the connectors in the Flink ecosystem and put some focus on connectors for the AWS ecosystem (i.e. KDS, Firehose).
The Elasticsearch sink #
There was significant work on Flink’s overall connector ecosystem, but we want to highlight the Elasticsearch sink because it was implemented with the new connector interfaces, which offers asynchronous functionality coupled with end-to-end semantics. This sink will act as a template in the future.
A Scala-free Flink #
A detailed
blog post
already explains the ins and outs of why Scala users can now use the Flink
Java API with any Scala version (including Scala 3).
In the end, removing Scala is just part of a larger effort of cleaning up and updating various technologies from the Flink ecosystem.
Starting in Flink 1.14, we removed the Mesos integration, isolated Akka, deprecated the DataSet Java API, and hid the Table API behind an abstraction. There’s already a lot of traction in the community towards these endeavors.
PyFlink #
Before Flink 1.15, Python user-defined functions were executed in separate Python processes which caused additional serialization/deserialization and communication overhead. In scenarios in with large amounts of data, e.g. image processing, etc, this overhead becomes non-negligible. Besides, since it involves inter-process communication, the processing latency is also non-negligible, which is unacceptable in scenarios for which latency is critical, e.g. quantitative transaction, etc. In Flink 1.15, we have introduced a new execution mode named ’thread’ mode, for which Python user-defined functions will be executed in the JVM as a thread instead of a separate Python process. Benchmarks have shown that throughput could be increased by 2x in common scenarios such as JSON processing. Processing latency is also decreased from several seconds to micro-seconds. It should be noted that since this is still the first release of ’thread’ mode, it currently only supports Python ScalarFunction which is used in Python Table API & SQL. We’re planning to extend it to other areas in which Python user-defined functions could be used in the next releases.
Other #
Further work has been done on the connector testing framework. If you want to contribute a connector or improve on one, you should definitely have a look.
Some long-awaited features have been added, including the CSV format and the small file compaction in the unified sink interface.
The sink API has been upgraded to version 2 and we encourage every connector maintainer to upgrade to this version.
Summary #
Apache Flink is now easier to operate, made even more progress towards aligning stream and batch processing, became more accessible through improvements in the SQL components, and now integrates better with other technologies.
It is also worth mentioning that the community has set up a new home for the CDC connectors, the connector repository will be externalized (with the Elasticsearch sink as a first example), and there is now a Kubernetes operator (announcement blogpost maintained by the community.
Moving forward, the community will continue to focus on making Apache Flink a true unified stream and batch processor and work on better integrating Flink into the cloud-native ecosystem.
Upgrade Notes #
While we aim to make upgrades as smooth as possible, some of the changes require users to adjust some parts of the program when upgrading to Apache Flink 1.15. Please take a look at the release notes for a list of applicable adjustments and issues during upgrades. The one big thing worth mentioning when upgrading is the updated dependencies without the Scala version. Get the details here.


SpriteBox class
A RenderBox
that draws a sprite world represented by a Node tree.
Constructors
- SpriteBox(NodeWithSize rootNode, [ SpriteBoxTransformMode mode = SpriteBoxTransformMode.letterbox ])
- Creates a new SpriteBox with a node as its content, by default uses letterboxing. [...]
Properties
- frameRate → double
-
An instantaneous estimate of the number of frames per second this sprite box is producing.
read-only
- rootNode ↔ NodeWithSize
-
The root node of the node tree that is rendered by this box. [...]
read / write
- transformMatrix → Matrix4
-
The transformation matrix used to transform the root node to the space of the box. [...]
read-only
- transformMode ↔ SpriteBoxTransformMode
-
The transform mode used by the SpriteBox.
read / write
- visibleArea → Rect
-
A rectangle that represents the visible area of the sprite world's
coordinate system.
read-only
- alwaysNeedsCompositing → bool
-
Whether this render object always needs compositing. [...]
@protected, read-only, inherited
- attached → bool
-
Whether this node is in a tree whose root is attached to something. [...]
read-only, inherited
- constraints → BoxConstraints
-
The box constraints most recently received from the parent.
read-only, inherited
- debugCanParentUseSize → bool
-
Whether the parent render object is permitted to use this render object's
size. [...]
read-only, inherited
- debugCreator ↔ dynamic
-
The object responsible for creating this render object. [...]
read / write, inherited
- debugDoingThisLayout → bool
-
Whether performLayout for this render object is currently running. [...]
read-only, inherited
- debugDoingThisPaint → bool
-
Whether paint for this render object is currently running. [...]
read-only, inherited
- debugDoingThisResize → bool
-
Whether performResize for this render object is currently running. [...]
read-only, inherited
- debugLayer → OffsetLayer
-
In debug mode, the compositing layer that this render object uses to repaint. [...]
read-only, inherited
- debugNeedsLayout → bool
-
Whether this render object's layout information is dirty. [...]
read-only, inherited
- debugNeedsPaint → bool
-
Whether this render object's paint information is dirty. [...]
read-only, inherited
- debugSemantics → SemanticsNode
-
The semantics of this render object. [...]
read-only, inherited
- depth → int
-
The depth of this node in the tree. [...]
read-only, inherited
- hashCode → int
-
The hash code for this object. [...]
read-only, inherited
- hasSize → bool
-
Whether this render object has undergone layout and has a size.
read-only, inherited
- isRepaintBoundary → bool
-
Whether this render object repaints separately from its parent. [...]
read-only, inherited
- layer → OffsetLayer
-
The compositing layer that this render object uses to repaint. [...]
read-only, inherited
- needsCompositing → bool
-
Whether we or one of our descendants has a compositing layer. [...]
read-only, inherited
- owner → PipelineOwner
-
The owner for this node (null if unattached). [...]
read-only, inherited
- paintBounds → Rect
-
Returns a rectangle that contains all the pixels painted by this box. [...]
read-only, inherited
- parent → AbstractNode
-
The parent of this node in the tree.
read-only, inherited
- parentData ↔ ParentData
-
Data for use by the parent render object. [...]
read / write, inherited
- runtimeType → Type
-
A representation of the runtime type of the object.
read-only, inherited
- semanticBounds → Rect
-
The bounding box, in the local coordinate system, of this
object, for accessibility purposes.
read-only, inherited
- size ↔ Size
-
The size of this render box computed during layout. [...]
@protected, read / write, inherited
- sizedByParent → bool
-
Whether the constraints are the only input to the sizing algorithm (in
particular, child nodes have no impact). [...]
@protected, read-only, inherited
Methods
-
attach(
PipelineOwner owner) → void -
detach(
) → void - Mark this node as detached. [...]
-
findNodesAtPosition(
Offset position) → List< Node> - Finds all nodes at a position defined in the box's coordinates. [...]
-
handleEvent(
PointerEvent event, _SpriteBoxHitTestEntry entry) → void - Override this method to handle pointer events that hit this render object. [...]
-
hitTest(
HitTestResult result, { Offset position }) → bool - Determines the set of render objects located at the given position. [...]
-
paint(
PaintingContext context, Offset offset) → void - Paint this render object into the given context at the given offset. [...]
-
performLayout(
) → void -
adoptChild(
RenderObject child) → void -
Called by subclasses when they decide a render object is a child. [...]
inherited
-
applyPaintTransform(
RenderObject child, Matrix4 transform) → void -
Multiply the transform from the parent's coordinate system to this box's
coordinate system into the given transform. [...]
inherited
-
assembleSemanticsNode(
SemanticsNode node, SemanticsConfiguration config, Iterable< SemanticsNode> children) → void -
Assemble the
SemanticsNode
for thisRenderObject
. [...]inherited -
clearSemantics(
) → void -
Removes all semantics from this render object and its descendants. [...]
@mustCallSuper, inherited
-
computeDistanceToActualBaseline(
TextBaseline baseline) → double -
Returns the distance from the y-coordinate of the position of the box to
the y-coordinate of the first given baseline in the box's contents, if
any, or null otherwise. [...]
@protected, inherited
-
computeMaxIntrinsicHeight(
double width) → double -
Computes the value returned by getMaxIntrinsicHeight. Do not call this
function directly, instead, call getMaxIntrinsicHeight. [...]
@protected, inherited
-
computeMaxIntrinsicWidth(
double height) → double -
Computes the value returned by getMaxIntrinsicWidth. Do not call this
function directly, instead, call getMaxIntrinsicWidth. [...]
@protected, inherited
-
computeMinIntrinsicHeight(
double width) → double -
Computes the value returned by getMinIntrinsicHeight. Do not call this
function directly, instead, call getMinIntrinsicHeight. [...]
@protected, inherited
-
computeMinIntrinsicWidth(
double height) → double -
Computes the value returned by getMinIntrinsicWidth. Do not call this
function directly, instead, call getMinIntrinsicWidth. [...]
@protected, inherited
-
debugAdoptSize(
Size value) → Size -
Claims ownership of the given Size. [...]
inherited
-
debugAssertDoesMeetConstraints(
) → void -
Verify that the object's constraints are being met. Override
this function in a subclass to verify that your state matches
the constraints object. This function is only called in checked
mode and only when needsLayout is false. If the constraints are
not met, it should assert or throw an exception.
inherited
-
debugDescribeChildren(
) → List< DiagnosticsNode> -
inherited
-
debugFillProperties(
DiagnosticPropertiesBuilder properties) → void -
inherited
-
debugHandleEvent(
PointerEvent event, HitTestEntry entry) → bool -
Implements the
debugPaintPointersEnabled
debugging feature. [...]inherited -
debugPaint(
PaintingContext context, Offset offset) → void -
Override this method to paint debugging information.
inherited
-
debugPaintBaselines(
PaintingContext context, Offset offset) → void -
In debug mode, paints a line for each baseline. [...]
@protected, inherited
-
debugPaintPointers(
PaintingContext context, Offset offset) → void -
In debug mode, paints a rectangle if this render box has counted more
pointer downs than pointer up events. [...]
@protected, inherited
-
debugPaintSize(
PaintingContext context, Offset offset) → void -
In debug mode, paints a border around this render box. [...]
@protected, inherited
-
debugRegisterRepaintBoundaryPaint(
{bool includedParent: true, bool includedChild: false }) → void -
Called, in checked mode, if isRepaintBoundary is true, when either the
this render object or its parent attempt to paint. [...]
inherited
-
debugResetSize(
) → void -
If a subclass has a "size" (the state controlled by
parentUsesSize
, whatever it is in the subclass, e.g. the actualsize
property ofRenderBox
), and the subclass verifies that in checked mode this "size" property isn't used when debugCanParentUseSize isn't set, then that subclass should override debugResetSize to reapply the current values of debugCanParentUseSize to that state.inherited -
describeApproximatePaintClip(
RenderObject child) → Rect -
Returns a rect in this object's coordinate system that describes
the approximate bounding box of the clip rect that would be
applied to the given child during the paint phase, if any. [...]
inherited
-
describeSemanticsConfiguration(
SemanticsConfiguration config) → void -
Report the semantics of this node, for example for accessibility purposes. [...]
@protected, inherited
-
dropChild(
RenderObject child) → void -
Called by subclasses when they decide a render object is no longer a child. [...]
inherited
-
getDistanceToActualBaseline(
TextBaseline baseline) → double -
Calls computeDistanceToActualBaseline and caches the result. [...]
@mustCallSuper, @protected, inherited
-
getDistanceToBaseline(
TextBaseline baseline, { bool onlyReal: false }) → double -
Returns the distance from the y-coordinate of the position of the box to
the y-coordinate of the first given baseline in the box's contents. [...]
inherited
-
getMaxIntrinsicHeight(
double width) → double -
Returns the smallest height beyond which increasing the height never
decreases the preferred width. The preferred width is the value that
would be returned by getMinIntrinsicWidth for that height. [...]
@mustCallSuper, inherited
-
getMaxIntrinsicWidth(
double height) → double -
Returns the smallest width beyond which increasing the width never
decreases the preferred height. The preferred height is the value that
would be returned by getMinIntrinsicHeight for that width. [...]
@mustCallSuper, inherited
-
getMinIntrinsicHeight(
double width) → double -
Returns the minimum height that this box could be without failing to
correctly paint its contents within itself, without clipping. [...]
@mustCallSuper, inherited
-
getMinIntrinsicWidth(
double height) → double -
Returns the minimum width that this box could be without failing to
correctly paint its contents within itself, without clipping. [...]
@mustCallSuper, inherited
-
getTransformTo(
RenderObject ancestor) → Matrix4 -
Applies the paint transform up the tree to
ancestor
. [...]inherited -
globalToLocal(
Offset point, { RenderObject ancestor }) → Offset -
Convert the given point from the global coordinate system in logical pixels
to the local coordinate system for this box. [...]
inherited
-
hitTestChildren(
HitTestResult result, { Offset position }) → bool -
Override this method to check whether any children are located at the
given position. [...]
@protected, inherited
-
hitTestSelf(
Offset position) → bool -
Override this method if this render object can be hit even if its
children were not hit. [...]
@protected, inherited
-
invokeLayoutCallback<
T extends Constraints> (LayoutCallback< T> callback) → void -
Allows mutations to be made to this object's child list (and any
descendants) as well as to any other dirty nodes in the render tree owned
by the same
PipelineOwner
as this object. Thecallback
argument is invoked synchronously, and the mutations are allowed only during that callback's execution. [...]@protected, inherited -
layout(
Constraints constraints, { bool parentUsesSize: false }) → void -
Compute the layout for this render object. [...]
inherited
-
localToGlobal(
Offset point, { RenderObject ancestor }) → Offset -
Convert the given point from the local coordinate system for this box to
the global coordinate system in logical pixels. [...]
inherited
-
markNeedsCompositingBitsUpdate(
) → void -
Mark the compositing state for this render object as dirty. [...]
inherited
-
markNeedsLayout(
) → void -
Mark this render object's layout information as dirty, and either register
this object with its
PipelineOwner
, or defer to the parent, depending on whether this object is a relayout boundary or not respectively. [...]inherited -
markNeedsLayoutForSizedByParentChange(
) → void -
Mark this render object's layout information as dirty (like
markNeedsLayout), and additionally also handle any necessary work to
handle the case where sizedByParent has changed value. [...]
inherited
-
markNeedsPaint(
) → void -
Mark this render object as having changed its visual appearance. [...]
inherited
-
markNeedsSemanticsUpdate(
) → void -
Mark this node as needing an update to its semantics description. [...]
inherited
-
markParentNeedsLayout(
) → void -
Mark this render object's layout information as dirty, and then defer to
the parent. [...]
@protected, inherited
-
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a non-existent method or property is accessed. [...]
inherited
-
performResize(
) → void -
Updates the render objects size using only the constraints. [...]
inherited
-
reassemble(
) → void -
Cause the entire subtree rooted at the given
RenderObject
to be marked dirty for layout, paint, etc, so that the effects of a hot reload can be seen, or so that the effect of changing a global debug flag (such asdebugPaintSizeEnabled
) can be applied. [...]inherited -
redepthChild(
AbstractNode child) → void -
Adjust the depth of the given
child
to be greater than this node's own depth. [...]@protected, inherited -
redepthChildren(
) → void -
Adjust the depth of this node's children, if any. [...]
inherited
-
replaceRootLayer(
OffsetLayer rootLayer) → void -
Replace the layer. This is only valid for the root of a render
object subtree (whatever object scheduleInitialPaint was
called on). [...]
inherited
-
rotate(
{int oldAngle, int newAngle, Duration time }) → void -
Rotate this render object (not yet implemented).
inherited
-
scheduleInitialLayout(
) → void -
Bootstrap the rendering pipeline by scheduling the very first layout. [...]
inherited
-
scheduleInitialPaint(
ContainerLayer rootLayer) → void -
Bootstrap the rendering pipeline by scheduling the very first paint. [...]
inherited
-
scheduleInitialSemantics(
) → void -
Bootstrap the semantics reporting mechanism by marking this node
as needing a semantics update. [...]
inherited
-
setupParentData(
RenderObject child) → void -
Override to setup parent data correctly for your children. [...]
inherited
-
showOnScreen(
[RenderObject child ]) → void -
Attempt to make this or a descendant RenderObject visible on screen. [...]
inherited
-
toDiagnosticsNode(
{String name, DiagnosticsTreeStyle style }) → DiagnosticsNode -
inherited
-
toString(
{DiagnosticLevel minLevel }) → String -
inherited
-
toStringDeep(
{String prefixLineOne: '', String prefixOtherLines: '', DiagnosticLevel minLevel: DiagnosticLevel.debug }) → String -
Returns a description of the tree rooted at this node.
If the prefix argument is provided, then every line in the output
will be prefixed by that string.
inherited
-
toStringShallow(
{String joiner: '; ', DiagnosticLevel minLevel: DiagnosticLevel.debug }) → String -
Returns a one-line detailed description of the render object.
This description is often somewhat long. [...]
inherited
-
toStringShort(
) → String -
Returns a human understandable name.
inherited
-
visitChildren(
RenderObjectVisitor visitor) → void -
Calls visitor for each immediate child of this render object. [...]
inherited
-
visitChildrenForSemantics(
RenderObjectVisitor visitor) → void -
Called when collecting the semantics of this node. [...]
inherited
Operators
-
operator ==(
dynamic other) → bool -
The equality operator. [...]
inherited


{% extends 'commercialoperator/emails/base_email.html' %} {% block content %}
The E Class licence {{ approval.lodgement_number}} will expire on {{approval.expiry_date}}.
You can renew the E Class licence for five more years by clicking Extend action on the E Class licence.
{% endblock %}


Intro to CSS
This tutorial teaches CSS
Tutorial 1
To begin with tutorial 1......
Tutorial 2
To begin with tutorial 2......
Hello
World


--- layout: post title: Model Reference Adaptive Control comments: true permalink: mrac ---
Consider the following first-order linear system:
\begin{equation} \dot{x} = a x + bu, \label{eq:truesystem} \end{equation}where \(a,\,b\) are unknown parameters. However, the sign of \(b\) is known.
Suppose that we want the linear system \eqref{eq:truesystem} to track the following reference system:
\begin{equation} \dot{x_m} = a_m x_m + b_m r, \label{eq:refsystem} \end{equation}where \(a_m < 0\) and \(b_m\) are known and \(r(t)\) is a known reference signal.
Suppose we use the following control law:
\begin{equation} u = \hat k_x x + \hat k_r r. \end{equation}Then the dynamic of system \eqref{eq:truesystem} will be
\begin{equation} \dot{x} = (a + b \hat k_x) x + b \hat k_r r. \end{equation}Therefore, if we can make
\begin{equation} \hat k_x = k_x \triangleq \frac{a_m-a}{b}\text{ and }\hat k_r = k_r \triangleq \frac{b_m}{b}, \end{equation}then the dynamic of system \eqref{eq:truesystem} will follow the reference system. Let us denote \(\Delta k_x \triangleq k_x - \hat k_x\) and \(\Delta k_r \triangleq k_r - \hat k_r\).
Now consider the dynamic of the error \(e \triangleq x - x_m\), we have
\begin{align*} \dot{e}& = (a + b \hat k_x) x + b \hat k_r r - a_m x_m - b_m r\\ & = a_m(x - x_m) - b \Delta k_x x - b \Delta k_r r \\ & = a_m e - b \Delta k_x x - b \Delta k_r r . \end{align*}Therefore, if we consider the following candidate Lyapunov function
\begin{equation} V = \frac{1}{2}\left(e^2 + |b|(\gamma_x^{-1} \Delta k_x^2 + \gamma_r^{-1} \Delta k_r^2)\right), \end{equation}where \(\gamma_x,\,\gamma_r > 0\). Then we have
\begin{align*} \dot{V} = a_m e^2 &- |b|\Delta k_x \left(\text{sgn}(b)ex + \gamma_x^{-1}\dot{\hat k_x}\right) \\ &- |b|\Delta k_r \left(\text{sgn}(b)er + \gamma_r^{-1}\dot{\hat k_r}\right). \end{align*}Therefore, if we use the following update rule on \(\hat k_x\) and \(\hat k_r\):
\begin{equation} \dot{\hat k_x} = -\gamma_x \text{sgn}(b) ex\text{ and }\dot{\hat k_r} = -\gamma_r \text{sgn}(b) er,\\ \end{equation}then \(\dot{V} = a_m e^2 \leq 0\). One can then prove that \(\ddot{V} =2 a_m e \dot{e}\) is bounded and thus \(\lim_{t\rightarrow\infty} \dot{V} = 0\) and hence \(e \rightarrow 0\).
Assume that the system is given as
\begin{equation} \dot{x} = x + u, \end{equation}while we want the system to tract the following system:
\begin{equation} \dot{x_m} = - x_m + r = - x_m + \sin(t). \end{equation}import numpy as np import matplotlib import matplotlib.pyplot as plt import seaborn as sns # for the sake of appreances from scipy.integrate import odeint a = 1. b = 1. am = -1. bm = 1. gammax = 10. gammar = 10. # y is a vector of [x ,x_m, \hat k_x, \hat k_r] def f(y, t): x = y[0] xm = y[1] hatkx = y[2] hatkr = y[3] r = np.sin(t) e = x - xm u = hatkx * x + hatkr * r f0 = a * x + b * u f1 = am * xm + bm * r f2 = -1 * gammax * e * x f3 = -1 * gammar * e * r return [f0, f1, f2, f3] t = np.linspace(0, 20., 10000) x0 = 0. xm0 = 0. hatkx0 = 0. hatkr0 = 0. y0 = [x0, xm0, hatkx0, hatkr0] solution = odeint(f, y0, t) x = solution[:, 0] xm = solution[:, 1] hatkx = solution[:, 2] hatkr = solution[:, 3] fig = plt.figure() plt.rc('text', usetex=True) plt.plot(t, np.sin(t), label=r'$r(t)$') plt.plot(t, x, label=r'$x(t)$') plt.plot(t, xm, label=r'$x_m(t)$') plt.plot(t, hatkx, label=r'$\hat k_x(t)$') plt.plot(t, hatkr, label=r'$\hat k_r(t)$') plt.xlabel('Time(t)') plt.legend(loc = 0) fig.tight_layout() plt.savefig('../../public/mrac.png') return '../../public/mrac.png' # return the filename to org-mode
Figure 1: The simulation result for model reference adaptive control. Notice that \(e(t) = x(t) - x_m(t)\) converges to 0 and \(\hat k_x \rightarrow -2\) and \(\hat k_r \rightarrow 1\).


# some jinja code that eric needed to store #AA8347 stem #A0793D stem shade #966F33 main #8C6529 main shade #785115 bottom bottom shade 1 11 2 8 3 6 3 4 4 5 2 (stop)
TBA sample
I am a very simple card. I am good at containing small bits of information. I am convenient because I require little markup to use effectively.


{% extends "accounts.html" %} {% load i18n %} {% block title %}{% trans "Password Change Successfully" %}{% endblock %} {% block main_panel %}
{% trans "Your password has been changed successfully." %}