Particle Kinematics in Cylindrical Coordinates

I recently had two different students ask me two different, but related questions. One had asked about the derivation of the equations he used in his dynamics I class for acceleration when using cylindrical coordinates, and another had asked me about Coriolis acceleration. Fortunately, both can be explained with the exact same answer, so let’s answer them both with the minimum amount of work required!

Let’s start with a little drawing illustrating what we’re dealing with here:

Cylindrical Coordinate System Diagram

Cool! We are dealing with a coordinate system characterized by a radial distance, R, azimuth, \theta, and axial distance, z. As we can see from the above diagram we have a right handed coordinate system defined by the unit vectors

1) \displaystyle \qquad\bar{e_{R}} \; \times \; \bar{e_{\theta}} = \bar{e_{z}}

From the above diagram we can relate these cylindrical coordinate system unit vectors back to traditional Cartesian coordinate system unit vectors with the following relationships.

2) \displaystyle \qquad \bar{e_{R}} = ( \cos \theta) \hat{i} + ( \sin \theta ) \hat{j}

3) \displaystyle \qquad \bar{e_{\theta}} = -( \sin \theta ) \hat{i} + ( \cos \theta ) \hat{j}

4)\displaystyle \qquad \bar{e_{z}} = \hat{k}

Now, let’s write the equation for our position vector, r.

5) \displaystyle \qquad \bar{r} = R \bar{e_{R}} + z \bar{e_{z}}

Note, in equation 5, from equation 3, the radial unit vector, \bar{e_{R}} implicitly depends on \theta, and theta may depend on time.

Velocity Derivation

If we wish to obtain the generic form of velocity in cylindrical coordinates all we must do is differentiate equation 5 with respect to time, but remember that the radial unit vector must be treated as a variable since it implicitly depends on \theta. This dictates that we must use the chain rule to differentiate the first term of equation 5.

6) \displaystyle \qquad \bar{v} = \dot{\bar{r}} = \dot{R} \bar{e_{R}} + R \frac{d \bar{e_{R}}}{dt} + \dot{z} \bar{e_{z}}

Now, to differentiate the radial unit vector with respect to time we must employ the chain rule.

7) \displaystyle \qquad \frac{d \bar{e_{R}}}{dt} = \frac{d \bar{e_{R}}}{d \theta} \; \frac{d \theta}{dt} = \frac{d \bar{e_{R}}}{d \theta} \cdot \dot{\theta} = \dot{ \theta} \bar{e_{\theta}}

Woah, woah, woah, how the hell did I do that last part and change unit vectors you may ask. Well, let’s differentiate equation 2 with respect to \theta.

8) \displaystyle \qquad \frac{d \bar{e_{R}}}{d \theta} = -(\sin \theta) \hat{i} + (\cos \theta) \hat{j} = \bar{e_{ \theta}}

That works out nicely, and it also informs us that the second velocity term below is the result of the radial unit vector changing as a function of time.

So, condensing everything from equations 6, 7, and 8 we obtain the general equation for velocity in cylindrical coordinates.

9) \displaystyle \qquad \bar{v} = \dot{R} \bar{e_{R}} + R \dot{\theta} \bar{e_{ \theta}} + \dot{z} \bar{e_{z}}

Let’s revisit the differentiation performed for the radial unit vector with respect to \theta, and do the same thing for the azimuth unit vector.

10) \displaystyle \qquad \frac{d \bar{e_{ \theta}}}{dt} = \frac{d \bar{e_{ \theta}}}{d \theta}\; \frac{d \theta}{dt} = \frac{d \bar{e_{ \theta}}}{d \theta}\; \dot{ \theta}= -\dot{ \theta} \bar{e_{R}}

11) \displaystyle \qquad \frac{d \bar{e_{\theta}}}{d_{ \theta}} = -(\cos \theta) \hat{i} - (\sin \theta) \hat{j} = - \bar{e_{R}}

Let’s look at equation 9 for a moment and discuss the contributions from the terms. The first and last are easy to understand; the second basically says that the azimuthal velocity results from changing the azimuth angle, with the magnitude growing in proportion to the radial distance.

Acceleration Derivation

Now, this is where things start to make us look smarter than we actually are because of all the cool symbols we get to use. Moving on to acceleration, we obviously just continue differentiating!

12a) \displaystyle \qquad \bar{a} = \frac{d}{dt} [ \dot{R} \bar{e_{R}}] + \frac{d}{dt} [ R \dot{ \theta} \bar{e_{\theta}} ] + \frac{d}{dt} [ \dot{z} \bar{e_{z}}]

Using the relations in 7, 8, 10, and 11 we end up with

12b) \displaystyle \qquad \bar{a}= \ddot{R} \bar{e_{R}} + \dot{R} \dot{ \theta} \bar{e_{ \theta}} + \dot{R} \dot{ \theta} \bar{e_{ \theta}} + R \ddot{ \theta} \bar{e_{ \theta}} - R \dot{ \theta}^2 \bar{e_{R}} + \ddot{z} \bar{e_{z}}

Collecting like terms we finally obtain the general equation for acceleration in cylindrical coordinates.

13) \displaystyle \qquad \bar{a} = ( \ddot{R} - R \dot{ \theta}^2) \bar{e_{R}} + (R \ddot{ \theta} + 2 \dot{R} \dot{ \theta}) \bar{e_{ \theta}} + \ddot{z} \bar{e_{z}}

The Coriolis acceleration is then the sum of the second and third quantities in equation 12b). I left this intermediate step in there to show that, although the second and third terms are the same quantity, they originate from different effects. The second term is the result of the radial direction not being constant, as evidenced by equation 7, whereas the third term is the rate at which the azimuthal velocity, R \dot{ \theta}, will change if R is non-constant.

Cylindrical Coordinate System Kinetics

To further elucidate the Coriolis acceleration, and in turn the Coriolis force or much more buzz worthy Coriolis Effect, let’s take a look at the scalar form of Newton’s second law in each principal direction.

14a) \displaystyle \qquad \sum F_{R} \equiv \sum \bar{F} \cdot \bar{e_{R}} = m ( \ddot{R} - R \dot{ \theta}^2)

14b) \displaystyle \qquad \sum F_{\theta} \equiv \sum \bar{F} \cdot \bar{e_{\theta}} = m ( R \ddot{\theta} + 2 \dot{R} \dot{ \theta})

14c) \displaystyle \qquad \sum F_{z} \equiv \sum \bar{F} \cdot \bar{e_{z}} = m \ddot{z}

It is worth mentioning here that the famous centrifugal force appears in equation 14a as the negative quantity, and the much less famous Euler force appears as the first term in equation 14b.

So what can we say about Coriolis acceleration from equation 14b? Well, as explained previously, it is the result of 1) the radial direction being non-constant, as is the case of a rotating coordinate system (like, say, the Earth), and 2) the magnitude of the position vector changing in that rotating coordinate frame. Equation 14b indicates that this results in a force acting perpendicular to the radial direction. The force resulting from this acceleration term contributes to many of Earth’s largest atmospheric circulation systems such as trade winds and hurricanes.

Another way to describe the Coriolis acceleration without the use of vector calculus is to say that at a given rate of rotation of an observer, the magnitude of this acceleration on an object is proportional to the velocity of the object as well as the sine of the angle between the direction of travel of the object and the axis of rotation.

In a different coordinate system this may be easier to see, as we end up with the equation

15) \displaystyle \qquad \bar{a_{c}} = 2 \bar{v} \times \bar{\omega}

where \bar{a_{c}} is the Coriolis acceleration vector, \bar{v} is the velocity vector of the particle in the rotating coordinate system, and \bar{\omega} is the angular velocity vector of the rotating coordinate system.

\blacksquare

Non-imaging Optical Design: Vaned Baffle

In a previous role I had a coworker who would always joke that I was the “Special Projects Engineer”. This was one of those special projects.

An engineer had just left, and in addition to my controls and acoustics duties, due to previous navigation and computer vision projects, had taken over the role of creating a non-imaging optic that needed to have a very precise projection geometry. We were working with an optics contractor, and he was very good, but many of the designs that he proposed were outside of our budgetary constraints. Ultimately, we proceeded using an approach that I came up with by inverting a cold shield design for telescope optics.

Vaned Optical Baffle

Now, I’m not going to say exactly what this was used for, but I believe the design process is worth documenting for other’s use. In the above image, the square near the top-middle of the CAD drawing is a light source, whose projection geometry is dictated by the narrowest lines at the outlet of the baffle. This type of vaned baffled is designed to not allow anything under a fourth order reflection to escape the aperture. The design process is basically an inversion of that proposed in section 9.2.1 of Stray Light Analysis and Control, E. Fest, where the author constructs an algorithm to create a cold shield to restrict the field of view of an imager to prevent blinding from stray ambient light.

This approach allowed the baffle to be molded, and an SPI A-1 surface finish was dictated to try to ensure all reflections within the baffle were specular, and not diffuse.

Permanent Magnet Encoder Disc Magnetic Field Strength Analysis

OK. This one was SUPER annoying to debug, but basically what was happening is the controls for some D.O.F.s of a previous product looked really bad, almost like we were missing encoder ticks. Looking at the position control loop, it certainly looked like we were missing ticks, but where did they go?

Since we were using ROS for trajectory generation I basically worked my way from that level down, figuring that computational burden was just causing us to not be able to keep up with things in real time. After working ALL THE WAY THROUGH the software side and concluding everything looked fine, I had to turn to the motors and encoders themselves. Now, unbeknownst to me, we had just changed the model of the magnetic disc we were using as an encoder (paired with a hall effect sensor). With almost everything else tested, I resolved to test the magnetic (B) field strength of the magnetic discs.

Experimental Setup

Magnetic field strength of the permanent magnet encoder discs were characterized as a function of angular position using a quadrature encoder and digital Gaussmeter. Discs were mounted via very small 3D printed couplers to a Koyo TRD-MX1024BD quadrature encoder to measure angular position, while B field strength was measured with an F.W. Bell 5180 Gauss meter. The disc was then rotated by hand while the Gauss meter probe was fixtured so that it was in contact with the disc surface. Data was collected with a Saleae pro 16 logic analyzer. The encoder was powered with 12 v from a benchtop power supply, and outputs of the A, B, and Z channels were pulled up to 5v via a 1.5k ohm pullup resistor.

After data collection, data sets were analyzed by python scripts that extracted one full revolution of B-field strength and angular position, matched the angular position in 0.1 degree intervals using a binary search tree, filtered the data, extracted local extrema, and carried out statistical analysis on the identified positive and negative magnetic poles. The test apparatus is shown below, without the rigid fixture between encoder and Gauss meter. Data collect showing A, B, Z channels of the encoder and B field strength from the Gauss meter are shown on the screen.

Output Plots and Analysis

Let’s begin by looking at some of the magnetic discs that we used in the past that have not given us any trouble.

Good Magnetic Disc

POSITIVE POLES:
Angular differences between positive magnetic poles (degrees): 
[ 29.1796875   29.35546875  30.9375      31.81640625  30.76171875
 30.5859375   29.53125     31.81640625  31.55273438  26.015625
 27.59765625]

Magnitude differences between positive magnetic poles (Gauss): 
[ -31.06543128  -37.91607879   48.9585365   -13.01091485   55.52667332
 -25.77534475  139.50712186 -107.25554613    1.97638668   73.26621106
 -42.15276701]

Magnitudes of positive magnetic poles (Gauss): 
[ 803.04389588  771.97846459  734.0623858   783.0209223   770.01000745
 825.53668077  799.76133602  939.26845788  832.01291175  833.98929843
 907.2555095   865.10274249]

Standard deviation of difference in angular position of positive magnetic poles (degrees): 1.75035138526

Standard deviation of difference in positive magnetic field strength (Gauss): 65.0042394818

Standard deviation of positive pole magnetic field strength (Gauss): 56.6024562212

Mean magnetic field strength of positive poles (Gauss): 822.086884405

Mean angular displacement between positive magnetic poles (degrees): 29.9227627841


NEGATIVE POLES:
Angular differences between negative magnetic poles (degrees): 
[ 29.70703125  30.05859375  31.20117188  31.55273438  30.76171875
 29.8828125   30.14648438  30.84960938  30.76171875  26.3671875
 27.24609375]

Magnitude differences between negative magnetic poles (Gauss): 
[ 56.61348071 -26.47935011 -17.37341869 -51.85460574  46.539964
 -1.21482977 -78.56630343  45.94343868 -91.39098625  40.87246128
 18.49249138]

Magnitudes of negative magnetic poles (Gauss): 
[-808.25615348 -751.64267277 -778.12202288 -795.49544157 -847.35004731
-800.81008331 -802.02491308 -880.59121651 -834.64777783 -926.03876408
-885.1663028  -866.67381142]

Standard deviation of difference in angular position of negative magnetic poles (degrees): 1.55056517428

Standard deviation of difference in negative magnetic field strength (Gauss): 49.9112757447

Standard deviation of negative pole magnetic field strength (Gauss): 48.8189412974

Mean magnetic field strength of negative poles (Gauss): -831.401600587

Mean angular displacement between negative magnetic poles (degrees): 29.8668323864T

Bad Magnetic Disc

And now, let’s take a look at a representative “bad” magnetic disc.

Woah, it looks like there’s a big difference in B-field strength here…

POSITIVE POLES:
Angular differences between positive magnetic poles (degrees): 
[ 22.41210938  23.37890625  23.203125    22.32421875  22.06054688
 24.08203125  21.62109375  23.37890625  21.88476562  22.93945312
 25.6640625   18.80859375  22.93945312  22.8515625   21.62109375]

Magnitude differences between positive magnetic poles (Gauss): 
[ -47.8981468   -29.24181437  -56.77963869 -104.24687756   16.93935508
 -48.46134758  -28.67192289   81.30195449   22.73229587   80.86085334
  69.16778126   -1.74263368   87.44192205   -1.72612453    5.0340433 ]

Magnitudes of positive magnetic poles (Gauss): 
[ 480.6194911   432.7213443   403.47952994  346.69989124  242.45301368
 259.39236876  210.93102118  182.25909829  263.56105278  286.29334864
 367.15420199  436.32198325  434.57934957  522.02127162  520.29514709
 525.32919039]

Standard deviation of difference in angular position of positive magnetic poles (degrees): 1.42966348597

Standard deviation of difference in positive magnetic field strength (Gauss): 55.7923451036

Standard deviation of positive pole magnetic field strength (Gauss): 112.811684507

Mean magnetic field strength of positive poles (Gauss): 369.631956489

Mean angular displacement between positive magnetic poles (degrees): 22.611328125


NEGATIVE POLES:
Angular differences between negative magnetic poles (degrees): 
[ 23.203125    23.11523438  23.29101562  22.93945312  21.4453125
 23.5546875   23.02734375  22.58789062  22.06054688  22.32421875
 23.11523438  23.29101562  21.26953125  20.7421875   24.43359375]

Magnitude differences between negative magnetic poles (Gauss): 
[ -31.87032808   61.11857653   16.26178864  122.02554834    2.7446541
  80.43354251  -28.80379618   72.50021235  -75.90017174  -51.9568724
 -61.59044252  -43.34832509  -25.8054608   -36.74159058  -54.81136214]

Magnitudes of negative magnetic poles (Gauss): 
[-521.8299272  -553.70025528 -492.58167875 -476.31989011 -354.29434177
-351.54968767 -271.11614517 -299.91994134 -227.41972899 -303.31990073
-355.27677313 -416.86721565 -460.21554074 -486.02100154 -522.76259212
-577.57395426]

Standard deviation of difference in angular position of negative magnetic poles (degrees): 0.938524830477

Standard deviation of difference in negative magnetic field strength (Gauss): 58.5461130337

Standard deviation of negative pole magnetic field strength (Gauss): 105.59001526

Mean magnetic field strength of negative poles (Gauss): -416.923035904

Mean angular displacement between negative magnetic poles (degrees): 22.693359375

Indeed, upon further verification we were missing that low B-field magnitude tick.

Conclusions

After repeating the tests on 15 magnetic wheels from each class, it was determined that all of the new, supposedly better, magnetic wheels were causing us to miss ticks due to their very non-uniform B-field strength.

The amount of time that it took to debug this was a VERY annoying setback for the control systems, one that I have not had to deal with before. With this discovery there was quite a bit of back and forth with the vendor, to say the least. Ultimately, due to timeline compression, we had to proceed using the same vendor, but used the “old” discs as they appeared to have better quality control.

A System Dynamics Approach to Testing Microphone Functionality and Gasket Seals

Background and Motivation

This one hearkens back to some time ago when I was tasked with creating a test methodology for validating 1) microphones were operating correctly in our product, and 2) the seal created with a MEMS microphone, acoustic gasket, hydrophobic mesh, and outer casing. The gasket was to be die cut from Poron Polyurethane gasketing material with dimensions and physical properties dictated by me, and the hydrophobic mesh / acoustic impedence was to be dictated by me, ultimately being a variant of Saatifil Acoustex whose impedance best damped any spikes in the measured frequency response we were seeing.

I will have to make a separate post about this, but one thing the acoustic designer will have to put some thought into, besides damping resonances created by the acoustic pathway, are the creation of a Helmholtz resonator due to the necessity of having a sound inlet, often modeled as a tube, and a resonating cavity. Think of blowing perpendicularly over the top of a 2-liter bottle of pop (or soda as non-midwesterners may try to convince me). A great primer is available from ST here.

The Problem

Now, getting back to the main objective of a test methodology, I was told by one of our acoustics consultants that leaks in a gasket typically pass low frequencies, with smaller leaks passing lower frequencies, and larger leaks passing higher frequencies, but he wasn’t able to explain why other than giving anecdotal evidence. Thinking about it, it seems to make sense that a gasket leak would pass low frequencies but not high ones, but it bothered me there was no mathematical basis for this claim. Someone once tried to hand-wave it by saying that it seemed to make sense that it would act like a capacitor, as I’m sure they were relating to a low pass RC filter, but capacitive reactance is inversely related to frequency, not proportional to it, as is the case with inductive impedance, which is why the capacitor connects to ground in a low pass RC filter; it passes the high frequencies through it to ground, forcing the low frequencies to pass to the output of the filter.

Alright, as an aside I feel compelled to briefly touch base on this, and maybe I’ll expand it to a different post, but here are the mathematical models for impedance for a capacitor and inductor:

\displaystyle Z_{C} = -j \frac{1}{\omega C}
\displaystyle Z_{L} = j\omega L

Where C is capacitance, L is inductance, and j is the square root of -1. As impedance is composed as the sum of resistance (real) and reactance (imaginary), we see the impedance of inductors and capacitors are purely from reactance.

Anyway, didactic diatribes aside, let’s get in to this.

Acoustical Derivation

For the case of simple one dimensional, harmonic motion, we know the displacement of a particle as a function of position, x, and time, t, is given by equation 1, below.

1) \displaystyle \qquad y = y_{m} \sin (kx-\omega t)

Where y_{m} is the displacement magnitude, k is the wave number, and \omega is the waveform angular velocity.

We can also model the one dimensional particle velocity, u, and acoustic pressure, p, with equations 2 and 3 respectively.

2) \displaystyle \qquad u = \frac{\partial y}{\partial t} = -A \omega \cos (kx-\omega t

3) \displaystyle \qquad p = -\kappa \frac{\partial y}{\partial x}= - \kappa A k \cos(kx - \omega t)

Where \kappa is the adiabatic bulk modulus.

Some texts prefer to define the particle velocity as related to increment in infinitesimal working volume, \tau and displacement \xi. For the three dimensional case this becomes:

4) \displaystyle \qquad \tau = V_{0} \; div \; \xi = V_{0} \; \nabla \cdot \xi

Differentiating with respect to time yields:

5) \displaystyle \qquad \frac{\partial \tau}{\partial t} = V_{0} \nabla \cdot q

Where q is the instantaneous particle velocity. In the one dimensional case this reduces to:

6) \displaystyle \qquad \frac{\partial \tau}{\partial t} = V_{0} \frac{\partial u}{\partial x}

Where u is the instantaneous one dimensional particle velocity. This ultimately relates particle velocity as the time rate of change of particle displacement.

7) \displaystyle \qquad u = \frac{\partial \xi_{x}}{\partial x}

Let’s proceed using the more intuitive definition of partial y partial t. If we then consider a one dimensional wave passing through an aperture with area A, the volume flow, U is defined as:

8) \displaystyle \qquad U = \frac{dV}{dt} = A \frac{dy}{dt} = Au

The acoustic impedance, Z, is then defined as the ratio of sound pressure to volume flow, which for this simple one dimensional case ignores reflections, etc.

9) \displaystyle \qquad Z = \frac{p}{U} = \frac{p}{Au} = \frac{z}{A}

Which utilizes changing to specific acoustic impedance, z:

10) \displaystyle \qquad z = \frac{p}{u}

We can also show that the adiabatic bulk modulus, which is the ratio of infinitesimal pressure increase to the resulting relative decrease of the volume, assuming no heat transfer, is:

11) \displaystyle \qquad \kappa = \rho v^2

where \rho is the acoustic medium density, and v is the velocity of sound in an ideal gas, v = \omega \ k.

If we then re-arrange equation 9, and substitute equations 2 and 3 we obtain:

12) \displaystyle \qquad z = \frac{- \kappa y_{m} \cos(kx - \omega t)}{-Ay \omega \cos(kx - \omega t)} = \frac{\kappa k}{A \omega} = \frac{\omega^2 k}{k^2 A \omega} = \frac{\rho \omega}{k A}

where k is the wave number, k = 2 \pi /\lambda.

From equation 12 we can see that as the frequency increases, the area of the aperture must also increase to maintain the same characteristic acoustic resistance. We can therefore conclude that if there are leaks in a MEMS microphone gasket, the smaller the size of the leak, the smaller the frequency is that it will pass.

Testing Apparatus

With the above knowledge, the testing apparatus consisted of a speaker mounted directly in front of the microphone port, one directly behind the mounted microphone and a single board computer to control the processing.

The test itself consists of five frequency sweeps with differing magnitudes to compensate for the large difference between minima and maxima of frequency response of the speakers. Each of the 5 sweeps are played, loaded into memory, windows with a rectangular window (the same as no window), and finally an FFT is used to convert to frequency domain using the pyfftw library so as to accelerate computation over traditional functions that operate on the Cooley-Tukey fast Fourier transform algorithm, such as that include with scipy. Once FFTs are obtained, a savitzky-golay filter is used to smooth the data while attempting to best preserve spectral peaks. The element wise ratio of filtered front speaker FFT to back speaker FFT is then calculated to determine the gasket attenuation. If the attenuation is above a pre-set threshold for all frequencies in each sweep the test is considered a pass. Below are some examples from the different frequency spectra, with red indicating the frequency response calculated from playing through the front speaker, and blue indicating the frequency response calculated from playing through the rear speaker.

Plots

40 to 80 hz frequency band frequency response
40 to 80 hz frequency band attenuation
80 to 140 hz frequency band frequency response
80 to 140 hz frequency band attenuation
140 to 220 hz frequency band frequency response
140 to 220 hz frequency band attenuation
220 to 2200 hz frequency band frequency response
220 to 2200 hz frequency band attenuation
2.2 to 20 khz frequency band frequency response
2.2 to 20 khz frequency band attenuation
example text output to be saved


Sources

http://www.animations.physics.unsw.edu.au/jw/sound-impedance-intensity.htm
and
Acoustics: Sound Fields and Transducers. L. Baranek, T. Mellow.

Real Time Kernel On Nvidia Jetson TX2

This is still under construction, but I wanted to publish it fast so a friend could duplicate the work…

So you want to build a real time kernel on your TX2, eh? Shouldn’t be much of an issue, right? Eh… It’s a little annoying, but here’s how I did it.

Before I begin, I’d like to thank the guys over at Jetson Hacks, because they made all of this MUCH easier for me. Now, let’s get started.

Getting Started

Start by cloning the Jetson Hacks build Jetson TX2 Kernel repo from here:
https://github.com/jetsonhacks/buildJetsonTX2Kernel

git clone https://github.com/jetsonhacks/buildJetsonTX2Kernel.git

Since I’m using Linux For Tegra 28.1, checkout their vL4T28.1 release tag.

git checkout vL4T28.1

Run the get kernel sources script (note: this will take a while):

sudo ./getKernelSources.sh

Make sure that loadable kernel modules are enabled, and go ahead and write the kernel configuration file to .config, then let’s try to build the vanilla kernel to see if we have any issues to begin with.

sudo ./makeKernel.sh

Everything builds fine for me, so let’s get to patching the kernel with the PREEMPT_RT patch.

Kernel builds are typically located in the /usr/src directory, so let’s cd to where this kernel build is occurring:
cd /usr/src/kernel/kernel-4.4

Get the rt preempt patch that EXACTLY matches our linux kernel version:

wget https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/older/patch-4.4.38-rt49.patch.xz

Make sure we have the xz-utils package to unpack .xz files:
sudo apt install xz-utils
unxz patch-4.4.38-rt49.patch.xz

Dry Run The Patch

Now, let’s do a patch dry run to see what we’re getting ourselves into:
patch -p1 --dry-run <patch-4.4.38-rt49.patch | grep FAIL

Ok, so we get some hunks that fail, but it doesn’t look like it will be anything intractable. Let’s just go ahead and patch it, redirect the output to a log file and see what we have to manually fix.

patch -p1 <patch-4.4.38-rt49.patch > patch.log
cat patch.log | grep FAILED>patch_fail.log
cat patch_fail.log

So, it looks like we have three files that have been rejected, with rejection details being saved to the corresponding .rej files. Let’s take a look at the first, cpu.c.rej.

cd kernel
ls

We see four files that we are interested in: cpu.c, which is the patched file, cpu.c.orig, which is the original, unpatched file, cpu.c.rej, which shows the rejected patch attempt, and cpu.o, which is the created object file.

Let’s open up cpu.c.rej and see what the issue is:

The exact line numbering that’s indicated by the reject file for kernel patches on this system has yet to make sense to me. It appears to be indicating that the issue in the original file starts at line 740 and persists for 9 lines, whereas the issue in the new file starts at line 1056 and goes for 14 lines. However, if we search for where the changes are we get to line 429… I’m assuming that it’s just a calling function that is somehow being caught at line 740, but in any case, let’s continue.



Begin The Manual Patching…

So, if we open up all three files, cpu.c, cpu.c.rej and cpu.c.orig, we can pretty easily see what the issue is: there is a trace_sched_cpu_hotplug()function call in there that the patch file wasn’t expecting.

Indeed, if we check the patch file and search for out_release, we find:

This entry in the patch file indicates that it wants to add cpu_unplug_done(cpu);and out_cancel:after out_release and before cpu_hotplug_done(), but there is an extra trace_sched_cpu_hotplug()in there messing things up. Since the patch file didn’t expect this, it fails because it doesn’t quite know what to do. Let’s manually patch it by placing this inside of out cancel:

Let’s save cpu.c and consider this file patched!

Yeah!

Moving on to the next rejected file, suspend.c.rej, we see that this patch failed in two places:

Let’s search for this area in the patched file to see what the issue is.

So, here we see the first issue, thre is a pm_suspend_marker()call in between return -EINVAL;and error =.
Let’s manually patch this part and find the second issue.


Finding the second issue, it looks like the line pm_suspend_marker("exit")is unexpected, so let’s manually patch this like we did the first issue.

Save it and consider it patched!

Now, on to the third one: /net/ipv4/tcp_ipv4.c.rej

And proceeding like we did before to find these same spots in the output patched file:

We again see that there is an unexpected line (the .uid method). Manually add the lock and unlock function calls:

Finding the second section that was rejected, we also see it’s an issue involving locks:

Save it, and we should (hopefully) be done patching!

Building After The Manual Patch

Now, let’s pick up where the jetson hacks scripts have left off:

cd kernel/kernel-4.4
make xconfig

Before changing any of the configuration parameters, let’s verify that things compile without tweaking the preemption model. Just go ahead and save the default values as .config.
Continuing on with the jetson hacks stuff, lets go back to the git directory and source the makeKernel.shscript and see if it compiles.

Ok, shit blows up, not what we were hoping to see. It looks like this may be an issue in the way nvidia prefers you build kernels, going back and seeing how good our GoogleFu skills are we find this discussion:

https://devtalk.nvidia.com/default/topic/1014729/how-to-compile-the-tx2-l4t-kernel-source-/

It looks like we need to set some environment variables and select the make output directory. Let’s make these changes in the jetson hacks makeKernel.sh shell script.

Ok, let’s try making again.

We get a bunch of garbage, so let’s start from a clean slate using make mrproperlike it suggests.

we need sudo…

Ok, then let’s manually call the commands:

mkdir $TEGRA_KERNEL_OUT
make O=$TEGRA_KERNEL_OUT tegra18_defconfig
make O=$TEGRA_KERNEL_OUT prepare
make O=$TEGRA_KERNEL_OUT zImage

It looks like we are seeing an issue with compiler warning flags. From a little more GoogleFu it appears that if we are using gcc5.x or higher we can suppress these warnings for incompatible pointer type. Let’s see if we need to chance which version of gcc we are using:

Since we’re using gcc 5.4.0 we can go into the main kernel Makefile and set -Wno-incompatible-pointer-types.

nano /usr/src/kernel/kernel-4.4/Makefile
and then search for the kbuild flag corresponding to incompatible pointer types.

Let’s change this line that enforces correct pointer usage to:
KBUILD_CFLAGS += $(call cc-option,-Wnoerror=incompatible-pointer-types)
Note: I’m not very concerned about doing this since the only places that this occurs is in the cryptography library.
Let’s save this change and manually try building the kernel image.

nvidia@tegra-ubuntu:/usr/src/kernel/kernel-4.4$ sudo make -j4 O=$TEGRA_KERNEL_OUT zImage

HO. LEE. SHIT. It built.

Selecting The Preemption Model

Phew, ok, let’s go back and make the config file and select the fully preemptive preemption model.

sudo rm -rf out/
mkdir $TEGRA_KERNEL_OUT

make O=$TEGRA_KERNEL_OUT tegra18_defconfig
make O=$TEGRA_KERNEL_OUT xconfig

In the configuration menu let’s go to Kernel Features -> Preemption Model -> Fully Preemptible Kernel (RT)
Note: if you are using a different system this will probably appear under a different tab.

If you want, you can also select to append a string to the local version. I was uncertain if it would automatically append -rt49, so I manually added this to the local version name. It does indeed add -rt49, so this was redundant.

Save and quit xconfig.

Continuing on, prepare the kernel and make it.
make -j4 O=$TEGRA_KERNEL_OUT prepare
sudo make -j4 O=$TEGRA_KERNEL_OUT zImage

This builds fine, so let’s make and install the kernel modules and device tree blobs.

sudo make O=$TEGRA_KERNEL_OUT dtb
sudo make O=$TEGRA_KERNEL_OUT modules
sudo make O=$TEGRA_KERNEL_OUT modules_install

This by default installs modules in /lib/modules/
I’m unsure if we need the compressed zImage or the regular binary Image file, so let’s just copy both over from the output directory:

sudo cp arch/arm64/boot/zImage /boot/zImage

sudo cp arch/arm64/boot/Image /boot/Image

Let’s verify that the compressed and binary files have been copied to the boot directory.

Looks good! Now, for the new kernel to take effect, reboot the machine and verify that the new kernel is being used. Let’s note the original system information using uname -rand uname -a.


Verify The Kernel Is Loaded

After rebooting, let’s verify that the kernel name has changed to reflect our patched image:

Cool! It looks like the new kernel has taken effect.
Now, the last check to be performed is to start a thread with priority level 99 and verify that it in fact shows this priority level in htop.

Verifying The Kernel Is Fully Preemptible

We can create a simple little function to do this:
make sure to include the pthread.h and sched files

Alright, let’s compile this and run and see how it looks in htop.

Awesome, htop shows this thread has a priority level of RT, which is the highest allowed by the system. Looks like we are finished!

Thanks to all these posts for helping me through this:

https://github.com/jetsonhacks/buildJetsonTX2Kernel/blob/vL4T28.1/scripts/getKernelSources.sh

https://devtalk.nvidia.com/default/topic/1014729/how-to-compile-the-tx2-l4t-kernel-source-/

https://developer.ridgerun.com/wiki/index.php?title=Compiling_Jetson_TX2_source_code

https://stackoverflow.com/questions/22322304/image-vs-zimage-vs-uimage

https://www.jann.cc/2015/05/18/peempt_rt_for_the_nvidia_jetson_tk1.html

Static Analysis of an Unbalanced Barbell

Alright, this is one that people have asked me to explain to them at the gym using actual numbers on more than one equation. It’s easy to understand that a barbell with weights only loaded on one side is able to balance, but people have asked some variant of “how stable is a bar that has weights on one side?” Well, let’s get into it!

Quick Physics Primer

In order to answer this one, we’ll take advantage of a branch of classical mechanics that people typically call statics; that is, analysis of forces on a body that result in no motion. Two concepts that you will have to understand are the notions of balance of forces, and balance of moments. A balance of forces is easy enough to imagine, a simple example is if you were to push horizontally on a wall, the wall pushes back on you with the exact same amount of force in the opposite direction, thereby causing the forces acting on the person-wall system to balance to 0. Balance of moments is exactly the same, but using moments, that is, forces that cause rotational motion.; most people will call this a torque, but physics uses the term moment. Think of two kids on a seesaw, one weighs 90 pounds and the other 80 pounds, each 4 feet from the center pivot point. The moment created by the 90 pound child we will call M1, and has magnitude 90 lbs x 4 feet = 360 lb-ft. Similarly, the moment created by the second child is 80 lbs x 4 feet = 320 lb-ft. So, if they are at rest and the smaller child is up in the air and the larger child is sitting on the ground, how much force is the ground exerting against the larger child? Easy! We know our forces and moments have to balance because there is no motion, so by looking at our moments we can construct the equation 360 = 320 + ground. Solving for the ground force we are left with 40 lb-ft, which upon dividing by the distance the force is from the center pivot, we obtain 10 pounds, as one would expect. Alright, now on to answering the question we actually care about.

Solution

Since we are dealing with moments, we need to know the actual dimensions of the barbell and weights we are asking about. Let’s assume we are using a Rogue Ohio Bar, and it’s being loaded with Rogue HG 2.0 bumper plates. I’ve chosen these plates because they are rather thick and will create a worst case scenario since they will force the loaded weight to hang further to one side. Now, with this bar and plates the dimensions we are about are as follows:

Unbalanced 45 lb Barbell

With all of this in mind, let’s create a free body diagram to visualize all of the forces and moments.

Unbalanced Barbell FBD

Alright, let’s talk about this picture. There are five main things that I’ve added that we care about: Forces acting on the system from the weight plates F1, and F2, forces acting on the system from the weight of the barbell, F3, forces acting on the system from the reactionary (balancing) forces caused by the squat rack R1, R2, the coordinate system that I’ve chosen to use, describing the X, Y, Z directions and coordinate system origin, O, from which all of my measurements will be relative to, and the distances these forces are from the origin. Since the barbell is axisymmetric we can apply the 45 pound force resulting from the mass of the barbell as a point force acting at its center of mass. Similarly, we can do this with the two plates.
You may notice that I chose to place my coordinate system origin through the line of action of the first reactionary force, this is on purpose. This allows me to neglect the moment created by R1 since it passes through the origin, resulting in a moment of M = 0"\cdot R_{1} = 0.

Working Out The Math

With all of this illustrated, let’s go ahead and construct our force and moment balance equations.

Sum of Forces:
1) \qquad \displaystyle \sum F = -F_{1} - F_{2} + R_{1} - F_{3} + R_{2} = 0

Sum of Moments:
2) \displaystyle \qquad \sum\nolimits M = 9.125" \cdot F_{1} + 5.375" \cdot F_{2} - 23.5" \cdot F_{3} + 47" \cdot R_{2} = 0

If we rearrange these equations we obtain:
1) \displaystyle \qquad F_{1} + F_{2} + F_{3} = R_{1} + R_{2}
2) \displaystyle \qquad 9.125" \cdot F_{1} + 5.375" \cdot F_{2} + 47" \cdot R_{2} = 23.5" \cdot F_{3}

We also know that forces F1, F2, and F3 are all 45 pounds. We can plug these values into equations 1 and 2 and solve for the second reactionary force. Doing this allows us to find out how much force the far side squat rack support arm is pushing back against the bar with. When this value drops to 0 or lower, the bar will lose contact with the rack since the support arm would then have to be pulling that side of the bar down in the negative y direction for forces to balance.

1) \displaystyle \qquad 45lb + 45lb + 45lb = R_{1} + R_{2}
2) \displaystyle \qquad 9.125" \cdot 45lb + 5.375" \cdot 45lb + 47" \cdot R_{2} = 23.5" \cdot 45lb

Simplifying further yields:
1) \displaystyle \qquad 135lb = R_{1} + R_{2}
2) \displaystyle \qquad 410.625 in-lb + 241.875 in-lb + 47" \cdot R_{2} = 1057.5 in-lb

Finally solving for the second reactionary moment:
2) \displaystyle \qquad 47" \cdot R_{2} = 405 in-lb

And dividing by the lever arm distance to obtain the reactionary force:
\displaystyle R_{2} = 8.617 lb

Now that we know R2, we can plug this in to equation 1 to find the first reactionary force.
1) \displaystyle \qquad 135lb = R_{1} + 8.617lb

Solving for R1 we obtain:
\displaystyle R_{1} = 126.383lb

Cool! So we can see that with this setup the barbell is still stable on the squat rack as the second support arm is exerting more than 8.5 lbs upwards to keep the barbell from falling.

Moving On

In a second part to this I will address the worst case scenario of when the bar is pulled all the way to one side, thereby creating longer lever arms for the plates, and a shorter lever arm for the mass of the barbell. We can even go as far as to solve for what kind of force would be required to start the bar tipping off the rack if someone were to bump in to it from the far side. Until then, happy lifting!