Jiro's pick this week is Data Acquisition Live app by Andrei Ursache.This is a very nice example of an app,... read more >>

]]>Jiro's pick this week is Data Acquisition Live app by Andrei Ursache.

This is a very nice example of an app, created using the App Designer, that makes use of the Data Acquisition Toolbox and Hardware Support Package for data acquisition hardware.

I downloaded the Data Acquisition Toolbox Support Package for Windows Sound Cards to get streaming data from my sound card.

I launch the app, select my sound card from the drop down menu, and click "Start" to start capturing audio from my microphone. Of course, you can save the audio data to a file for any post-processing.

**Comments**

Give it a try and let us know what you think here or leave a comment for Andrei.

Get
the MATLAB code

Published with MATLAB® R2018a

I have never written about these topics on this blog because this is not specific to Simulink, but... I am... read more >>

]]>**MATLAB Drive**

In case you did not know: If you have a MathWorks account, you have access to MATLAB Drive!

How do you access it? Let's begin with the method I use the most: MATLAB Drive Connector.

You can install MATLAB Drive Connector from this link. Once this is done, you will see a MATLAB Drive Connector icon in the taskbar, and clicking on it will allow you, for example, to see file activity and quickly navigate to your MATLAB Drive folder.

*Note: I am using on Windows, but this is also available for Mac and Linux.*

Another option is to access MATLAB Drive through a web browser, where you will be able to upload and download files:

I recommend looking at MATLAB Drive help for more details.

**MATLAB Online**

Another feature that works in combination with MATLAB Drive is MATLAB Online, which is also included with most license types. With MATLAB Online, your "working directory" is MATLAB Drive.

MATLAB Online offers limited support for Simulink. You cannot edit models, but you can simulate them as mentioned here.

**MATLAB Mobile**

MATLAB Mobile is another way to run MATLAB and simulate models. If you are not using it already, you can get it from Google Play or Apple App Store righ now.

Here is a screenshot of my iPad simulating a model:

**Advantages**

One obvious advantage of simulating models using MATLAB Online or MATLAB Mobile is that the computation is done online. This keeps your computer CPU available to do something else.

Another feature I really like is that your session is continuous. You can connect and disconnect interchangeably between MATLAB Online and MATLAB Mobile and the same session continues. This means I can start a simulation from MATLAB Online at work, disconnect and check on it later from MATLAB Mobile.

The last thing I want to highlight is that you can publish a script as HTML or PDF and share the address with anybody, even if they do not have a MathWorks Account.

You can see the results of my simulation above by visiting this link:

https://matlab.mathworks.com/users/guirlo/Published/simMyModel/index.html

Here is what it looks like:

**Now it's your turn**

Are you using MATLAB Online, MATLAB Mobile or MATLAB Drive? Let us know how in the comment below.

One final thought... If you enjoy running simulations online instead of on your computer, I also recommend looking into the options for Parallel Computing on the Cloud. This will allow you to scale up and run tons of simulations in the cloud at the same time.

]]>Doug Hull was the founder and owner of this blog for 10 years. I talked about his contributions in my... read more >>

]]>You may remember that MATLAB can generate code coverage information in the Cobertura format now. Been able to since R2017b.... read more >>

]]>One of these is the great codecov.io service. This service provides gorgeous views and, better yet, meaningful insight into your code coverage. Guess what? It supports the Cobertura format. Take a look at that last coverage post to remind yourself how we can create this Cobertura style coverage data from the MATLAB side. That's pretty much all you need. As it turns out, the good folks over at codecov.io seem to be hard at work making it super simple to get this going for your GitHub repos.

Once you have generated the coverage information, your CI system just needs one more build step to run their uploader script to codecov. This looks something like this as per their documentation:

bash <(curl -s https://codecov.io/bash)

There's not even a need to point to your coverage file or anything, codecov finds the Cobertura file you've generated in your workspace and automagically detects it and uploads it to boot.

Let's see this in action for a real repo. I took a quick peak around to find a good representative code repository, and I found and forked the Nonlinear Estimation Toolbox. I actually don't know much about what this toolbox does apart from the description they provide in the *did* notice that they have a nice collection of unit tests!

With nice unit tests usually comes nice coverage. Let's check it out for this repo with the help of Cobertura output and codecov.io. Step one is you need to create your account with codecov.

They allow doing this via GitHub, Bitbucket or GitLab:

From there you will want to add the repository you'd like to report your coverage on:

Once you add your desired repo (I made an unchanged fork of the Nonlinear Estimation Toolbox to get this to work for me), codecov.io will give you your API token for the coverage upload script.

Alright, now you have a token linked to your GitHub repo, and then all you need to do in your CI build is run that bash script as a build step after the Cobertura is generated. The way I did this was by using the EnvInject Jenkins plugin to create the CODECOV_TOKEN environment variable with the token value provide to me from the codecov site. remember, you don't want to share your token so this should be done privately as I've done below:

Then you just set up your bash script and run your job:

You've made it when you see some nice high quality ASCII art followed by some pleasant sounding (success implying) messages:

...and there we go. That's it! from now on you'll have all your coverage data up on codecov.io. For this repo, I was right that they have some pretty solid, 90.34% code coverage. What's more is that this tool makes it really easy to see areas not covered and add the appropriate testing. Check it out:

Does that seem as easy (and powerful) to you as it does to me? Are you using codecov.io or another coverage service out there? Interested to hear your experiences.

]]>Today I want to finish up my long-running discussion of Feret diameters. (Previous posts: 29-Sep-2017, 24-Oct-2017, 20-Feb-2018, and 16-Mar-2018.) ... read more >>

]]>Recall that the Feret diameter measures the extent of an object along a particular direction. The diagram below illustrates the concept. Place the object to be measured inside the jaws of a caliper, with the caliper oriented at a specified angle. Close the jaws tightly on the object while maintaining that angle. The distance between the jaws is the Feret diameter at that angle.

The *maximum Feret diameter* and *minimum Feret diameter* measure the maximum and minimum width of an object. In previous posts, I talked about how to identify *antipodal vertex pairs* from the set the convex hull vertices to speed up the process of finding these maximum and minimum measures. I also considered the various assumptions one can make about the shape of an individual pixel and how those assumptions can affect the results. (In the rest of this post, I'll assume a diamond pixel shape, as suggested by Cris.)

Let's look at these several measurements for a particular object.

```
bw = imread('shape.png');
imshow(bw)
```

visualizeFeretProperties(bw)

The first diagram above shows the maximum Feret diameter and its orientation. It also shows the Feret diameter at the angle that is orthogonal to the maximum diameter.

The second diagram is similar, except that it shows the minimum Feret diameter instead of the orthogonal diameter. You can see that they are not the same, and, in general, they won't be.

The third diagram shows the minimum-area bounding box, which can be found using a search procedure similar to the minimum Feret diameter. In this diagram, notice that the bounding box is not exactly aligned with the direction of the maximum Feret dimension. In general, they won't necessarily be aligned, and then the length of the minimum-area bounding box will be less than the maximum Feret dimension.

Below is a function I wrote that adds Feret diameter properties to the table returned by

T = regionprops('table',bw,'PixelList')

T=1×1 tablePixelList _________________ [163875×2 double]

T = feretProperties(T)

T=1×12 tablePixelList MaxFeretDiameter MaxFeretDiameterEndpoints MaxFeretDiameterOrientation MinFeretDiameter MinFeretDiameterTrianglePoints MinFeretDiameterOrientation OrthogonalDiameter OrthogonalDiameterLowerPoints OrthogonalDiameterUpperPoints MinAreaBoundingBox MinAreaBoundingBoxArea _________________ ________________ _________________________ ___________________________ ________________ ______________________________ ___________________________ __________________ _____________________________ _____________________________ __________________ ______________________ [163875×2 double] 781.13 [2×2 double] -41.835 317.08 [3×2 double] -143.8 331.18 [1×2 double] [1×2 double] [5×2 double] 2.4321e+05

I hope that at least a few of you enjoyed this diversion into algorithms associated with object shape measurement.

function T = feretProperties(T) % Copyright 2017-2018 The MathWorks, Inc. maxfd = zeros(height(T),1); maxfd_endpoints = cell(height(T),1); maxfd_orientation = zeros(height(T),1); minfd = zeros(height(T),1); minfd_triangle_points = cell(height(T),1); minfd_orientation = zeros(height(T),1); minod = zeros(height(T),1); minod_lower_points = cell(height(T),1); minod_upper_points = cell(height(T),1); minbb = cell(height(T),1); minbb_a = zeros(height(T),1); for k = 1:height(T) pixels = T.PixelList{k}; V = pixelHull(pixels,'diamond'); pairs = antipodalPairs(V); [maxfd(k),maxfd_endpoints{k}] = maxFeretDiameter(V,pairs); points = maxfd_endpoints{k}; e = points(2,:) - points(1,:); maxfd_orientation(k) = atan2d(e(2),e(1)); [minfd(k),minfd_triangle_points{k}] = minFeretDiameter(V,pairs); points = minfd_triangle_points{k}; e = points(2,:) - points(1,:); thetad = atan2d(e(2),e(1)); minfd_orientation(k) = mod(thetad + 180 + 90,360) - 180; [minod(k),minod_lower_points{k},minod_upper_points{k}] = ... feretDiameter(V,maxfd_orientation(k)+90); [minbb{k},minbb_a(k)] = minAreaBoundingBox(V,pairs); end T.MaxFeretDiameter = maxfd; T.MaxFeretDiameterEndpoints = maxfd_endpoints; T.MaxFeretDiameterOrientation = maxfd_orientation; T.MinFeretDiameter = minfd; T.MinFeretDiameterTrianglePoints = minfd_triangle_points; T.MinFeretDiameterOrientation = minfd_orientation; T.OrthogonalDiameter = minod; T.OrthogonalDiameterLowerPoints = minod_lower_points; T.OrthogonalDiameterUpperPoints = minod_upper_points; T.MinAreaBoundingBox = minbb; T.MinAreaBoundingBoxArea = minbb_a; end function [bb,A] = minAreaBoundingBox(V,antipodal_pairs) % Copyright 2017-2018 The MathWorks, Inc. if nargin < 2 antipodal_pairs = antipodalPairs(V); end n = size(antipodal_pairs,1); p = antipodal_pairs(:,1); q = antipodal_pairs(:,2); A = Inf; thetad = []; for k = 1:n if k == n k1 = 1; else k1 = k+1; end pt1 = []; pt2 = []; pt3 = []; if (p(k) ~= p(k1)) && (q(k) == q(k1)) pt1 = V(p(k),:); pt2 = V(p(k1),:); pt3 = V(q(k),:); elseif (p(k) == p(k1)) && (q(k) ~= q(k1)) pt1 = V(q(k),:); pt2 = V(q(k1),:); pt3 = V(p(k),:); end if ~isempty(pt1) % Points pt1, pt2, and pt3 are possibly on the minimum-area % bounding box, with points pt1 and pt2 forming an edge coincident with % the bounding box. Call the height of the triangle with base % pt1-pt2 the height of the bounding box, h. h = triangleHeight(pt1,pt2,pt3); pt1pt2_direction = atan2d(pt2(2)-pt1(2),pt2(1)-pt1(1)); w = feretDiameter(V,pt1pt2_direction); A_k = h*w; if (A_k < A) A = A_k; thetad = pt1pt2_direction; end end end % Rotate all the points so that pt1-pt2 for the minimum bounding box points % straight up. r = 90 - thetad; cr = cosd(r); sr = sind(r); R = [cr -sr; sr cr]; Vr = V * R'; xr = Vr(:,1); yr = Vr(:,2); xmin = min(xr); xmax = max(xr); ymin = min(yr); ymax = max(yr); bb = [ ... xmin ymin xmax ymin xmax ymax xmin ymax xmin ymin ]; % Rotate the bounding box points back. bb = bb * R; end function h = triangleHeight(P1,P2,P3) % Copyright 2017-2018 The MathWorks, Inc. h = 2 * abs(signedTriangleArea(P1,P2,P3)) / norm(P1 - P2); end function area = signedTriangleArea(A,B,C) % Copyright 2017-2018 The MathWorks, Inc. area = ( (B(1) - A(1)) * (C(2) - A(2)) - ... (B(2) - A(2)) * (C(1) - A(1)) ) / 2; end]]>

Jason Barnes had wanted to be a professional drummer since he was a teenager. At age 22, Barnes lost his... read more >>

]]>"The drummer essentially becomes a cyborg," stated Weinberg. "The second drumstick has a mind of its own. It's interesting to see him playing and improvising with part of his arm that he doesn't totally control."The wearable robot enables Barnes to create truly unique music. It uses artificial intelligence to detect the beat, tempo, and density in his drumming and responds with a beat that complements what it “hears”. It also autonomously listens to the chords played by the guitarist and adjusts its speed based on the chords. [caption id="attachment_1488" align="alignnone" width="385"] Professor Gil Weinberg (left) created a robotic prosthesis for Jason Barnes. Image credit: Georgia Tech.[/caption] With the device, Barnes can once again control the bounce of the drumstick.

“Now I can flex and send signals to a computer that tightens or loosens the stick and controls the rebound,” said Barnes.He can also drum at up to 20 hertz with each stick for a combined 40 beats per second. The prosthesis lets him drum at speeds that no human ever had. With the ability to reach 40 hertz, the sound has its own unique color, or timbre.

“I’ll bet a lot of metal drummers might be jealous of what I can do now," he continued. "Speed is good. Faster is always better.”

- Because of the music. With the new prosthesis, the team plans to record awesome music, and make a video, and perform in a one-of-a-kind, live concert.
- Because of the technology. The campaign will help the team to push the state-of-the-art in human augmentation leading to innovations that have the potential to improve the lives of many.
- Because of Jason. The Kickstarter campaign will allow Jason to overcome a potentially career-ending accident and become the performing musician he has always wanted to be.

MathWorks shipped our R2018a release last month. As usual (lately, at least), there are many new capabilities related to deep... read more >>

]]>In this post, I'll summarize the other new capabilities. I'll focus mostly on what's in the Neural Network Toolbox, with also some mention of the Image Processing Toolbox and the Parallel Computing Toolbox.

The doc example "Sequence-to-Sequence Regression Using Deep Learning" shows the estimation of engine's remaining useful life (RUL), formulated as a regression problem using an LSTM network. The new function

When you train a network, now you can select the Adams solver or the RMSProp solver. You can also introduce gradient clipping, which can help keep the training stable in the face of rapid increase in gradients.

Use the new plotconfusion function to show what's happening with your categorical classifications.

The rows correspond to the predicted class (Output Class) and the columns correspond to the true class (Target Class). The diagonal cells correspond to observations that are correctly classified. The off-diagonal cells correspond to incorrectly classified observations. Both the number of observations and the percentage of the total number of observations are shown in each cell.

The column on the far right of the plot shows the percentages of all the examples predicted to belong to each class that are correctly and incorrectly classified. These metrics are often called the precision (or positive predictive value) and false discovery rate, respectively. The row at the bottom of the plot shows the percentages of all the examples belonging to each class that are correctly and incorrectly classified. These metrics are often called the recall (or true positive rate) and false negative rate, respectively. The cell in the bottom right of the plot shows the overall accuracy.

The previous restriction on the number of channels in a convolutional neural network has been relaxed. That opens up the possibility of using deep learning with multispectral images. See the Image Processing Toolbox documentation example, "Semantic Segmentation of Multispectral Images Using Deep Learning."

It's easier now to replace a layer in a

When you are using transfer learning with a pretrained convolutional neural network, you can now try to accelerate the training process by freezing the weights in the initial network layers. The "Transfer Learning Using GoogLeNet" documentation example shows you how.

Neural networks are inherently parallel algorithms. You can take advantage of this parallelism by using Parallel Computing Toolbox to distribute training across multicore CPUs, graphical processing units (GPUs), and clusters of computers with multiple CPUs and GPUs.

Training deep networks is extremely computationally intensive and you can usually accelerate training by using a high performance GPU. If you do not have a suitable GPU, you can train on one or more CPU cores instead, or rent GPUs in the cloud. You can train a convolutional neural network on a single GPU or CPU, or on multiple GPUs or CPU cores, or in parallel on a cluster. Using GPU or any parallel option requires Parallel Computing Toolbox.

See "Scale Up Deep Learning in Parallel and in the Cloud."

There are many detailed documentation examples that illustrate the deep learning in various applications. Here are some of the new examples in R2018a:

- Deep Learning Speech Recognition (Audio System Toolbox)
- Train Residual Network on CIFAR-10
- Time Series Forecasting Using Deep Learning
- Sequence-to-Sequence Classification Using Deep Learning
- Sequence-to-Sequence Regression Using Deep Learning
- Classify Text Data Using Deep Learning (Text Analytics Toolbox)
- Semantic Segmentation of Multispectral Images Using Deep Learning (Image Processing Toolbox)
- Single Image Super-Resolution Using Deep Learning (Image Processing Toolbox)
- JPEG Image Deblocking Using Deep Learning (Image Processing Toolbox)
*(I once co-authored a paper on deblocking in JPEG images. That was about 25 years ago. Time flies!)* - Remove Noise from Color Image Using Pretrained Neural Network (Image Processing Toolbox)

Be sure to check out the Release Notes for other enhancements and changes that you might be interested in.

]]>Today is Friday, the 13th. In many parts of the world, today is regarded as unlucky. But I want to... read more >>

]]>Today is Friday, the 13th. In many parts of the world, today is regarded as *unlucky*. But I want to revisit an old question: is today *unlikely*? What are the chances that the 13th of any month falls on a Friday? Computing the answer makes use of a new MATLAB® feature, the `datetime` method.

I wrote about Friday the 13th in a blog post several years ago, Cleve's Corner, Friday the 13th. I am reusing a portion of that post today.

Leap years make our calendar a nontrivial mathematical object. The leap year rule can be implemented by this anonymous function.

leapyear = @(y) mod(y,4)==0 & mod(y,100)~=0 | mod(y,400)==0;

This says that leap years happen every four years, except for the turn of centuries not divisible by 400. Try a few year numbers.

y = [2018 2020 2000 2100]'; isleap = [y leapyear(y)]

isleap = 2018 0 2020 1 2000 1 2100 0

So, this year is not a leap year, the next one is in 2020. The turn of the century 2000 was a leap year, but 2100 will not be.

The leap year rule implies that our calendar has a period of 400 years. The calendar for years 2000 to 2399 will be reused for 2400 to 2799. In a 400 year period, there are 97 leap years, 4800 months, 20871 weeks, and 146097 days. So the average number of days in a calendar year is not 365.25, but

dpy = 365+97/400

dpy = 365.2425

We can compute the probability that the 13th of a month is a Friday by counting how many times that happens in 4800 months. The correct probability is then that count divided by 4800. Since 4800 is not a multiple of 7, the probability does not reduce to 1/7.

For many years, computations involving dates and time have been done using a whole bunch of functions.

`clock``datenum``datevec``datestr``dateticks``now``weekday`

Those functions have served us well, but they have some significant shortcomings. They are not particularly easy to use. The display formatting is limited. The floating point precision of `datenum` effectively limits the calculation of durations. There are no immediate plans to retire `datenum` and its friends, but something preferable is now available.

The `datetime` object, introduced in R2014b, combines and extends these functions into one.

`datetime`

The documentation for `datetime` is available online, or, from within MATLAB, with the command

doc datetime

For example, here is the date and time when I am publishing this post.

```
d = datetime('now')
```

d = datetime 13-Apr-2018 21:21:19

I can specify a custom display format with

d = datetime(d,'Format','eeee, MMMM d, yyyy HH:mm:ss')

d = datetime Friday, April 13, 2018 21:21:19

The available display formats include support for an international standard, ISO 8601.

`datetime`'s are much more precise than `datenum`'s can ever hope to be. Try this

hms = datetime(d,'Format','HH:mm:ss.SSS')

hms = datetime 21:21:19.502

We see that `d` is carrying fractional seconds to at least three places beyond the decimal point. How about nanoseconds?

secperday = 24*60*60 nano = 1.e-9/secperday hms = datetime(d,'Format','HH:mm:ss.SSSSSSSSS') hmsplusnano = hms + nano

secperday = 86400 nano = 1.1574e-14 hms = datetime 21:21:19.502000000 hmsplusnano = datetime 21:21:19.502000001

A nanosecond is four orders of magnitude smaller than roundoff error of `datenum`'s in this era. Compare

nano epsofdatenum = eps(datenum(d))

nano = 1.1574e-14 epsofdatenum = 1.1642e-10

I am pleased to reveal some details about the arithmetic in `datetime`. The object is using a form of quadruple precision known as double-double. In fact, the second half of the 112-bit format is stored as the imaginary part of the `data` field, as you see in the following.

disp(struct(hmsplusnano))

Warning: Calling STRUCT on an object prevents the object from hiding its implementation details and should thus be avoided. Use DISP or DISPLAY to see the visible public details of an object. See 'help struct' for more information. UTCZoneID: 'UTC' UTCLeapSecsZoneID: 'UTCLeapSeconds' ISO8601Format: 'uuuu-MM-dd'T'HH:mm:ss.SSS'Z'' epochDN: 719529 MonthsOfYear: [1×1 struct] DaysOfWeek: [1×1 struct] dateFields: [1×1 struct] noConstructorParamsSupplied: [1×1 struct] data: 1.5237e+12 + 1.0000e-06i fmt: 'HH:mm:ss.SSSSSSSSS' tz: '' isDateOnly: 0

The summary description in the `datetime` documentation describes some important features of the object, which has nearly 100 methods defined.

`datetime` arrays represent points in time using the proleptic
ISO calendar. `datetime` values have flexible display formats
up to nanosecond precision and can account for time zones,
daylight saving time, and leap seconds.

I had to look up the definition of "proleptic". In this context it means the calendar can be extended backwards in time to apply to dates even before it was adopted.

Let's get on with Friday the 13th. Like most things in MATLAB `datetime` works with vectors. The statements

y = 2000; m = 1:4800; t = 13; v = datetime(y,m,t);

produce a row vector of 4800 `datetime`'s for the 13th of every month. The first few and last few are

fprintf(' %s',v(1:4)) fprintf(' ...\n') fprintf(' %s',v(end-3:end))

13-Jan-2000 13-Feb-2000 13-Mar-2000 13-Apr-2000 ... 13-Sep-2399 13-Oct-2399 13-Nov-2399 13-Dec-2399

The statement

w = weekday(v);

produces a row vector of 4800 flints between 1 (for Sunday) and 7 (for Saturday). The first few and last few are

fprintf('%3d',w(1:4)) fprintf(' ...') fprintf('%3d',w(end-3:end))

5 1 2 5 ... 2 4 7 2

Now to get the counts of weekdays, all we need is

c = histcounts(w)

c = 687 685 685 687 684 688 684

There you have it. The count for Friday, 688, is higher than for any other day of the week. The 13th of any month is slightly more likely to fall on a Friday.

The probabilities are

p = c/4800

p = 0.1431 0.1427 0.1427 0.1431 0.1425 0.1433 0.1425

Compare these values with their mean, `1/7 = 0.1429`. Four probabilities are below the mean, three are above.

Let's pair the counts with the days of the week, using a `categorical` variable, introduced in R2013b.

c = categorical(w,1:7,{'Sun' 'Mon' 'Tue' 'Wed' 'Thu' 'Fri' 'Sat'}); summary(c)

Sun Mon Tue Wed Thu Fri Sat 687 685 685 687 684 688 684

When we plot a histogram the appropriate labels are provided on the x-axis. Friday the 13th is the winner.

histogram(c) set(gca,'ylim',[680 690]) title('Weekday counts, 400 years')

Thanks to Peter Perkins at MathWorks. I learned a lot from him while working on this post.

Get
the MATLAB code

Published with MATLAB® R2018a

I am excited to announce a number of new features that are available to all ThingSpeak users. We added the ability... read more >>

]]>Today I'd like to introduce a guest blogger, Stephen Doe, who works for the MATLAB Documentation team here at MathWorks.... read more >>

]]>Today I'd like to introduce a guest blogger, Stephen Doe, who works for the MATLAB Documentation team here at MathWorks. In today's post, Stephen discusses how, and why, you might want to update your code to accept string arrays as inputs.

In R2016b, MATLAB® introduced the `string` data type as a new data type for text. Each element of a string array stores a sequence of characters. You can use standard array indexing and operations on string arrays, along with string manipulation functions introduced in R2016b. Also, you can use many MATLAB functions (such as `sort` and `unique`) on string arrays.

Here's a short example. Start with some text you can store as one string--or as a string *scalar*, a term we use to describe a string array with one element. As of R2017a, you can use double-quotes to create a string. (Single-quotes still create a character vector.)

```
str = "A horse! a horse! My kingdom for a horse!"
```

str = "A horse! a horse! My kingdom for a horse!"

If you use the `split` function to split that string on space characters, then the result is a string array with nine elements. Instead of getting a cell array, you get a homogeneous array storing text--an array that has the same data type you started with. The `split` function returns the string array as a column vector. Let's reshape it as a row vector of strings for more compact display.

str = split(str); str = str'

str = 1×9 string array Columns 1 through 8 "A" "horse!" "a" "horse!" "My" "kingdom" "for" "a" Column 9 "horse!"

String arrays now provide a powerful way to deal with text in your data. As you work with your text in a string array, you never have to resort to cell arrays or curly brace indexing. I won't belabor the point, because Loren already has published some wonderful guest posts on using string arrays. If you are looking for more examples using strings, see: Introducing String Arrays, Singing the Praises of Strings, and Working with Text in MATLAB.

And of course, you can find the documentation for string arrays at Characters and Strings.

A few paragraphs ago, I said that "many" MATLAB functions now accept string arrays as inputs arguments. In fact, in a future release nearly all MathWorks® products will work with string arrays as inputs.

Here's what we mean when we say that a product "works with" string arrays as inputs:

- If an input argument can be a single piece of text, then you can specify it as a character vector
**or**as a string scalar. That is, you can use either single-quotes or double-quotes.

- If an input argument can contain multiple pieces of text, then you can specify it as a cell array of character vectors
**or**as a string array.

We're holding to this pattern in old functions where we are adding support for string arrays, and in new functions going forward. Consider the `split` function I used to split a string. It works just as well on character vectors or cell arrays of character vectors as it does on strings. (Note that functions which have always returned a character vector in previous releases, such as the `fileread` function, will continue to do so for compatibility.)

We think this approach is the most seamless way to support use of string arrays throughout our products. Our advice is to take the same approach in your own code. If you maintain code of your own, or write code for other MATLAB users, then it is to your advantage to update your code to accept string arrays as inputs, while maintaining support for the older types for storing text.

Right now, you are thinking, "Great! But how do I do that?" (Well, perhaps "great" is not the exact word that came to mind.)

To help you update your code, the R2018a documentation provides guidelines to Update Your Code to Accept Strings. You can apply these guidelines to your code now. The guidelines, and our documentation, also provide links to helper functions, such as `convertStringsToChars`, that smooth the way to accepting strings in your code.

Here is a short example that shows two ways to put these guidelines into action. I'll start with a fast and simple way that uses one of our helper functions. Then I'll follow with another way that is a little more time consuming, but is also a little more forward-looking.

Suppose this code is your original function to abbreviate the name of a city using its first three letters, making those letters uppercase. Up to now, you have specified a city's name as a character vector. For example, if the input argument is `'Boston'`, then the output argument is `'BOS'`.

function abr = abbreviateName(str) abr = upper(str(1:3)); end

If your user instead specifies the **string** `"Boston"` as the input argument, then there will be a syntax error. For a string array, the syntax `str(1:3)` means, return the first, second, and third strings as a three-element string array. But `"Boston"` all by itself is a 1-by-1 string array!

One way to support both character vectors and strings is to use the helper function `convertStringsToChars` at the beginning of the original code. `convertStringsToChars` processes an arbitrary number of input arguments and, if any of them are strings, converts them. It leaves all other data types alone.

function abr = abbreviateName(str) str = convertStringsToChars(str); abr = upper(str(1:3)); end

With the helper function, you can accept input string arrays without altering any of the code that follows. Also, the output argument type does not differ from the type returned by the original code.

A second way is to use one of the new functions for text manipulation, such as `extractBefore`. These new functions also work with character vectors and cell arrays of character vectors. And so, this new version of `abbreviateName` works the same way for inputs of any text data type.

function abr = abbreviateName(str) abr = extractBefore(str,4); abr = upper(abr); end

While this code supports both strings and character vectors, I did have to rewrite the code. Also, this code returns a string if the input is a string. The original code always returned a character vector.

Which way is the right way for you? Well, that is the "choose your own adventure" part. If you are doing a lot of work with text, then it might be time for you to do a deep dive into your code and rewrite its internals to use string arrays. If not, then use `convertStringsToChars` and minimize the pain of updating your code. On either path, look for help in our guidelines.

And if you have things to say about string arrays, or your efforts to update your own code, then let us know here.

Get
the MATLAB code

Published with MATLAB® R2018a

In this blog post, Sebastian Castro will talk about robot manipulation with MATLAB and Simulink. This part will discuss... read more >>

]]>**Kinematics**is the analysis of motion without considering forces. Here, we only need geometric properties such as lengths and degrees of freedom of the manipulator bodies.**Dynamics**is the analysis of motion caused by forces. In addition to geometry, we now require parameters like mass and inertia to calculate the acceleration of bodies.

**Analytic solutions**mean that you can derive, in closed-form, an expression for the joint positions given the desired end effector position. This is beneficial because you do all the work offline and solving IK will be fast. As with everything in engineering: if you have an exact model of your system, you should take advantage of it!**Numerical solutions**are generally slower and less predictable than analytic solutions, but they can solve harder problems than analytic solutions (we expand on this below). However, these solutions introduce uncertainty in the form of initial conditions, optimization algorithm choice, or even random chance. So, you may not get the answer you want.

- Your manipulator has redundant degrees of freedom (always the case with 7 or more)
- You don’t want to derive the math and have the computational resources for a numeric solution
- Your target position is not valid, but you still want to get as close to it as possible
- There are multiple, or even infinite, analytic solutions
- You want to introduce multiple, complex constraints

*Cases where there are multiple solutions, which are relatively easy to handle with analytical IK.
(Left) IK has exactly two solutions – “over” or “under”.
(Right) IK has infinite solutions since any rotation of the base is valid.*

*Complex manipulation cases which are likely candidates for numerical solution.
(Left) 7-DOF manipulator can position the end effector with multiple valid solutions.
(Right) Example of position constraints between two coordinate frames on the manipulator. *

**How:**Create a rigid body tree object**When to use:**Solving forward and inverse kinematics and dynamics, extracting mechanical properties (Jacobian, mass matrix, gravity torques, etc.)

**How:**Create a Simscape Multibody model**When to use:**System-level dynamic simulation, integration with physical models of actuators, contact mechanics, etc.

**Inverse Kinematics****:**Enforces joint limits and lets you supply relative weights for each position and orientation target.**Generalized Inverse Kinematics****:**Allows you to add multiple, and more complex, constraints such as relative position between coordinate frames, aiming at certain objects, or time-varying joint limits.

sawyer = importrobot('sawyer.urdf', 'MeshPath', ... fullfile(fileparts(which('sawyer.urdf')),'..','meshes','sawyer_pv')); gik = robotics.GeneralizedInverseKinematics('RigidBodyTree',sawyer, ... 'ConstraintInputs',{'position','aiming'}); % Target Position constraint targetPos = [0.5, 0.5, 0]; handPosTgt = robotics.PositionTarget('right_hand','TargetPosition',targetPos); % Target Aiming constraint targetPoint = [1, 0, -0.5]; handAimTgt = robotics.AimingConstraint('right_hand','TargetPoint',targetPoint); % Solve Generalized IK [gikSoln,solnInfo] = gik(sawyer.homeConfiguration,handPosTgt,handAimTgt) show(sawyer,gikSoln);

*What other constraints can you think of to make the motion smoother?*

- Integrating IK with a simulation of the robot dynamics
- Adding other algorithms, such as supervisory logic, perception, and path planning
- Automatically generating standalone C/C++ code from your algorithms and deploying to hardware or middleware such as ROS

Here I continue with my analysis of the log files of a different server. I need to modify my... read more >>

]]>Let me tell you about a beautiful, fractal curve, the Dragon Curve. Download my new dragon program from the File... read more >>

]]>Let me tell you about a beautiful, fractal curve, the Dragon Curve. Download my new `dragon` program from the File Exchange and follow along.

Start with a long, narrow strip of paper, like the one in the following photograph. Fold it in half once, end over end. Then fold it a second time, being careful to fold in the same direction, right over left or left over right, as the first. Then a third fold, and a fourth. Unfold the strip so that all the folds form the right angles pictured. You will have created a Dragon Curve of degree four.

Image credit: http://www.cutoutfoldup.com/216-dragon-curve.php

How many times do you imagine you could fold the paper before it is too thick to fold again? Probably five, maybe six.

The degree one curve has one right angle; let's denote that by R. The degree two curve has two right angles, followed by a left; that's RRL. The degree three signature is RRLRRLL.

Can you read off the signature of degree four from the photo? Do you see the pattern? Probably not yet.

The number of segments between folds doubles with each increase in degree. Here's code to display the signatures of degrees one through six. That's all I can display in one column of this blog post.

The key operation in the code is `LR-fliplr(s)`. That flips the string `s` end to end and replaces all the R's by L's and the L's by R's.

s = 'R'; disp(s) LR = 'L'+'R'; for n = 2:6 s = [s 'R' LR-fliplr(s)]; disp(s) end

R RRL RRLRRLL RRLRRLLRRRLLRLL RRLRRLLRRRLLRLLRRRLRRLLLRRLLRLL RRLRRLLRRRLLRLLRRRLRRLLLRRLLRLLRRRLRRLLRRRLLRLLLRRLRRLLLRRLLRLL

The following figures are all from my new MATLAB program, `dragon`. The computations are based on a growing and shrinking vector `z` of points in the complex plane.

Start with

z = [0 1]

This isn't complex yet, but it soon will be. When we plot `z`, we get a single black line, representing an unfolded strip of paper.

Let's fold the paper once. This is done with the help of the complex number

w = (1+i)/2

In polar form, $w$ is $e^{i \pi/4}/\sqrt{2}$. So complex multiplication by $w$ rotates by $45^\circ$ and scales by $1/\sqrt{2}$.

In MATLAB, `w'` is the complex conjugate of `w`. This is used in the "fold" operation for any vector `z`.

zleft = w*z zright = 1 - w'*fliplr(z) z = [zleft zright]

Folding turns `[0 1]` into

[0 w w 1]

When we plot any vector, we break it in half, then plot the left half in black and the right half in blue.

The black line has been rotated $45^\circ$ to the left and a blue line, rotated $45^\circ$ to the right, appended.

Fold it again.

The black line becomes a black right angle and the blue line becomes a blue "left angle".

Two more folds produce a degree four Dragon Curve.

A total of eight folds gives degree eight.

And after a total of eighteen folds, we have our dragon.

We could keep on folding, but we now have $2^{18}$ short line segments and have reached the limits of screen resolution. More folds do not change any more pixels.

Let's do a different kind of rotation. Rotate the entire dragon by $90^\circ$, superimpose it on the original, and plot the four halves with four colors.

Do it twice more.

We could now do translations in all four compass directions and superimpose all the dragons, but I won't show that. It turns out that as both the degrees and the translates go to infinity, the curves, which are intricately intertwined, never intersect, and completely cover and tile the complex plane.

I found this at an on-line shopping center named Etsy, in the "Fractal and Geeky Jewelry" section. It's from an outfit named DragonNerd in Winnipeg. Count the number of bends to determine the degree.

The last time I blogged about jewelry was in my piece about the Pentium Affair.

Image credit: http://www.etsy.com/shop/DragonNerd

All the figures above are from my new program, `dragon`, available from MATLAB Central and also included in Cleve's Laboratory.

`dragon` provides four pushbuttons

These buttons

- Unwind the rotations
- Reduce the degree
- Increase the degree
- Superimpose rotations

The Web is full of stuff about the Dragon Curve. Just ask Google and Wikipedia.

I highly recommend two videos from Numberphile. In one, Don Knuth tells about a wrong turn he made in the Dragon Curve ceramic displayed in his home, https://www.youtube.com/watch?v=v678Em6qyzk.

In the other, the popular British author, Rob Eastaway, describes the appearance of the Curve in Michael Crichton's *Jurassic Park*, https://www.youtube.com/watch?v=wCyC-K_PnRY.

Get
the MATLAB code

Published with MATLAB® R2018a

Sean's pick this week is Simulink Pacing by MathWorks' Simulink Development... read more >>

]]>Sean's pick this week is Simulink Pacing by MathWorks' Simulink Development team.

Last summer, I highlighted the Simulink Pacer block as a means to slow a simulation down to a desired speed so you can see what's happening. Yesterday, one my colleagues was demonstrating a customized prototype that streams data directly from Simulink to a cloud IoT platform. He elegantly used the new simulation pacing capabilities to slow the simulation so you could see the simulation in Simulink and the IoT dashboard updating at the same time.

Here's the same model from last time. To enable simulation pacing in Simulink, select the "Simulation" drop down and then "Pacing Options".

The new simulation pacing options allow me to drag the slider to adjust the speed as necessary.

Give R2018a a try and let us know what you think here.

Get
the MATLAB code

Published with MATLAB® R2018a

Living organisms have long provided inspiration for technology. Biomimicry of birds helped us design our first aircraft, while the structure... read more >>

]]>“The moth olfactory network is among the simplest biological neural systems that can learn,” the researchers, Charles B. Delahunt, Jeffrey Riffell, and J. Nathan Kutz, stated in their paper, Biological Mechanisms for Learning: A Computational Model of Olfactory Learning in the Manduca sexta Moth, with Applications to Neural Nets.The

- First, it learned quickly by filtering information at each step and only passing along the most critical information to the next phase is the system. While the first of the five distinct networks starts with nearly 30,000 receptors in the antenna, the second network is comprised of 4,000 cells. By the time the information reaches the last network in the system, the neurons number in the 10s.
- Second, the filtering process had the added benefit of removing noise from the signals. The sparse layer between the first two networks acts as an effective noise filter, protecting the downstream neurons from the noisy signal received by the "antennas".
- Lastly, the brain “rewarded” successfully identifying odors with a release of a chemical neurotransmitter called Octopamine, reinforcing the successful connections in the neural wiring. The active connections strengthen for an assigned digit, the rest wither away.

“The results demonstrate that even very simple biological architectures hold novel and effective algorithmic tools applicable to [machine learning] tasks, in particular, tasks constrained by few training samples or the need to add new classes without full retraining,” the researchers stated in the paper.All coding was done in MATLAB. The code for this paper can be found here. ]]>

I want to carryout the analysis I did in my previous post on another server. However, that server has a... read more >>

]]>Today is Easter Sunday. Why? How is the date of Easter determined? This is a revision of a blog... read more >>

]]>Today is Easter Sunday. Why? How is the date of Easter determined?

This is a revision of a blog post from 2013.

Easter Day is one of the most important events in the Christian calendar. It is also one of the most mathematically elusive. In fact, regularization of the observance of Easter was one of the primary motivations for calendar reform centuries ago.

Easter is linked to the Jewish Passover. The informal rule is that Easter Day is the first Sunday after the first full moon after the vernal equinox. But the ecclesiastical full moon and equinox involved in this rule are not always the same as the corresponding astronomical events, which, after all, depend upon the location of the observer on the earth.

I am using a revision of the `easter` program in my blog post from 2013 and *Experiments with MATLAB*. Let's check this year.

easter_2018 = datestr(easter(2018))

easter_2018 = '01-Apr-2018'

My MATLAB® program is based on the algorithm presented in the first volume of the classic series by Donald Knuth, The Art of Computer Programming. Knuth has used it in several publications to illustrate different programming languages. The task has often been the topic of an exercise in computer programming courses.

Knuth says that the algorithm is due to the Neapolitan astronomer Aloysius Lilius and the German Jesuit mathematician Christopher Clavious in the late 16th century and that it is used by most Western churches to determine the date of Easter Sunday for any year after 1582.

The date varies between March 22 and April 25.

The earth's orbit around the sun and the moon's orbit around the earth are not in sync. It takes the earth about 365.2425 days to orbit the sun. This is known as a tropical year. The moon's orbit around the earth is complicated, but an average orbit takes about 29.53 days. This is known as a synodic month. The fraction

```
year = 365.2425;
month = 29.53;
format rat
ratio = year/month
```

ratio = 6444/521

is not the ratio of small integers. However, in the 5th century BC, an astronomer from Athens named Meton observed that the ratio is very close to 235/19.

```
format short
ratio
meton = 235/19
```

ratio = 12.3685 meton = 12.3684

In other words, 19 tropical years is close to 235 synodic months. This Metonic cycle was the basis for the Greek calendar and is the key to the algorithm for determining Easter.

Here is the revised MATLAB program. Try other years.

Can you spot the change made to my old program in the blog post from 2013?

```
type easter
```

function dn = easter(y) % EASTER Date of Easter. % EASTER(y) is the datenum of Easter in year y. % Example: % datestr(easter(2020)) % % Ref: Donald Knuth, The Art of Computer Programming, % Fundamental Algorithms, pp. 155-156. % Copyright 2014-18 Cleve Moler % Copyright 2014-18 The MathWorks, Inc. % Golden number in 19-year Metonic cycle. g = mod(y,19) + 1; % Century number. c = floor(y/100) + 1; % Corrections for leap years and moon's orbit. x = floor(3*c/4) - 12; z = floor((8*c+5)/25) - 5; % Epact. e = mod(11*g+20+z-x,30); if (e==25 && g>11 || e==24), e = e + 1; end % Full moon. n = 44 - e; if n < 21, n = n + 30; end % Find a Sunday. d = floor(5*y/4) - x - 10; % Easter is a Sunday in March or April. d = n + 7 - mod(d+n,7); dn = datenum(y,3,32);

[1] Donald E. Knuth, The Art of Computer Programming, Volume 1: Fundamental Algorithms (3rd edition), pp. 159-160, Addison-Wesley, 1997, ISBN 0-201-89683-4, PDF available.

[2] Wikipedia, Primary article on Easter. <http://en.wikipedia.org/wiki/Easter>

[3] Wikipedia, Computus, details on calculation of Easter. <http://en.wikipedia.org/wiki/Computus>

[4] Wikipedia, Metonic cycle. <http://en.wikipedia.org/wiki/Metonic_cycle>

Get
the MATLAB code

Published with MATLAB® R2018a

As most of you know I love building IoT projects. Most of these maker projects use an Arduino, Particle, or... read more >>

]]>% create an Arduino object a = arduino('com3', 'uno');

% turn on an LED connected to Pin D11 writeDigitalPin(a, 'D11', 1);

% turn off an LED connected to Pin D11 writeDigitalPin(a, 'D11', 0);

Jiro's pick this week is GUIDE to App Designer Migration Tool (for R2018a) by MathWorks App Designer Team.The App Designer... read more >>

]]>Jiro's pick this week is GUIDE to App Designer Migration Tool (for R2018a) by MathWorks App Designer Team.

The App Designer was initially introduced in R2016a, and since then we've been adding new, shiny components to it every release. It is now our recommended tool for anyone who wants to build an interactive app. As of R2018a, you can now easily deploy your apps built with App Designer to the web, with the MATLAB Compiler.

Many of you may have used GUIDE to build interactive apps in MATLAB before R2016a. Now that App Designer provides most of the features that GUIDE provides, plus many more newer components, you may be interested in porting your old GUIDE apps to App Designer apps. But laying out the components and rewriting callback functions can be tedious.

That's where this "GUIDE to App Designer Migration Tool" comes to the rescue. It will help with the migration process and will also give you a report to assist you with additional modifications and inform you of any incompatibilities.

I gave it a try with a GUIDE app I had from a long time ago.

**GUIDE Version**

**App Designer Version**

Now, I did need to do some modifications, such as create new properties for data management and change some of the plotting syntax. Many of these modifications were explained in the report that it created.

**Comments**

Give it a try and let us know what you think here or leave a comment for MathWorks App Designer Team.

Get
the MATLAB code

Published with MATLAB® R2018a

We have a treat today: a guest visit from MATLAB user and controls researcher Jiří Zemánek. Jiří is a doctoral student at... read more >>

]]>phi = (sqrt(5)+1)/2; golden_angle = 2*pi/phi; max_angle = 1000; theta = 1:golden_angle:max_angle; r = sqrt(theta); [x,y] = pol2cart(theta,r); plot(x,y,'.')Phyllotaxis patterns are ideal for zoetropic animation. I took this pattern and animated it. The result gives you a visceral sense of how the seeds come into existence at the center of the flower and slowly radiate outward. Amazingly, there are only 11 frames in this animation. My version is not on an egg, but it could be. The idea is the same. Maybe Jiří can do a seed-packing egg animation one of these days. So if you celebrate Easter, then Happy Easter! If you don't, then Happy Check-Out-These-Amazing-Zoetropic-Eggs! https://www.youtube.com/watch?v=rIgpqlrj-G0]]>