Related
I have a problem in performing a non linear fit with Gnu Octave. Basically I need to perform a global fit with some shared parameters, while keeping others fixed.
The following code works perfectly in Matlab, but Octave returns an error
error: operator *: nonconformant arguments (op1 is 34x1, op2 is 4x1)
Attached my code and the data to play with:
clear
close all
clc
pkg load optim
D = dlmread('hd', ';'); % raw data
bkg = D(1,2:end); % 4 sensors bkg
x = D(2:end,1); % input signal
Y = D(2:end,2:end); % 4 sensors reposnse
W = 1./Y; % weights
b0 = [7 .04 .01 .1 .5 2 1]; % educated guess for start the fit
%% model function
F = #(b) ((bkg + (b(1) - bkg).*(1-exp(-(b(2:5).*x).^b(6))).^b(7)) - Y) .* W;
opts = optimset("Display", "iter");
lb = [5 .001 .001 .001 .001 .01 1];
ub = [];
[b, resnorm, residual, exitflag, output, lambda, Jacob\] = ...
lsqnonlin(F,b0,lb,ub,opts)
To give more info, giving array b0, b0(1), b0(6) and b0(7) are shared among the 4 dataset, while b0(2:5) are peculiar of each dataset.
Thank you for your help and suggestions! ;)
Raw data:
0,0.3105,0.31342,0.31183,0.31117
0.013229,0.329,0.3295,0.332,0.372
0.013229,0.328,0.33,0.33,0.373
0.021324,0.33,0.3305,0.33633,0.399
0.021324,0.325,0.3265,0.333,0.397
0.037763,0.33,0.3255,0.34467,0.461
0.037763,0.327,0.3285,0.347,0.456
0.069405,0.338,0.3265,0.36533,0.587
0.069405,0.3395,0.329,0.36667,0.589
0.12991,0.357,0.3385,0.41333,0.831
0.12991,0.358,0.3385,0.41433,0.837
0.25368,0.393,0.347,0.501,1.302
0.25368,0.3915,0.3515,0.498,1.278
0.51227,0.458,0.3735,0.668,2.098
0.51227,0.47,0.3815,0.68467,2.124
1.0137,0.61,0.4175,1.008,3.357
1.0137,0.599,0.422,1,3.318
2.0162,0.89,0.5335,1.645,5.006
2.0162,0.872,0.5325,1.619,4.938
4.0192,1.411,0.716,2.674,6.595
4.0192,1.418,0.7205,2.691,6.766
8.0315,2.34,1.118,4.195,7.176
8.0315,2.33,1.126,4.161,6.74
16.04,3.759,1.751,5.9,7.174
16.04,3.762,1.748,5.911,7.151
32.102,5.418,2.942,7.164,7.149
32.102,5.406,2.941,7.164,7.175
64.142,7.016,4.478,7.174,7.176
64.142,7.018,4.402,7.175,7.175
128.32,7.176,6.078,7.175,7.176
128.32,7.175,6.107,7.175,7.173
255.72,7.165,7.162,7.165,7.165
255.72,7.165,7.164,7.166,7.166
511.71,7.165,7.165,7.165,7.165
511.71,7.165,7.165,7.166,7.164
Giving the function definition above, if you call it by F(b0) in the command windows, you will get a 34x4 matrix which is correct, since variable Y has the same size.
In that way I can (in theory) compute the standard formula for lsqnonlin (fit - measured)^2
I am trying to call to a script, and I am getting an error message. Please help.
The following is what I am trying to run in Octave:
%%% May 23, 2016
%%% Potential Fields for Robot Path Planning
%
%
% Initially proposed for real-time collision avoidance [Khatib 1986].
% Hundreds of papers published on APF
% A potential field is a scalar function over the free space.
% To navigate, the robot applies a force proportional to the
% negated gradient of the potential field.
% A navigation function is an ideal potential field
clc
close all
clear
%% Defining environment variables
startPos = [5,5];
goalPos = [90, 95];
obs1Pos = [50, 50];
obsRad = 10;
goalR = 0.2; % The radius of the goal
goalS = 20; % The spread of attraction of the goal
obsS = 30; % The spread of repulsion of the obstacle
alpha = 0.8; % Strength of attraction
beta = 0.6; % Strength of repulsion
%% Carry out the Potential Field Math as follows:
u = zeros(100, 100);
v = zeros(100, 100);
testu = zeros(100, 100);
testv = zeros(100, 100);
for x = 1:1:100
for y = 1:1:100
[uG, vG] = GoalDelta(x, y, goalPos(1), goalPos(2), goalR, goalS, alpha);
[uO, vO] = ObsDelta(x, y, obs1Pos(2), obs1Pos(1), obsRad, obsS, beta);
xnet = uG + uO;
ynet = vG + vO;
vspeed = sqrt(xnet^2 + ynet^2);
theta = atan2(ynet,xnet);
u(x,y) = vspeed*cos(theta);
v(x,y) = vspeed*sin(theta);
% hold on
end
end
%%
[X,Y] = meshgrid(1:1:100,1:1:100);
figure
quiver(X, Y, u, v, 3)
%% Defining the grid
% Plotting the obstacles
circles(obs1Pos(1),obs1Pos(2),obsRad, 'facecolor','red')
axis square
hold on % Plotting start position
circles(startPos(1),startPos(2),2, 'facecolor','green')
hold on % Plotting goal position
circles(goalPos(1),goalPos(2),2, 'facecolor','yellow')
%% Priting of the path
currentPos = startPos;
x = 0;
while sqrt((goalPos(1)-currentPos(1))^2 + (goalPos(2)-currentPos(2))^2) > 1
tempPos = currentPos + [u(currentPos(1),currentPos(2)), v(currentPos(1),currentPos(2))]
currentPos = round(tempPos)
hold on
plot(currentPos(1),currentPos(2),'-o', 'MarkerFaceColor', 'black')
pause(0.5)
end
The following is the error message I am getting:
error: invalid call to script C:\Users\MyComputer\Downloads\circles.m
error: called from
circles
ECE8743_PotentialFields_Obstacle_1 at line 59 column 1
>>
Here is circles.m:
function [ h ] = circles(x,y,r,varargin)
% h = circles(x,y,r,varargin) plots circles of radius r at points x and y.
% x, y, and r can be scalars or N-D arrays.
%
% Chad Greene, March 2014. Updated August 2014.
% University of Texas Institute for Geophysics.
%
%% Syntax
% circles(x,y,r)
% circles(...,'points',numberOfPoints)
% circles(...,'rotation',degreesRotation)
% circles(...,'ColorProperty',ColorValue)
% circles(...,'LineProperty',LineValue)
% h = circles(...)
%
%% Description
%
% circles(x,y,r) plots circle(s) of radius or radii r centered at points given by
% x and y. Inputs x, y, and r may be any combination of scalar,
% vector, or 2D matrix, but dimensions of all nonscalar inputs must agree.
%
% circles(...,'points',numberOfPoints) allows specification of how many points to use
% for the outline of each circle. Default value is 1000, but this may be
% increased to increase plotting resolution. Or you may specify a small
% number (e.g. 4 to plot a square, 5 to plot a pentagon, etc.).
%
% circles(...,'rotation',degreesRotation) rotates the shape by a given
% degreesRotation, which can be a scalar or a matrix. This is useless for
% circles, but may be desired for polygons with a discernible number of corner points.
%
% circles(...,'ColorProperty',ColorValue) allows declaration of
% 'facecolor' or 'facealpha'
% as name-value pairs. Try declaring any fill property as name-value pairs.
%
% circles(...,'LineProperty',LineValue) allows declaration of 'edgecolor',
% 'linewidth', etc.
%
% h = circles(...) returns the handle(s) h of the plotted object(s).
%
%
%% EXAMPLES:
%
% Example 1:
% circles(5,10,3)
%
% % Example 2:
% x = 2:7;
% y = [5,15,12,25,3,18];
% r = [3 4 5 5 7 3];
% figure
% circles(x,y,r)
%
% % Example 3:
% figure
% circles(1:10,5,2)
%
% % Example 4:
% figure
% circles(5,15,1:5,'facecolor','none')
%
% % Example 5:
% figure
% circles(5,10,3,'facecolor','green')
%
% % Example 6:
% figure
% h = circles(5,10,3,'edgecolor',[.5 .2 .9])
%
% % Example 7:
% lat = repmat((10:-1:1)',1,10);
% lon = repmat(1:10,10,1);
% r = .4;
% figure
% h1 = circles(lon,lat,r,'linewidth',4,'edgecolor','m','facecolor',[.6 .4 .8]);
% hold on;
% h2 = circles(1:.5:10,((1:.5:10).^2)/10,.12,'edgecolor','k','facecolor','none');
% axis equal
%
% % Example 8: Circles have corners
% This script approximates circles with 1000 points. If all those points
% are too complex for your Pentium-II, you can reduce the number of points
% used to make each circle. If 1000 points is not high enough resolution,
% you can increase the number of points. Or if you'd like to draw
% triangles or squares, or pentagons, you can significantly reduce the
% number of points. Let's try drawing a stop sign:
%
% figure
% h = circles(1,1,10,'points',8,'color','red');
% axis equal
% % and we see that our stop sign needs to be rotated a little bit, so we'll
% % delete the one we drew and try again:
% delete(h)
% h = circles(1,1,10,'points',8,'color','red','rot',45/2);
% text(1,1,'STOP','fontname','helvetica CY',...
% 'horizontalalignment','center','fontsize',140,...
% 'color','w','fontweight','bold')
%
% figure
% circles([1 3 5],2,1,'points',4,'rot',[0 45 35])
%
%
% TIPS:
% 1. Include the name-value pair 'facecolor','none' to draw outlines
% (non-filled) circles.
%
% 2. Follow the circles command with axis equal to fix distorted circles.
%
% See also: fill, patch, and scatter.
%% Check inputs:
assert(isnumeric(x),'Input x must be numeric.')
assert(isnumeric(y),'Input y must be numeric.')
assert(isnumeric(r),'Input r must be numeric.')
if ~isscalar(x) && ~isscalar(y)
assert(numel(x)==numel(y),'If neither x nor y is a scalar, their dimensions must match.')
end
if ~isscalar(x) && ~isscalar(r)
assert(numel(x)==numel(r),'If neither x nor r is a scalar, their dimensions must match.')
end
if ~isscalar(r) && ~isscalar(y)
assert(numel(r)==numel(y),'If neither y nor r is a scalar, their dimensions must match.')
end
%% Parse inputs:
% Define number of points per circle:
tmp = strcmpi(varargin,'points')|strcmpi(varargin,'NOP')|strcmpi(varargin,'corners')|...
strncmpi(varargin,'vert',4);
if any(tmp)
NOP = varargin{find(tmp)+1};
tmp(find(tmp)+1)=1;
varargin = varargin(~tmp);
else
NOP = 1000; % 1000 points on periphery by default
end
% Define rotation
tmp = strncmpi(varargin,'rot',3);
if any(tmp)
rotation = varargin{find(tmp)+1};
assert(isnumeric(rotation)==1,'Rotation must be numeric.')
rotation = rotation*pi/180; % converts to radians
tmp(find(tmp)+1)=1;
varargin = varargin(~tmp);
else
rotation = 0; % no rotation by default.
end
% Be forgiving if the user enters "color" instead of "facecolor"
tmp = strcmpi(varargin,'color');
if any(tmp)
varargin{tmp} = 'facecolor';
end
%% Begin operations:
% Make inputs column vectors:
x = x(:);
y = y(:);
r = r(:);
rotation = rotation(:);
% Determine how many circles to plot:
numcircles = max([length(x) length(y) length(r) length(rotation)]);
% Create redundant arrays to make the plotting loop easy:
if length(x)<numcircles
x(1:numcircles) = x;
end
if length(y)<numcircles
y(1:numcircles) = y;
end
if length(r)<numcircles
r(1:numcircles) = r;
end
if length(rotation)<numcircles
rotation(1:numcircles) = rotation;
end
% Define an independent variable for drawing circle(s):
t = 2*pi/NOP*(1:NOP);
% Query original hold state:
holdState = ishold;
hold on;
% Preallocate object handle:
h = NaN(size(x));
% Plot circles singly:
for n = 1:numcircles
h(n) = fill(x(n)+r(n).*cos(t+rotation(n)), y(n)+r(n).*sin(t+rotation(n)),'',varargin{:});
end
% Return to original hold state:
if ~holdState
hold off
end
% Delete object handles if not requested by user:
if nargout==0
clear h
end
end
What am I doing wrong here? How do I correct this error? I am rather new to Octave and Matlab, so any help is greatly appreciated.
this is the first post after pasting the error so maybe it'll help anyone later:
in my case pasting the script into a function worked out!
function retval = name_of_script(parametres)
%your script
endfunction
function [theta, J_history] = gradientDescent(X, y, theta, alpha, num_iters)
%GRADIENTDESCENT Performs gradient descent to learn theta
% theta = GRADIENTDESCENT(X, y, theta, alpha, num_iters) updates theta by
% taking num_iters gradient steps with learning rate alpha
% Initialize some useful values
m = length(y); % number of training examples
J_history = zeros(num_iters, 1);
for iter = 1:num_iters
% ====================== YOUR CODE HERE ======================
% Instructions: Perform a single gradient step on the parameter vector
% theta.
%
% Hint: While debugging, it can be useful to print out the values
% of the cost function (computeCost) and gradient here.
%
%theta(iter)=theta(iter)-0.01*(1/m)*(((theta(1)+theta(2))*X-y)*X(iter,2))
theta=theta-(alpha*(1/m)*(X*theta-y)*X(iter,2);
% ============================================================
% Save the cost J in every iteration
J_history(iter) = computeCost(X, y, theta);
end
end
theta=theta-(alpha*(1/m)*(X*theta-y)*X(iter,2);
The parentheses are not balanced as far as I can tell?
You're missing a closing parenthesis ) are you not?
I would like to smooth an Impulse Response audio file. The FFT of the file shows that it is very spikey. I would like to smooth out the audio file, not just its plot, so that I have a smoother IR file.
I have found a function that shows the FFT plot smoothed out. How could this smoothing be applied to the actual FFT data and not just to the plot of it?
[y,Fs] = audioread('test\test IR.wav');
function x_oct = smoothSpectrum(X,f,Noct)
%SMOOTHSPECTRUM Apply 1/N-octave smoothing to a frequency spectrum
%% Input checking
assert(isvector(X), 'smoothSpectrum:invalidX', 'X must be a vector.');
assert(isvector(f), 'smoothSpectrum:invalidF', 'F must be a vector.');
assert(isscalar(Noct), 'smoothSpectrum:invalidNoct', 'NOCT must be a scalar.');
assert(isreal(X), 'smoothSpectrum:invalidX', 'X must be real.');
assert(all(f>=0), 'smoothSpectrum:invalidF', 'F must contain positive values.');
assert(Noct>=0, 'smoothSpectrum:invalidNoct', 'NOCT must be greater than or equal to 0.');
assert(isequal(size(X),size(f)), 'smoothSpectrum:invalidInput', 'X and F must be the same size.');
%% Smoothing
% calculates a Gaussian function for each frequency, deriving a
% bandwidth for that frequency
x_oct = X; % initial spectrum
if Noct > 0 % don't bother if no smoothing
for i = find(f>0,1,'first'):length(f)
g = gauss_f(f,f(i),Noct);
x_oct(i) = sum(g.*X); % calculate smoothed spectral coefficient
end
% remove undershoot when X is positive
if all(X>=0)
x_oct(x_oct<0) = 0;
end
end
endfunction
function g = gauss_f(f_x,F,Noct)
% GAUSS_F calculate frequency-domain Gaussian with unity gain
%
% G = GAUSS_F(F_X,F,NOCT) calculates a frequency-domain Gaussian function
% for frequencies F_X, with centre frequency F and bandwidth F/NOCT.
sigma = (F/Noct)/pi; % standard deviation
g = exp(-(((f_x-F).^2)./(2.*(sigma^2)))); % Gaussian
g = g./sum(g); % normalise magnitude
endfunction
% take fft
Y = fft(y);
% keep only meaningful frequencies
NFFT = length(y);
if mod(NFFT,2)==0
Nout = (NFFT/2)+1;
else
Nout = (NFFT+1)/2;
end
Y = Y(1:Nout);
f = ((0:Nout-1)'./NFFT).*Fs;
% put into dB
Y = 20*log10(abs(Y)./NFFT);
% smooth
Noct = 12;
Z = smoothSpectrum(Y,f,Noct);
% plot
semilogx(f,Y,'LineWidth',0.7,f,Z,'LineWidth',2.2);
xlim([20,20000])
grid on
PS. I have Octave GNU, so I don't have the functions that are available with Matlab Toolboxes.
Here is the test IR audio file.
I think I found it. Since the FFT of the audio file (which is real numbers) is symmetric, with the same real part on both sides but opposite imaginary part, I thought of doing this:
take the FFT, keep the half of it, and apply the smoothing function without converting the magnitudes to dB
then make a copy of that smoothed FFT, and invert just the imaginary part
combine the two parts so that I have the same symmetric FFT as I had in the beginning, but now it is smoothed
apply inverse FFT to this and take the real part and write it to file.
Here is the code:
[y,Fs] = audioread('test IR.wav');
function x_oct = smoothSpectrum(X,f,Noct)
x_oct = X; % initial spectrum
if Noct > 0 % don't bother if no smoothing
for i = find(f>0,1,'first'):length(f)
g = gauss_f(f,f(i),Noct);
x_oct(i) = sum(g.*X); % calculate smoothed spectral coefficient
end
% remove undershoot when X is positive
if all(X>=0)
x_oct(x_oct<0) = 0;
end
end
endfunction
function g = gauss_f(f_x,F,Noct)
sigma = (F/Noct)/pi; % standard deviation
g = exp(-(((f_x-F).^2)./(2.*(sigma^2)))); % Gaussian
g = g./sum(g); % normalise magnitude
endfunction
% take fft
Y = fft(y);
% keep only meaningful frequencies
NFFT = length(y);
if mod(NFFT,2)==0
Nout = (NFFT/2)+1;
else
Nout = (NFFT+1)/2;
end
Y = Y(1:Nout);
f = ((0:Nout-1)'./NFFT).*Fs;
% smooth
Noct = 12;
Z = smoothSpectrum(Y,f,Noct);
% plot
semilogx(f,Y,'LineWidth',0.7,f,Z,'LineWidth',2.2);
xlim([20,20000])
grid on
#Apply the smoothing to the actual data
Zreal = real(Z); # real part
Zimag_neg = Zreal - Z; # opposite of imaginary part
Zneg = Zreal + Zimag_neg; # will be used for the symmetric Z
# Z + its symmetry with same real part but opposite imaginary part
reconstructed = [Z ; Zneg(end-1:-1:2)];
# Take the real part of the inverse FFT
reconstructed = real(ifft(reconstructed));
#Write to file
audiowrite ('smoothIR.wav', reconstructed, Fs, 'BitsPerSample', 24);
Seems to work! :) It would be nice if someone more knowledgeable could confirm that the thinking and code are good :)
I am working on modeling the motion of a single actuated leg in Octave. The leg has 3 points: a stationary hip (point A), a foot (point B) that moves along a known path, and a knee (point C) whose location and angle I am trying to solve for.
Using the code below I can successfully solve for the knee's XYZ position and relevant angles for a single value of the parameters s0 and Theta_H.
Now I want to be able to loop through multiple s0 and Theta_H values and run the solver. My problem is that I can't figure out how to pass new values for those variables into the equations function.
The reason this is tricky is that the function format necessary to use Octave's fsolve prevents entering inputs other than the unknowns into the function. I've tried updating a global variable as an indexer but to do that I would need to clear all workspace variables which causes other problems.
Any ideas on how to update the parameters in this function while still being able to input it into fsolve would be really appreciated!
The code below calls the solver:
global AC = 150; % length of the thigh limb
global CB = 150; % length of the shin limb
global lspan = 75; % width span of the foot touch down wrt the hip
global bob = 10; % height of the hip joint off the ground during a step
inits = [ .75; 2.35; 37; 0; 125]; % initial guesses at horizontal step position
% x(1): hip joint - guessing a 45 deg (.75 rad) angle for hip joint
% x(2): knee joint - guessing a 135 deg (2.35 rad) angle (wrt to vert)
% x(3): X position of the knee joint - guessing middle of the leg span in mm
% x(4): Y position of the knee joint - know it is 0 mm at the horizontal step position
% x(5): Z position of the knee joint - guessing the height to be ~80% of the height of a limb
[x, fval, info] = fsolve(#Rug_Bug_Leg, inits); % when running fsolve for the first time often have to remove the output suppress
The code below shows the function containing the system of equations to be solved by Octave's fsolve function:
function y = Rug_Bug_Leg(x)
global AC;
global CB;
global lspan;
global bob;
s0 = 0; % fore/aft (Y) position of the foot during the step. Trying to iterate this
Theta_H = 0; % hip angle during the step. Trying to iterate this
y = zeros(6,1); % zeros for left side of each equation
% First set of equations, Joint C wrt to Joint A
y(1) = -1*x(3)+AC*sin(x(1))*cos(Theta_H);
y(2) = -1*x(4)+AC*sin(x(1))*sin(Theta_H);
y(3) = -1*bob - x(5)+AC*cos(x(1));
% Second set of equations, Joint B wrt to Joint C
y(4) = x(3)-lspan +CB*sin(x(2))*cos(Theta_H);
y(5) = x(4) - s0 +sin(x(2))*sin(Theta_H);
y(6) = x(5) + bob + CB*cos(x(2));
end function
You can definitely do that!
All you need to do is create a function that returns a function.
First have your Rug_Bug_Leg function take s0 and Theta_H as inputs:
function y = Rug_Bug_Leg(x, s0, Theta_H)
% ...
endfunction
Then, you can write a "wrapper" function around Rug_Bug_Leg like this:
rbl = #(s0, Theta_H) #(x) Rug_Bug_Leg(x, s0, Theta_H)
Now, if you call rbl with some values (s0,Theta_H), it will return a function that takes x as input and returns Rug_Bug_Leg(x,s0,Theta_H).
For instance, rbl(0,0) returns the function:
#(x) Rug_Bug_Leg(x,0,0)
Here's a sample usage:
for s0=1:10
for Theta_H=1:10
[x, fval, info] = fsolve( rbl(s0,Theta_H), inits );
endfor
endfor