Deriving optimal trajectories on a manifold in GEKKO - gekko

I've finally gotten back to working on my project and have found my next hurdle.
I have an enclosed manifold:
Also here's an example trajectory in the game im modelling
that I can have my system drive on like a normal car. I'm curious what the best way to incorporate this type of constraint would be in gekko. The manifold looks like a cube with rounded edges and corners. My current thought is to create a MLP (multii layer perceptron) to approximate the normal vector on the manifold at each point in on the surface. I tried using the GEKKO brain model to do this but it ended up being very slow so I moved to a keras model. I now have a keras model that is about 89% percent accurate connecting positions to normal vectors (which might be enough).
So my first thing is, how can I incorporate the keras model into my gekko equations? If I'm able to calculate the derivative of the neural network output at each point as well would it be possible to black box the model such that gekko puts in a position and then the black box function spits out a normal vector and this normal vectors derivative to ultimately calculate optimal trajectories?
If this is not possible, do you think I could easily model this manifold as a bspline? And what would be the way I should approach making the manifold surface a constraint for the system while it's in the driving state? My thoughts were I would take the system's current velocity vector and dot it with the normal vector of the manifold at the system's position to get how much along the manifold the velocity vector rotates. I already see some problems like for example large time steps missing curvature of the manifold and causing the system to drive off the surface of the manifold. I think the typical way of doing this math is to project the system's velocity into the "tanget space" of the manifold, derive the future state in the tanget space then map back to the manifold using a retraction. I'm still fairly new to this topic of topology and manifolds so correct me if I've made a mistake on the theory.
I don't have much code yet doing this as I'm stuck figuring out how to use the keras model in an equation. I do have a simpler problem available which is instead of driving on this complex manifold I just drive on a circle in R2. I've modelled this circle in R2 using a keras model as well. I plan to start with the simpler version if I'm able to use keras in equations before I jump into driving on the manifold in R3.
Are there any examples doing something similar to this that I could learn form?
Thank You! Excited to get back into this project.

This path planning optimization application may be better with a shooting approach where the model is a "black box" that the optimizer repeatedly calls the simulator. Some of the challenges are the changing equations when the vehicle is interacting with the ground versus in the air. If you do want to try to model both ground and air, an if3 statement would allow the switching or else use slack variables.
For the boundary constraint, maybe there is a simpler way to start modeling it such as simple inequality constraints that would form a box. You could add additional inequality constraints for the edges to model the curvature.
Below is a related application with a rocket launch that is applicable to the air dynamics. You would need to extend this to 3D.
import numpy as np
import matplotlib.pyplot as plt
from gekko import GEKKO
# create GEKKO model
m = GEKKO()
# scale 0-1 time with tf
m.time = np.linspace(0,1,101)
# options
m.options.NODES = 6
m.options.SOLVER = 3
m.options.IMODE = 6
m.options.MAX_ITER = 500
m.options.MV_TYPE = 0
m.options.DIAGLEVEL = 0
# final time
tf = m.FV(value=1.0,lb=0.1,ub=100)
tf.STATUS = 1
# force
u = m.MV(value=0,lb=-1.1,ub=1.1)
u.STATUS = 1
u.DCOST = 1e-5
# variables
s = m.Var(value=0)
v = m.Var(value=0,lb=0,ub=1.7)
mass = m.Var(value=1,lb=0.2)
# differential equations scaled by tf
m.Equation(s.dt()==tf*v)
m.Equation(mass*v.dt()==tf*(u-0.2*v**2))
m.Equation(mass.dt()==tf*(-0.01*u**2))
# specify endpoint conditions
m.fix(s, pos=len(m.time)-1,val=10.0)
m.fix(v, pos=len(m.time)-1,val=0.0)
# minimize final time
m.Obj(tf)
# Optimize launch
m.solve()
print('Optimal Solution (final time): ' + str(tf.value[0]))
# scaled time
ts = m.time * tf.value[0]
# plot results
plt.figure(1)
plt.subplot(4,1,1)
plt.plot(ts,s.value,'r-',linewidth=2)
plt.ylabel('Position')
plt.legend(['s (Position)'])
plt.subplot(4,1,2)
plt.plot(ts,v.value,'b-',linewidth=2)
plt.ylabel('Velocity')
plt.legend(['v (Velocity)'])
plt.subplot(4,1,3)
plt.plot(ts,mass.value,'k-',linewidth=2)
plt.ylabel('Mass')
plt.legend(['m (Mass)'])
plt.subplot(4,1,4)
plt.plot(ts,u.value,'g-',linewidth=2)
plt.ylabel('Force')
plt.legend(['u (Force)'])
plt.xlabel('Time')
plt.show()
Here is one more application with the landing of a reusable rocket with source files. They developed a surrogate model of the rocket dynamics to apply the model in predictive control.
This is an example of a 3D rocket application but they didn't have the complication of ground interaction with changing dynamic equations.

Related

Formula for procedurally generating the location of planets in a game

I want to develop a game where the universe is a maximum 65536 x 65536 grid. I do not want the universe to be random, what I want is for it to be procedurally generated according to location. What it should generate is a number from 0 to 15.
0 means empty space. Most of the universe (probably 50-80%) is empty space.
1 - 9 a planet of that technology level
10-15 various anomalies (black hole, star, etc.)
Given an address from 0x8000-0xFFFF or 0 or 1-0x7fff for the X address, and the same range for the Y address, returns a number from 0 to 15. Presumably this would place planets nearer to 0,0 more plentiful than those at a distance of
The idea being, the function is called passing the two values and returns the planet number. I used to have a function to do this, but it has gotten lost over various moves.
While the board could be that big, considering how easy it would be to get lost, I'll probably cut the size to 1200 in both directions, -600 to +600. Even that would be huge.
I've tried a number of times, but I've come to the conclusion that I lack the sufficient math skills to do this. It's probably no more than 10 lines. As it is intended to be multiplayer, it'll probably be either a PHP application on the back end or a desktop application connecting to a server.
Any help would be appreciated. I can probably read any commonly used programming language you might use.
Paul Robinson
See How to draw sky chart? for the planetary position math. Especially pay attention to the image with equations you can use it to compute period of your planet based on its distance and mass to system central mass... for simple circular orbit just match the centripedal force with gravity like I did in here:
Is it possible to make realistic n-body solar system simulation in matter of size and mass?
So for example:
G = 6.67384e-11;
v = sqrt(G*M/a); // orbital speed
T = sqrt((4.0*M_PI*M_PI*a*a*a)/(G*(m+M))); // orbital period
pos = (a,0,0); // start position
vel = (0,sqrt(G*M/a),0); // start speed
The distribution of planets and their sizes complies specific (empirically obtained) rules (that is one of the reasons why we are still looking for 10th planet). I can't remember the name of the rule, however from quick look on Google Image from here can be used too:
Distribution of the planets in solar system according to their mass
and their distances from the Sun. The distances (X-axis) are in AU and
masses (Y-axis) in Yotta (10^24)
Jupiter mass is M=1,898e27 kg so mass units are in 10^24 kg.
So just match your PRNG generation to such curve and be done with it.

image processing : Segregating panel vs house like structure

I am working on a problem that involves segregating solar panel vs house.
Both the house as well as panel are of same color.
NOTE: There are two houses in the image. I am referring to the one which is bluish.
PFB the image as well as my approach.
Any insights how to deal with such situations are welcome.
My approach
transform to hsv colorspace
Perform thresholding on hue component of the image.
Dialate/Erode.
hsv_img = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
## Thresholding values
red_MIN = np.array([100, 10, 10],np.uint8)
red_MAX = np.array([130, 255, 255],np.uint8)
frame_threshed = cv2.inRange(hsv_img, red_MIN, red_MAX)
k_dialation = np.ones((5,5),np.uint8)
dialation = cv2.dilate(frame_threshed,k_dialation, iterations =5)
k = np.ones((3,3),np.int8)
erosion = cv2.erode(dialation,k,iterations =8)
I also tried drawing contours perform shape analysis,
calculate area,
but as both panel and house have same shape from top and similar area, This approach doesnt work.
I tried template matching,
query image : House structure.
I convolved over the image with query image to find relevant structure(house in my case)
steps 4-6 might work on this image but isnt generalized solution . A slight variation in terms of house position or a different shape house will break the algorithm.
Result after doing 1-5 steps.
Since the problem involves segregating the solar panels with roof tops, you cant expect a generic OpenCV solution to work out. Using supervised learning methods can be one choice.
If you want to segregate roof tops from solar panels, one distinction we can observe is that solar panels have a certain repetitive distinctive pattern. This can be employed for the job. Let me introduce to you this method called Histogram of Sparse Codes.
It is more like the HOG, where the object is recognized by the shape (gradients), with the difference that HSC takes " by learning and
using local representations that are much more expressive
than gradients ".
Then, as an improvement, you can try region proposal algorithms like Selective search instead of sliding window based approach.
HSC makes a dictionary of signals (Signals here are patches of images) from the train images and then reconstructs your test image from those signals. Then a histogram of the codes used to regenerate each signal is generated. Since your region of interest is unique, different set of codes are generated for your object and background and hence can make a distinction. Passing it to SVM can easily segregate your solar panels.
Link to the paper.
Link for selective search
You can use mlpack for sparse coding implementation.
All the best finding solar panel datasets.
Image after selective search (No thresholding etc hence more generalized usage):
If you are finding all the above very difficult to implement. Find the "+" signs inside the selective search regions. You can use template matching or HOG. Then the region with more rate of +'s is the solar panel.

Kalman filtering for movement in long lat coordinates

I am trying to implement a simple kalman filter that will be used for filtering/predicting the movement of a vehicle in long/loat coordinates.
There are no measurements from vehicle sensors, just a new update on an observed long/lat position, so basically the state that I will be trying to predict and correct is the longitude and latitude of the vehicle at any given time.
As far as I understand the model is non linear as there may be random accelerations change of direction etc, but I think this can be largely ignored as long as I keep track of the bearing as well in my state. My problem is that I do not know how to model this system in terms of the state and prediction matrices and on top of this it seems that it is necessary to convert/project the long/lat coordinates into some cartesian xy system so that the two become independent, but I am not exactly sure how to go about this.
It seems that converting back to wgs84 from xy is not that trivial and potentially a bit intense computationally. Can anyone shed some light into this?
It looks like your state variable would be a vector [lat, long], and your measurement variable would be [lat, long, bearing]. You will need to figure out appropriate f and h functions, based on these vectors, for the process and measurement models, respectively. Since this is a non-linear problem, you will probably need to use a nonlinear filter, such as the EKF, UKF or CKF (cubature Kalman filter).
When using a Kalman-type filter to deal with modular values such as angles, latitudes, or longitudes, there is a big problem whenever your state or your measurements are near the discontinuous modular boundary. For example, if your bearing is an angle from 0 to 360 degrees, the filter will have problems if you are measuring at 1 degree or 359 degrees. Also, you could have problems if your longitude is around plus or minus 180 degrees longitude, or your latitude is at one of the poles (which might be remote possibilities that you could ignore).
One example of how to deal with angles in the state or measurement variables is presented in David Frederic Crouse, "Cubature/ Unscented/ Sigma Point Kalman Filtering with Angular Measurement Models," 18th Int'l Conf. on Information Fusion (Wash., D.C. July 6-9, 2015), https://ieeexplore.ieee.org/document/7266741. Based on Crouse's approach, to use bearing as a measurement variable you would need to add a wrapping function to a couple of locations in the standard unscented or cubature filter equations. If you want to deal with the discontinuities in latitude and longitude (which you might not), you would need to transform the coordinates to and from Euclidean space while calculating the covariance matrices.

Does there exist a way to directly figure out the "smoothness" of a digital image?

There exist several ways to evaluate an image, brightness, saturation, hue, intensity, contrast etc. And we always hear about the operation of smoothing or sharperning an image. From this, there must exist a way to evaluate the overall smoothness of an image and an exact way to figure out this value in one formula probably based on wavelet. Or fortunately anyone could even provide the MATLAB function or combination of them to directly calculate this value.
Thanks in advance!
Smoothness is a vague term. What considered smooth for one application might not be considered smooth for another.
In the common case, smoothness is a function of the color gradients. Take a 2d gradient on the 3 color channels, then take their magnitude, sqrt(dx^2 + dy^2) and average, sum or some function over the 3 channels. That can give you local smoothness which you can then sum/average/least squares over the image.
In the more common case, however, linear changes in color is also smooth (think 2 color gradients, or how light might be reflected from an object). For that, a second differential could be more suitable. A laplacian does exactly that.
I've had much luck using the laplacian operator for calculating smoothness in Python with the scipy/numpy libraries. Similar utilities exist for matlab and other tools.
Note that the resulting value isn't something absolute from the math books, you should only use it relative to itself and using constants you deem fit.
Specific how to:
First get scipy. If you are on Linux it's it available on pypi. For Windows you'll have to use a precompiled version here. You should open the image using scipy.ndimage.imread and then use scipy.ndimage.filters.laplace on the image you read. You don't actually have to mix the channels, you can simply call numpy.average and it should be close enough.
import scipy as np
import scipy.ndimage as ndi
print np.average(np.absolute(ndi.filters.laplace(ndi.imread(path).astype(float) / 255.0)))
This would give the average smoothness (for some meaning of smoothness) of the image. I use np.absolute since values can be positive or negative and we don't want them to even out when averaging. I convert to float and divide by 255 to have values between 0.0 and 1.0 instead of 0 to 256, since it's easier to work with.
If you want to see the what the laplacian found, you can use matplotlib:
import matplotlib.pyplot as plt
v = np.absolute(ndi.filters.laplace(ndi.imread(path).astype(float) / 255.0))
v2 = np.average(v, axis=2) # Mixing the channels down
plt.imshow(v2);
plt.figure();
plt.imshow(v2 > 0.05);
plt.show()

Set autoscale limits on plot to have buffer around all points

I would like to plot a set of points using pyplot in matplotlib but have none of the points be on the edge of my axes. The autoscale (or something) sets the xlim and ylim such that often the first and last points lie at x = xmin or xmax making it difficult to read in some situations.
This is more often problematic with loglog() or semilog() plots because the autoscale would like xmin and xmax to be exact powers of ten, but if my data contains only three points, e.g. at xdata = [10**2,10**3,10**4] then the first and last points will lie on the border of the plot.
Attempted Workaround
This is my solution to add a 10% buffer to either side of the graph. But is there a way to do this more elegantly or automatically?
from numpy import array, log10
from matplotlib.pyplot import *
xdata = array([10**2,10**3,10**4])
ydata = xdata**2
figure()
loglog(xdata,ydata,'.')
xmin,xmax = xlim()
xbuff = 0.1*log10(xmax/xmin)
xlim(xmin*10**(-xbuff),xmax*10**(xbuff))
I am hoping for a one- or two-line solution that I can easily use whenever I make a plot like this.
Linear Plot
To make clear what I'm doing in my workaround, I should add an example in linear space (instead of log space):
plot(xdata,ydata)
xmin,xmax = xlim()
xbuff = 0.1*(xmax-xmin)
xlim(xmin-xbuff,xmax+xbuff))
which is identical to the previous example but for a linear axis.
Limits too large
A related problem is that sometimes the limits are too large. Say my data is something like ydata = xdata**0.25 so that the variance in the range is much less than a decade but ends at exactly 10**1. Then, the autoscale ylim are 10**0 to 10**1 though the data are only in the top portion of the plot. Using my workaround above, I can increase ymax so that the third point is fully within the limits but I don't know how to increase ymin so that there is less whitespace at the lower portion of my plot. i.e., the point is that I don't always want to spread my limits apart but would just like to have some constant (or proportional) buffer around all my points.
#askewchan I just succesfully achieved how to change matplotlib settings by editing matplotlibrc configuration file and running python directly from terminal. Don't know the reason yet, but matplotlibrc is not working when I run python from spyder3 (my IDE). Just follow steps here matplotlib.org/users/customizing.html.
1) Solution one (default for all plots)
Try put this in matplotlibrc and you will see the buffer increase:
axes.xmargin : 0.1 # x margin. See `axes.Axes.margins`
axes.ymargin : 0.1 # y margin See `axes.Axes.margins`
Values must be between 0 and 1.
Obs.: Due to bugs, scale is not correctly working yet. It'll be fixed for matplotlib 1.5 (mine is 1.4.3 yet...). More info:
axes.xmargin/ymargin rcParam behaves differently than pyplot.margins() #2298
Better auto-selection of axis limits #4891
2) Solution two (individually for each plot inside the code)
There is also the margins function (for put directly in the code). Example:
import numpy as np
from matplotlib import pyplot as plt
t = np.linspace(-6,6,1000)
plt.plot(t,np.sin(t))
plt.margins(x=0.1, y=0.1)
plt.savefig('plot.png')
Obs.: Here scale is working (0.1 will increase 10% of buffer before and after x-range and y-range).
A similar question was posed to the matplotlib-users list earlier this year. The most promising solution involves implementing a Locator (based on MaxNLocator in this case) to override MaxNLocator.view_limits.

Resources