6 Robust FlexPendant applications. ABB RobotWare 5.0
Robot Application Builder (RAB) is a software tool, which enables ABB programmers to develop customized operator interfaces for the IRC5 robot controller. Robot Application Builder is fully integrated with Microsoft Visual Studio, which means that a .NET programmer will recognize wizards for project setup, tools for visual design support, and debug etc.
Advertisement
Advertisement
6 Robust FlexPendant applications
5.5.8. System info domain
6 Robust FlexPendant applications
3HAC028083-001 Revision: D 181
6 Robust FlexPendant applications
6.1. Introduction
6.1. Introduction
Overview
Developing an application for a device with limited resources, such as memory and process power, can be quite demanding. Moreover, to have an application executing around the clock will reveal weaknesses in design and implementation that may cause slow performance or
FlexPendant hangings.
At worst, your application will drain the FlexPendant of all memory during production, and cause an out-of-memory crash. It can even slow down the performance of the robot controller due to excessive use of controller resources.
This chapter describes how to design and implement reliable and well performing applications for the FlexPendant. It presents some good practices to utilize, as well as some pitfalls that should be avoided.
Technical overview of the FlexPendant device
The FlexPendant device consists of both hardware and software and is a complete computer in itself, with its own memory, file system, operating system and processor.
It is an integral part of IRC5, connected to the controller by an integrated cable and connector.
Using the hot plug button option, however, you can disconnect the FlexPendant in automatic mode and continue running without it.
There are ways to restart the FlexPendant without having to restart the controller (See
Restart the FlexPendant on page 49
). At a FlexPendant restart the assemblies and resources of
FlexPendant SDK applications are downloaded to the FlexPendant file system from the robot controller.
FlexPendant applications run on Windows CE, a scalable embedded operating system, and the .NET Compact Framework, which is Microsoft’s lightweight version of the .NET
Framework, intended for small devices.
This is the size of the FlexPendant touch screen:
FlexPendant screen
Size
Total display
FP SDK Application display
640 * 480 pixels
640 * 390 pixels
The FlexPendant uses these kinds of memory:
Memory type Function
Flash - 16 MB
RAM - 64 MB
E
2
PROM
Stores the FlexPendant standard software, the Windows
CE operating system in compressed format and the registry.
At boot time the compressed image is copied to RAM. All execution of code uses RAM.
Stores touch screen calibration values, joystick calibration values etc. Only used internally.
How large can a custom application be?
You may wonder about the maximum size of your custom application. There is no exact answer to that question, as there are many variables to take into account. For a rough estimation the table below can be used. As you see, the operating system uses about 8 MB
182
Continues on next page
3HAC028083-001 Revision: D
6 Robust FlexPendant applications
6.1. Introduction
Continued
and the ABB base software about 25 MB. This means that half of the available RAM memory is already used once the FlexPendant has started up. The standard applications of the ABB menu and the FlexPendant SDK applications will all share the memory that is left. As a rule of thumb, about 20 MB should be available for custom applications.
FlexPendant memory resources
RAM
Operating system
ABB base software
Custom applications
64 MB
8 MB
25 MB
~20 MB
This is some advice to help you make sure your application does not exceed the memory limitation:
1. Do not allow more than ONE instance by setting the
TpsViewType
parameter of the
TpsView
attribute to
Static
for detailed information.
2. Avoid excessive use of images. Do not use bigger images than necessary. Check the size of the images your application will use.
3. Use fpcmd “-memShow” to check the amount of memory in use when your application is active. Open a couple of Program Editors and start RAPID execution.
See
Discover memory leaks on page 186
for further information.
4. Avoid static
data and methods.
5. Release memory for objects that are not used by calling their
Dispose
method.
3HAC028083-001 Revision: D 183
6 Robust FlexPendant applications
6.2. Memory management
6.2. Memory management
Garbage collection and Dispose
An important feature of the .NET runtime environment is the garbage collector, which reclaims not referenced memory from the managed heap. Generally, this means that the programmer should not have to free memory which has been allocated by the use of new
. A drawback, when memory is limited, is that the execution of the garbage collector is nondeterministic. There is no way of knowing exactly when garbage collection will be performed.
The
IDisposable
interface, however, represents a way to obtain deterministic deallocation of resources. You should therefore call
Dispose()
on all disposable object when they are no longer needed, as this will free up valuable resources as soon as possible.
Moreover, objects used to access robot controller resources, must be released by the custom application by an explicit call to their
Dispose
method.
SignalBindingSource
and
RapidDataBindingSouce
objects, as well as all other objects located in the components pane of the VS Designer must also be explicitly disposed of, or else your application will have a permanent memory leak.
NOTE!
The creator of an object implementing the
IDisposable
interface is responsible for its lifetime and for calling
Dispose
.
TIP!
You may wonder why the .NET garbage collector cannot ensure that all objects no longer referenced are finally destroyed? The FlexPendant development team have tried hard to remove any remaining objects of an SDK application at application shut down, for example implemented finalizers for the
TpsControl
,
RapidDataBindingSouce
and
SignalBindingSource
classes. Due to Microsoft’s implementation, however, the .NET
184
Continues on next page
3HAC028083-001 Revision: D
6 Robust FlexPendant applications
6.2. Memory management
Continued
runtime nonetheless refuses to destroy these objects unless their
Dispose
method is called.
This behavior is under debate. If you are curious to find out more about this, these community articles may be of interest.
Dispose, Finalization, and Resource Management (Joe Duffy): http://www.bluebytesoftware.com/blog/PermaLink.aspx?guid=88e62cdf-5919-4ac7-bc33-
20c06ae539ae
Garbage Collection: Automatic Memory Management in the Microsoft .NET
Framework (MSDN-magazine): ms-help://ms.msdnqtr.v80.en/ms.msdn.v80/dnmag00/ html/GCI.htm
Finalization - cbrumme's WebLog: http://blogs.msdn.com/cbrumme/archive/2004/02/20/
77460.aspx
Application Framework usage - ITpsViewSetup
The application framework TAF, which hosts the controls that make up a FlexPendant application, offers some mechanisms that should be used by client applications. See
Understanding FlexPendant application life cycle on page 52
to learn more about TAF.
Your application view class should implement
ITpsViewSetup
and
ITpsViewActivation
ITpsViewSetup and ITpsViewActivation on page 58
for general information on these interfaces and
Application Framework usage - ITpsViewActivation on page 190
to learn how to use
ITpsViewActivation
to improve performance.
The
ITpsViewSetup
interface has two methods:
Install
and
Uninstall
.
Install
is called when the view is being created, right after the constructor has been executed.
Uninstall
is called when the client view is closed down. After
Uninstall
has been called,
TAF will also call the
Dispose
method of the view class. These methods thus offer the last opportunity for you to clean up and release memory and system resources held by the custom application.
NOTE!
The user should close down the application by using the close button, [x], in the upper right corner of the display, in the same way as the Program Data or other standard applications are closed. Never implement a close button on the first view. When the application is closed the correct way, first
Deactivate
, then
Uninstall
and finally
Dispose
will be called by TAF.
How to program the Dispose method - example
When starting a new FlexPendant project in Visual Studio a skeleton for the
Dispose
method is auto generated. You should use it to add code for cleaning up as shown by the figure below:
3HAC028083-001 Revision: D
Continues on next page
185
6 Robust FlexPendant applications
6.2. Memory management
Continued
7.2_1
NOTE!
Error handling should be added to the
Dispose
method (left out in the figure).
NOTE!
Ensure you have unsubscribed to any events from the robot controller before you call the
Dispose
method of a CAPI object. If it has been done in the
Deactivate
method, which is what is usually recommended, you should not do it again in the
Dispose
method. Also ensure you do not try to access an object after it has been disposed.
Discover memory leaks
When your application interacts with the robot controller, unmanaged objects are created under the hood. If you forget to call
Dispose
on such objects there will be memory leaks.
You are recommended to test the memory consumption of your application. Use a controller console window on your PC and the command fpcmd_enable_console_output
3 to enable printouts. Then use the
"-memShow"
command with a period argument that produces a printout every 500 second for example, like this:
-> period 500, fpcmd, “-memShow”
Result:
task spawned: id = 0xba7f3b8, name = t2value = 195556280 = 0xba7f3b8-> [fp]: Available memory: 20881408 (tot 40394752), disk: 737148 (tot 1728512) load: 54(261955)[fp]:
Test all functions of your application with several other FlexPendant views visible in the task bar and possibly one or several RAPID tasks executing. Observe how your implementation affects memory. The load component shows current memory load on the FlexPendant
186
Continues on next page
3HAC028083-001 Revision: D
6 Robust FlexPendant applications
6.2. Memory management
Continued
expressed in percentage and the figures in the parenthesis are number of ms after start-up.
Close your application and make sure the same amount of memory is available as before opening it.
The procedure below shows yet another way of checking that your application cleans up correctly:
Step Action
3
4
1
2
5
Log out from the FlexPendant by pressing Log Off on the ABB menu.
In the controller console window write fpcmd_enable_console_output
.
Write fpcmd "-a"
.
For each cpp class check Number of instances. It shall be 0, except for
AdaptController
(1) and
AdaptEventImpl
(1).
If the previous step shows that there are unmanaged objects left, you need to search your code for missing
Dispose
calls.
NOTE!
You must use the real FlexPendant device when verifying memory consumption and looking for memory leaks in your code.
3HAC028083-001 Revision: D 187
6 Robust FlexPendant applications
6.3. Performance
6.3. Performance
About performance
A FlexPendant application cannot meet hard real time demands. There should however be no difference in performance between a FlexPendant SDK application and the standard applications of the device. If your application is slow, the advice in this section will be useful.
TIP!
Do not get overwhelmed by the number of restrictions presented in this section. Most of the time you will not notice any difference if you decide to neglect a few of them. Yet - it is good to know what can be done whenever performance does become an issue.
Less code means faster code
A general piece of advice (maybe too obvious a recommendation) is that less code normally means faster code. Remember that methods that are executed frequently, such as
OnPaint
, event handlers etc. must be efficient. Everything that can be computed once and stored for future use should be computed only once.
Fewer controller accesses means faster code
The best thing you can do to improve performance is probably to ensure that you do not access controller functionality more often than necessary. To achieve this you need to understand CAPI, the SDK class libraries used to access robot controller functionality.
It is very easy to use a property of a class and not realize that an access to the controller is actually made. A general recommendation is to try to use subscriptions to controller information (events) where applicable, and let your application store updated values instead of performing numerous reading operations toward the same controller resource.
TIP!
You can easily get an estimate of the number of controller accesses your application performs in different user scenarios by using a robot controller console. The console command robdisp_watch 2
monitors and prints controller accesses made by the FlexPendant to the console. Press a button of your application for example, and study how the FlexPendant and the controller communicate in response to this action. Enter the command robdisp_watch
188
Continues on next page
3HAC028083-001 Revision: D
6 Robust FlexPendant applications
6.3. Performance
Continued
0
to turn this service off. (The monitor service slows down the response time of your application, due to printing to the console. So don’t get worried if your application seems unusually slow!)
NOTE!
Keep in mind that an excessive number of controller accesses will slow down the performance of your application. At worst, it may even affect the performance of the robot controller.
NOTE!
Excessive use of subscriptions may also be a problem. If your application has to handle a continuous load of Rapid data and I/O signal events, and your event handlers need to manipulate the data before presenting it, GUI interaction may become slow. As a rule of thumb, do not estimate more than 20 events/sec. and keep the event handlers thin.
Fewer objects means faster code
Fewer objects means better performance. If you know that an object will be used again, create it once and keep a reference. Also, try not to create objects that may not be used.
Reusing existing objects instead of creating new ones is especially important when executing the same code repeatedly, e.g. in tight loops.
This example shows how this should be done: object _o = new object(); for (int i = 0; i < 100000; i++)
{ ... }
TIP!
Do not create several
Controller
objects, but reuse it by sending it as a parameter when creating a new view, or share it between classes as a public property.
Transferring files
Transferring files between the device and the robot controller takes time and also occupies storage memory on the device. Write efficient and fault-tolerant code if it must be done.
3HAC028083-001 Revision: D
Continues on next page
189
6 Robust FlexPendant applications
6.3. Performance
Continued
Application Framework usage - ITpsViewActivation
The
ITpsViewActivation
interface is used by TAF to hide and display your application. It has two methods:
Activate
and
Deactivate
. The former is called by TAF at the creation of the client view, right after the
ITpsViewSetup.Install
method has been executed. The latter is called at shut down of the client view, right before the
ITpsViewSetup.Uninstall method is executed.
The interface is also used when the user selects another application on the task bar. TAF then calls
ITpsViewActivation.Deactivate
(but not
ITpsViewSetup.Uninstall
).
Likewise, when the application regains focus via the task bar icon, TAF calls
ITpsViewActivation.Activate
(but not
ITpsViewSetup.Install
).
It is recommended to enable and disable any subscriptions to controller events in the
ITpsViewActivation
methods, as valuable resources should not be held when the application is not used. Note that current values should be read before enabling the subscription.
For the same reason, any timers can be activated and deactivated in these methods. That way timers will not run when other applications are in focus, thus saving processor power.
Excessive string manipulation is costly
The string class is an immutable type, i.e. once a string is created its value cannot be changed.
This means that string methods that seem to modify the string in fact create new strings.
Look at a this string concatenation example: string name = "192.168.126.1"; string str = "/" + name + "/" + "RAPID";
Four strings will be appended to one resulting string. No less than four additional strings will be created and allocated when the right hand side of the assignment is executed. A better idea is to use the
StringBuilder
class or string.Forma
t (which uses the
StringBuilder internally): string str = string.Format("/{0}/RAPID", name);
As a rule, if you are going to do only one string operation on a particular string, you can use the appropriate string method. It is when you start doing numerous string operations that you need to use
StringBuilder
or string.Format.
190
Continues on next page
3HAC028083-001 Revision: D
6 Robust FlexPendant applications
6.3. Performance
Continued
Avoid Control.Refresh
Control.Refresh()
must only be used when an immediate update of the GUI is absolutely required.
Refresh
makes a direct call to the
OnPaint
method of the Control, and is therefore much more costly than
Control.Invalidate()
.
Several calls to
Invalidate
will not mean several calls to
OnPaint
. When the GUI thread processes the
Invalidate
message all queued up messages of the same control are handled at the same time, thus saving process power.
NOTE!
In the 2.0 version of .NET CF there are new methods to be used for GUI controls inheriting
System.Windows.Forms.Control
:
•
SuspendLayout()
•
ResumeLayout()
•
BeginUpdate()
•
EndUpdate()
These methods are used to control GUI updates while modifying a GUI element. The control will not be drawn when
SuspendLayout
has been called, for example, but is blocked until
ResumeLayout
is called.
Avoid boxing and unboxing
A common reason for slow code is unintentional boxing and unboxing. To avoid this, you need to be aware of the difference between reference and value types. Reference types (the keyword class is used) are always allocated on the heap, while value types are allocated on the stack; unless embedded into a reference type.
Boxing is the operation where a value type, is converted to a reference type. It is done automatically when a reference to a value type is required. Then a new object will be created, allocated on the heap with a copy of the original data.
Here are some examples of not so obvious boxing/unboxing:
• Using the foreach
statement on an array that contains value types will cause the values to be boxed and unboxed.
•
Accessing values of a Hashtable with a value type key, will cause the key value to be boxed when the table is accessed.
• Using an ArrayList with value types; this should be avoided - use typed arrays instead.
Typed arrays are also better because of type safety, as type checking can be performed at compile time.
•
The following methods should be overridden in order to avoid unnecessary boxing/ unboxing: Equals( ), GetHashCode( ).
3HAC028083-001 Revision: D
Continues on next page
191
6 Robust FlexPendant applications
6.3. Performance
Continued
Foreach
Using a for
loop is often faster than using the foreach
statement, especially if a large number of iterations are made. The reason is that the JIT compiler (see
About terms and acronyms on page 18
) is prohibited to optimize the code execution when
foreach
is used.
However, foreach
makes the code more readable and is therefore a better option when performance is not crucial.
Reflection is performance demanding
Reflection is a mechanism used to read the meta data of an assembly. The
typeof
operator, for example, uses reflection to determine the type of an object. Another example is object.ToString()
, which also uses reflection.
As reflection is very performance demanding you are recommended to override or to avoid the
ToString()
method for reference types.
Efficiently parsing Xlm
XmlTextReader
and
XmlDocument
can both be used to parse xml data. The
XmlTextReader
is the preferred option in most cases; it is more light weight (less memory footprint) and a lot faster to instantiate. The limitation of the
XmlTextReader
is that forward only reading is possible.
The xml structure may also have an impact on performance. If xml data is organized in non- flat way, search operations will be faster, as a large portion of the information can be skipped.
This is achieved by using categories and sub categories.
192 3HAC028083-001 Revision: D
6 Robust FlexPendant applications
6.4. Reliability
6.4. Reliability
Overview
This section presents information on how to make the application robust. The most important mechanism related to robustness and reliability is error handling. Avoiding thread conflicts and memory leaks are however also important means of improving reliability.
Error handling in .NET applications
As already pointed out in this manual, Microsoft recommends that exceptions are used to discover and report anomalities in .NET applications. If you are not sure about when to use
exceptions or how to do the implementation you should read
to understand the general idea before moving on to the FlexPendant specific information of this section.
3HAC028083-001 Revision: D
Continues on next page
193
6 Robust FlexPendant applications
6.4. Reliability
Continued
SDK exception classes
The
ABB.Robotics
namespace provides quite a few exception classes, used by the
FlexPendant SDK and SDK applications. In addition, the SDK also uses
System
exceptions and may throw a
System.ArgumentException
object for example.
Whenever an exception is thrown, your application must catch it and take proper action. You catch an exception by using the try-catch(-finally)
statements. See
for further information about how to implement these statements.
As you see in the figure below
GeneralException
derives from
BaseException
, which in turn derives from
System.ApplicationException
of the .NET Framework class library.
ApplicationException
is thrown by user programs, such as the FlexPendant SDK, not by
the Common Language Runtime (CLR, see
way to differentiate between exceptions defined by applications versus exceptions defined by the system.
194
7.4_1
As you see there are derived types under
GeneralException
. These types are listed and briefly described below:
Continues on next page
3HAC028083-001 Revision: D
6 Robust FlexPendant applications
6.4. Reliability
Continued
7.4_2
3HAC028083-001 Revision: D
Continues on next page
195
6 Robust FlexPendant applications
6.4. Reliability
Continued
TIP!
Learn more about the FlexPendant SDK exception classes by using the FlexPendant SDK
Reference Documentation Help.
Thread affinity
You should be aware that execution of code modifying the user interface, has to be done on the thread that created the GUI control, the so called GUI thread.
An application initially starts with a single thread. Normally all user interface controls are created by this thread. Windows CE user interface objects are characterized by thread affinity, which means that they are closely coupled with the thread that created them.
Interacting with the message queue of an interface control from a thread other then the creating thread may cause data corruption or other errors. This restriction applies to the thread pool as well as to explicitly created threads.
When executing on a secondary thread, a so called worker thread, an update of the user interface must therefore be done very carefully, enforcing a switch to the GUI thread. This is in fact a very common scenario, as controller events use their own threads and should often be communicated to the end user by a GUI update.
NOTE!
Thread affinity is especially relevant as for robot controller events, as these by default execute on a background thread. See
GUI and controller event threads in conflict on page 68
for further information along with code samples. The following
section also deals with the same issue.
Invoke
In order to execute a method on the GUI thread
Control.Invoke
can be used. It should however be done carefully, as it makes a synchronous call to the specified event handler, which blocks execution until the GUI thread has finished executing the method. All concurrent calls to
Invoke
will be queued and executed in their queue order by the GUI thread. This could easily make the GUI less responsive.
There is now an asynchronous version of
Invoke
, which should be used instead whenever possible.
TpsControl.BeginInvoke
is a non blocking method, which lets the worker thread continue execution instead of waiting for the GUI thread to have processed the method
Remember that
Invoke
as well as BeginInvoke should only be used on code that modifies the user interface. You should keep the execution on the background thread as long as possible.
NOTE!
If your code tries to access a GUI control from a background thread the .NET common language runtime will throw a
System.NotSupportedException
.
Memory leaks
196
As FlexPendant applications are supposed to run without interruption, no memory leaks can be permitted. It is your responsibility to properly clean up and call
Dispose
. Take your time
How to avoid memory leaks on page 93
and
Continues on next page
3HAC028083-001 Revision: D
6 Robust FlexPendant applications
6.4. Reliability
Continued
Technical overview of the FlexPendant device on page 182
.
Utilizing multi-threading
Threading enables your program to perform concurrent processing so you can do more than one operation at a time. For example, you can use threading to monitor input from the user, and perform background tasks simultaneously. The
System.Threading
namespace provides classes and interfaces which enable you to easily perform tasks such as creating and starting new threads, synchronizing multiple threads, suspending threads and aborting threads.
The classes
Thread
and
ThreadPool
can be used to execute methods on a worker thread.
Use
ThreadPool
for temporary usage of a background thread when a task is meant to terminate fairly soon. Use
Thread
only for background work that will persist, e.g. a thread that fetches data from the controller continuously.
There are two timers available in .NET CF that can be used to execute methods periodically at specified intervals. There is however, an important difference between these. The
System.Threading.Timer
executes the method on a background thread, while the
System.Windows.Forms.Timer
executes the method on the UI thread.
NOTE!
Use
System.Threading.Timer
if you want to poll data from the controller in order to reduce the load on the GUI thread.
Lock statement
The lock
statement is used in multi-threaded applications to make sure access to a part of the code is made by one thread exclusively. If a second thread attempts to lock code which has already been locked by another thread, it must wait until the lock is released.
Remember to limit the code segment that you want to control, i.e. only lock what is absolutely necessary to make the code thread safe:
Object thisLock = new Object(); lock (thisLock)
{
// Critical code section
}
Deadlocks must be avoided. They can occur if more than one lock is used. If more than one lock object must be held, they must always be locked and released in the same order, wherever they are used.
3HAC028083-001 Revision: D
Continues on next page
197
6 Robust FlexPendant applications
6.4. Reliability
Continued
NOTE!
If a deadlock occurs, the FlexPendant system will hang. If this happens you should attach the device to the Visual Studio debugger and study the call stack of the threads in the Threads window.
CAUTION!
Using the lock
statement in combination with a call to
Invoke
is a potential cause to deadlock situations, since
Invoke
is a blocking call. In short, be careful if you use locks!
Multicast delegates
If a multicast delegate is executed, the execution of the delegates is terminated if an exception is thrown by one of the delegates. It means that the remaining delegates in the list will not be executed if an exception is thrown. This situation can cause erratic behavior, which may be tricky to trace and debug.
Therefore, if you have numerous delegates which are to execute as the result of the same event, you may want to implement the
GetInvocationList
method. It retrieves a list with a copy of the delegates. This list can be iterated and each delegate called directly:
7.4_3
198 3HAC028083-001 Revision: D
Download
Advertisement
Key features
Develop custom operator interfaces
FlexPendant SDK
PC SDK
Visual Studio integration
.NET programming
Virtual IRC5
Frequently asked questions
Robot Application Builder (RAB) is a software tool, which enables programmers to develop customized operator interfaces for the IRC5 robot controller.
The supported operating systems are Microsoft Windows XP + SP2 or Windows Vista + SP1.
The supported versions are Visual Studio 2005 and Visual Studio 2008.
The supported programming languages are C# and Visual Basic.NET for FlexPendant applications. For PC applications, any of the .NET languages should work, however, ABB support is only offered for Visual Basic and C#.