Real Time Angle Detection for Inverted Pendulum
1 view (last 30 days)
Show older comments
James Rhodes
on 17 May 2020
Commented: Image Analyst
on 17 May 2020
I am currently trying to develop an inverted pendulum stablisation system using matlab and simulink utilising visual feedback. I have been trying to use 'Image Acquisition Toolbox' with imfindcircles to identify angles, this is what i currently have in place:
- Getting a snapshot of the current video
- Using imfindcircles to locate the main circles on the lever/arm of the pendulum
- Drawing line between those two points
- Drawing a vertical line which can be a static reference to compare the angle between lever arm and vertical line.
- computing angle of the two lines using an equation
- (will have to implement a for loop in which 1-5 is completed to ensure its real-time analysis)
I am struggling to determine the following:
- Will this be viable for a time senstive control system?
- Will image acquisition tool be able to compute these processes near real-time?
- is there anyway in which this can be improved (imfindcirlces can be unreliable at times causing the program to crash)?
Below is a snapshot of the code with its results: (above line 40 is simply lots of comments and using "vid = videoinput('winvideo', 1, 'MJPG_1920x1080');
src = getselectedsource(vid);" to import the files).
The current angle displayed is within 1 degree of error which I believe is acceptable (an if statement has been used for the angle formula for occasions the lever is to the left).
Any help or suggestions would be appreciated. Thankyou!
2 Comments
Accepted Answer
Image Analyst
on 17 May 2020
Why are you using findcircles? Can't you just threshold? It's a lot faster I believe. And simpler. Then make a mask and erase the pivot point and determine the angle using regionprops().
clc; % Clear the command window.
fprintf('Beginning to run %s.m.\n', mfilename);
close all; % Close all figures (except those of imtool.)
clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 20;
grayImage = imread('pendulum.png');
% Get the dimensions of the image.
% numberOfColorChannels should be = 1 for a gray scale image, and 3 for an RGB color image.
[rows, columns, numberOfColorChannels] = size(grayImage);
if numberOfColorChannels > 1
% It's not really gray scale like we expected - it's color.
% Use weighted sum of ALL channels to create a gray scale image.
grayImage = rgb2gray(grayImage);
% ALTERNATE METHOD: Convert it to gray scale by taking only the green channel,
% which in a typical snapshot will be the least noisy channel.
% grayImage = grayImage(:, :, 2); % Take green channel.
end
% Display the image.
subplot(2, 2, 1);
imshow(grayImage, []);
title('Original Grayscale Image', 'FontSize', fontSize, 'Interpreter', 'None');
impixelinfo;
hFig = gcf;
hFig.WindowState = 'maximized'; % May not work in earlier versions of MATLAB.
drawnow;
subplot(2, 2, 2);
imhist(grayImage);
grid on;
title('Histogram', 'FontSize', fontSize);
maskImage = imread('mask.png') > 128;
subplot(2, 2, 3);
imshow(maskImage, []);
title('Mask of Pivot Point', 'FontSize', fontSize);
someGrayLevel = 50;
binaryImage = grayImage < someGrayLevel; % Binarize it, or use binaryImage = ~imbinarize(grayImage).
% Erase pivot point
binaryImage(maskImage) = false;
% Extract largest blob only.
binaryImage = bwareafilt(binaryImage, 1);
% Fill any noise holes.
binaryImage = imfill(binaryImage, 'holes');
subplot(2, 2, 4);
imshow(binaryImage, []);
axis('on', 'image');
% Find orientation
props = regionprops(binaryImage, 'Orientation', 'Centroid');
angle = props.Orientation
fprintf('The angle = %f\n', angle);
% Mark the centroid.
hold on;
xCentroid = props.Centroid(1)
yCentroid = props.Centroid(2)
plot(xCentroid, yCentroid, 'r+', 'MarkerSize', 25, 'LineWidth', 2);
xFit = 1 : columns;
angle = -props.Orientation
slope = tand(angle)
yFit = slope * (xFit - props.Centroid(1)) + props.Centroid(2);
yFit(yFit < 1) = nan;
yFit(yFit > rows) = nan;
plot(xFit, yFit, 'c-', 'LineWidth', 2);
caption = sprintf('Pendulum with arm angle of %.2f degrees', angle);
title(caption, 'FontSize', fontSize);
% Draw another cyan line from the centroid upwards.
line([xCentroid, xCentroid], [1, yCentroid], 'LineWidth', 2, 'Color', 'c');
% Plot on original image also.
subplot(2, 2, 1);
hold on;
plot(xCentroid, yCentroid, 'r+', 'MarkerSize', 25, 'LineWidth', 2);
plot(xFit, yFit, 'c-', 'LineWidth', 2);
line([xCentroid, xCentroid], [1, yCentroid], 'LineWidth', 2, 'Color', 'c');
I'm attaching the mask but of course you'll need to make up a new one with the correct size.
2 Comments
Image Analyst
on 17 May 2020
findcircles() uses the Hough transform which is a fairly compilcated routine I believe.
More Answers (0)
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!