Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
# Conflicts:
#	toolbox/plotellipsoid.m
#	toolbox/plotsphere.m
  • Loading branch information
remo-pillat committed Nov 8, 2023
2 parents f81c704 + 7a6329c commit 993145f
Show file tree
Hide file tree
Showing 13 changed files with 331 additions and 275 deletions.
20 changes: 19 additions & 1 deletion .github/workflows/run_book_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,27 @@ jobs:
- name: Check out RVC3-MATLAB repository (for unit tests)
uses: actions/checkout@v3
- run: echo "The ${{ github.repository }} repository has been cloned to the runner."

- name: Start display server
# Start a display server so Java Swing is available for testing
run: |
sudo apt-get install xvfb
Xvfb :99 &
echo "DISPLAY=:99" >> $GITHUB_ENV
- name: Set up MATLAB
# This uses the latest release of MATLAB. Can specify "release" if needed.
uses: matlab-actions/setup-matlab@v1
# Use v2-beta for Java Swing access
uses: matlab-actions/setup-matlab@v2-beta
with:
release: R2023b
products: MATLAB Simulink Robotics_System_Toolbox Automated_Driving_Toolbox Computer_Vision_Toolbox Image_Processing_Toolbox Deep_Learning_Toolbox Model_Predictive_Control_Toolbox Optimization_Toolbox ROS_Toolbox Signal_Processing_Toolbox Statistics_and_Machine_Learning_Toolbox Symbolic_Math_Toolbox UAV_Toolbox Control_System_Toolbox

- name: Print out ver details
uses: matlab-actions/run-command@v1
with:
command: ver

- name: Run MATLAB Tests
# Only run tests in folder test/book
uses: matlab-actions/run-tests@v1
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/run_toolbox_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ jobs:
- name: Set up MATLAB
# This uses the latest release of MATLAB. Can specify "release" if needed.
uses: matlab-actions/setup-matlab@v1

- name: Print out ver details
uses: matlab-actions/run-command@v1
with:
command: ver

- name: Run MATLAB Tests
# Only run tests in test/toolbox folder
uses: matlab-actions/run-tests@v1
Expand Down
28 changes: 28 additions & 0 deletions test/toolbox/RunAllTests.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
% run the unit tests locally
%
% run from this folder, will produce test report + coverage.xml file

%% set up the test runner
import matlab.unittest.plugins.CodeCoveragePlugin
import matlab.unittest.plugins.codecoverage.CoberturaFormat
import matlab.unittest.TestRunner
import matlab.unittest.plugins.codecoverage.CoverageReport

suite = testsuite(".",IncludeSubfolders=false);
runner = TestRunner.withTextOutput;

% add a coverage report
reportFile = 'coverage.xml';
% reportFormat = CoberturaFormat(reportFile); % XML report
reportFormat = CoverageReport("."); % HTML report

plugin = CodeCoveragePlugin.forFolder("../../toolbox", IncludingSubfolders=true, Producing=reportFormat);
runner.addPlugin(plugin);


%% Run all unit tests in this folder
fprintf('---------------------------------- Run the unit tests ------------------------------------\n')

results = runner.run(suite);
open(fullfile(".","index.html"))

6 changes: 3 additions & 3 deletions toolbox/@CentralCamera/visjac_p_polar.m
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@

function J = visjac_p_polar(cam, rt, Z)

if numcols(rt) > 1
if numel(rt) > 2
J = [];
if length(Z) == 1
% if depth is a scalar, assume same for all points
Z = repmat(Z, 1, numcols(rt));
Z = repmat(Z, 1, size(rt, 2));
end
% recurse for each point
for i=1:numcols(rt)
for i=1:size(rt, 2)
J = [J; visjac_p_polar(cam, rt(:,i), Z(i))];
end
return;
Expand Down
12 changes: 10 additions & 2 deletions toolbox/NOTNEEDED/printline.m
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,16 @@

% Copyright 2022-2023 Peter Corke, Witold Jachimczyk, Remo Pillat

function out = printline(X, varargin)

function out = printline(X, options)
arguments
X
options.mode (1,1) string = "rpy";
options.fmt (1,1) string = ""
options.unit (1,1) string {mustBeMember(options.unit, ["rad", "deg"])} = "rad"
options.fid (1,1) {mustBeInteger} = 1
options.label (1,1) string = ""
end

opt.fmt = [];
opt.mode = {'rpy', 'euler', 'axang'};
opt.unit = 'rad';
Expand Down
5 changes: 3 additions & 2 deletions toolbox/ccxyz.m
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@

function [x,y] = ccxyz(lambda, e)
xyz = cmfxyz(lambda);
if nargin == 1,
if nargin == 1
cc = xyz ./ (sum(xyz')'*ones(1,3));
elseif nargin == 2,
elseif nargin == 2
xyz = xyz .* (e(:)*ones(1,3));
xyz = sum(xyz);
cc = xyz ./ (sum(xyz')'*ones(1,3));
Expand All @@ -33,3 +33,4 @@
x = cc(:,1);
y = cc(:,2);
end
end
107 changes: 49 additions & 58 deletions toolbox/plotellipse.m
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
function handles = plotellipse(E, varargin)
%PLOTELLIPSE Draw an ellipse
%
% PLOTELLIPSE(E) draws an ellipse defined by X'EX = 1
Expand All @@ -16,8 +15,12 @@
%
% PLOTELLIPSE(..., Name=Value) specifies additional
% options using one or more name-value pair arguments.
% Specify the options after all other input arguments.
%
%
% The ellipse is defined by x' * E * x = s^2 where x is in R^2
% and s is the scale factor.
%
% Options:
%
% confidence - Confidence interval, range 0 to 1. If a confidence interval
% is given then E is interpretted as an inverse covariance
% matrix and the ellipse size is computed using an inverse
Expand All @@ -38,8 +41,6 @@
% Default: 1
%
%
% The ellipse is defined by x' * E * x = s^2 where x is in R^2
% and s is the scale factor.
% For some common cases we require inv(E), for example
% - for robot manipulability
% \nu inv(J*J') \nu
Expand Down Expand Up @@ -67,52 +68,44 @@
% % Draw 95% confidence ellipse
% PLOTELLIPSE(COVAR, confidence=0.95);
%
% References:
% - Robotics, Vision & Control: Fundamental algorithms in MATLAB, 3rd Ed.
% P.Corke, W.Jachimczyk, R.Pillat, Springer 2023.
% Appendix C.1.4
%
% See also PLOTCIRCLE, PLOT_BOX, CHI2INV.

% Copyright 2022-2023 Peter Corke, Witek Jachimczyk, Remo Pillat

opt.fillcolor = 'none';
opt.alpha = 1;
opt.edgecolor = 'k';
opt.alter = [];
opt.npoints = 40;
opt.confidence = [];
opt.inverted = 0;

[opt,arglist,ls] = tb_optparse(opt, varargin);

% process some arguments

if ~isempty(ls)
opt.edgecolor = ls{1};
end
function handles = plotellipse(varargin)
ip = inputParser();
ip.KeepUnmatched = true;
ip.addRequired("E", @(x) isnumeric(x) && isreal(x));
ip.addOptional("center", [0 0], @(x) isnumeric(x) && isreal(x) && (numel(x) == 2));
ip.addOptional("ls", "", @(x) ischar(x) || isstring(x));
ip.addParameter("fillcolor", "none");
ip.addParameter("alpha", 1, @(x) isnumeric(x) && isreal(x) && isscalar(x));
ip.addParameter("edgecolor", "k");
ip.addParameter("alter", [], @(x) ishandle(x));
ip.addParameter("npoints", 40);
ip.addParameter("confidence", [], @(x) isnumeric(x));
ip.addParameter("inverted", false, @(x) islogical(x));
ip.parse(varargin{:});
args = ip.Results;
arglist = namedargs2cell(ip.Unmatched);
E = args.E;

% process the probability
if isempty(opt.confidence)
if isempty(args.confidence)
s = 1;
else
if exist('chi2inv', 'file') == 2
s = sqrt(chi2inv(opt.confidence, 2));
s = sqrt(chi2inv(args.confidence, 2));
else
s = sqrt(chi2inv_rvc(opt.confidence, 2));
s = sqrt(chi2inv_rvc(args.confidence, 2));
end
end

if ~isempty(arglist) && isnumeric(arglist{1})
% ellipse center is provided
center = arglist{1};
arglist = arglist(2:end);
else
% default to origin
center = zeros(1, size(E,1));
end

% check the ellipse to be altered
if ~isempty(opt.alter) && ~ishandle(opt.alter)
error('SMTB:plotellipse:badarg', 'argument to alter must be a valid graphic object handle');
end

holdon = ishold();
hold on

Expand All @@ -125,70 +118,68 @@
E = [A C;C B];

elseif all(size(E) == [2 2])
if ~opt.inverted
if ~args.inverted
E = inv(E);
end
else
error('ellipse is defined by a 2x2 matrix');
error('RVC3:plotellipse:badarg', ...
'ellipse is defined by a 1x3 or 2x2 matrix');
end


%% plot an ellipse

% define points on a unit circle
th = linspace(0, 2*pi, opt.npoints);
th = linspace(0, 2*pi, args.npoints);
pc = [cos(th);sin(th)];

% warp it into the ellipse
pe = sqrtm(E)*pc * s;

% offset it to optional non-zero center point
center = center(:);
if nargin > 1
pe = bsxfun(@plus, center(1:2), pe);
end
pe = args.center(:) + pe;
x = pe(1,:); y = pe(2,:);

% plot 2D data

if length(center) > 2
if length(args.center) > 2
% plot 3D data
z = ones(size(x))*center(3);
z = ones(size(x))*args.center(3);
else
z = zeros(size(x));
end


if strcmpi(opt.fillcolor, 'none')
if strcmpi(args.fillcolor, "none")
% outline only, draw a line

if isempty(ls)
if ~isempty(opt.edgecolor)
arglist = ['Color', opt.edgecolor, arglist];
if ~isempty(args.edgecolor)
arglist = [{"Color"}, args.edgecolor, arglist];
end
else
arglist = [ls arglist];
arglist = [{args.ls}, arglist];
end

if isempty(opt.alter)
if isempty(args.alter)
h = plot3(x', y', z', arglist{:});
else
set(opt.alter, 'xdata', x, 'ydata', y);
set(args.alter, "xdata", x, "ydata", y);
end
else
% fillcolored, use a patch

if ~isempty(opt.edgecolor)
arglist = ['EdgeColor', opt.edgecolor, arglist];
if ~isempty(args.edgecolor)
arglist = ["EdgeColor", args.edgecolor, arglist];
end

arglist = [ls, 'FaceAlpha', opt.alpha, arglist];
arglist = [ls, "FaceAlpha", args.alpha, arglist];


if isempty(opt.alter)
h = patch(x', y', z', opt.fillcolor, arglist{:});
if isempty(args.alter)
h = patch(x', y', z', args.fillcolor, arglist{:});
else
set(opt.alter, 'xdata', x, 'ydata', y);
set(args.alter, "xdata", x, "ydata", y);
end

end
Expand Down
Loading

0 comments on commit 993145f

Please sign in to comment.