What is causing dimension 1 to vary?

조회 수: 1 (최근 30일)
Sam Elliott
Sam Elliott 2019년 2월 28일
편집: Guillaume 2019년 3월 6일
In brief, I am trying to create a simulink function block that selects the next waypoint in a predefined array when the model vehicle gets within a certain distance of the current waypoint.
Inputs into this function block are the current waypoint 'target' in the form of a [1 x 2] array, distance to the currently selected waypoint 'd2w' and 'accuracy' as a value at which when 'd2w' is less than 'accuracy', the function block switches to the next waypoint in the predefined array.
Output is simply the desired waypoint 'targetnew'.
function target new - setwaypoint(d2w,target,accuracy)
waypoints = [100 150; 200 400; 175 275; 600 300]; % pre-defined waypoints (in the future imported as a large array from an external source.
if isempty(target) == 1
target = waypoints(1,:); % initializes the first waypoint.
end
idx = find((waypoints(:,1) == target(1)) & (waypoints(:,2) == target(2))); % determines current index.
if d2w > accuracy
idx = idx + 1; % if target waypoint is reached, add one to index.
end
if idx == length(waypoints)
targetnew = waypoints(end,:); % attempt to avoid any issues if simulation time is greater than time taken to reach final waypoint.
else, targetnew = waypoints(idx,:); % selects the indexed waypoint.
end
end
When run, I get an error saying:
Dimesnion 1 is fixed on the left hand side but varies on the right ([1 x 2] ~= [:? x 2]).
Function 'MATLAB Function' (~35.653.662), line 17, column 9:
"targetnew"
Nothing in my code should be varying in dimension. Looking at it, it might be line 9 that causes the isses, because for some reason in the report, it shows 'target' as a [2 x 1] when it should be [1 x 2].

답변 (2개)

Guillaume
Guillaume 2019년 2월 28일
There are many issue with your code, some minors, some majors.
1) minor
if isempty(target) == 1
should be simply
if isempty(target)
isempty returns the logical true or false. Which you then compare to double 1. So matlab has first to convert that logical to double, then compare it. The result of that comparison is then the exact same logical value that isempty returned in the first place.
2) major, and the cause of the error
idx = find((waypoints(:,1) == target(1)) & (waypoints(:,2) == target(2)))
that could be written more neatly as
idx = find(all(waypoints == target, 2));
Either way, that expression will return all the indices of the rows that match target. It seems you assume that there is always just one row. Matlab doesn't assume that, so for matlab idx can be a vector. It can also be empty if there's no match. So yes, later when you use idx to extract rows from waypoints, the result is ?x2.
You can tell matlab to return at most 1 index:
idx = find(all(waypoints == target, 2), 1); %no more than row
but for simulink you may still need to ensure that idx is not empty, maybe (I don't use simulink):
idx = find(all(waypoints == target, 2), 1);
if isempty(idx)
error('something went wrong');
end
%from here on idx is guaranteed to be scalar
3) minor in this context. Major in other context.
In my opinion, length should be deprecated. People misuse it, as you have done here. length returns the size of the largest dimension, luckily for you the largest dimension of waypoints is the number of rows, which is what you actually meant. But wait, until your code is later modifed and more columns added to waypoints. Suddenly your code will stop working. Use numel for vectors, and size with a explicit dimension for matrix, so:
if idx == size(waypoints, 1)
4) major, but goes away once you've solved 2
if idx == scalar
As we saw in 2), idx can be a vector. So you're comparing a vector to a scalar, which will return a logical vector. When you pass a logical vector to if the expression is only true if all the values are true. In your case, if idx is a vector, you are guaranteed that at most one value will be equal to the scalar, so the if will not be true.
5) major,
the idx returned by find may be the last row of waypoints, and you may have added 1 to that in the d2w test, in which case, idx is past the end row of waypoint. Not that if idx is equal to the height, there's no difference between end and idx, so your if test was pointless anyway. Perhaps, you meant:
if idx > size(waypoints, 1)
targetnew = waypoints(end, :);
else
targetnew = waypoints(idx, :);
end
That could be written simpler as:
targetnew = waypoints(min(end, idx), :); %no need for if
  댓글 수: 2
Sam Elliott
Sam Elliott 2019년 3월 3일
Okay, that is brilliantly explained thank you. I never realised how many issues I had but I've learnt something new.
However, I have implemented these changes and also specified sizes for the input and outputs of the function block, but Matlab is still not happy with your find function. It's not happy with the size mismatch between waypoints size[4 x 2] and target size[1 x 2].
I understand that that is exactly true, but I don't uderstand the ins and outs of the function. Does it not understand that it's supposed to find a vector that matches target within that array?
I apolagize for my ignorance, I'm very new to matlab.
mattlaberror6.png
Guillaume
Guillaume 2019년 3월 6일
편집: Guillaume 2019년 3월 6일
Certainly, you shouldn't see an 'Undefined function or variable' error, so you must have done something wrong. What is the code that you're using?
It should probably be:
function targetnew = setwaypoint(d2w,target,accuracy)
waypoints = [100 150; 200 400; 175 275; 600 300]; % pre-defined waypoints (in the future imported as a large array from an external source.
if isempty(target)
target = waypoints(1,:); % initializes the first waypoint.
end
matchedrow = find(all(waypoints == target, 2), 1); %find the first row that match
if isempty(matchedrow) %no row found!
error('could not find target in the waypoints');
end
if d2w > accuracy
matchedrow = matchedrow + 1; % if target waypoint is reached, add one to index.
end
targetnew = waypoints(min(end, matchedrow), :); %make sure we don't index past the last waypoint (but shouldn't that be an error?)
end
Note that I don't use Simulink. While the above guarantees that by the end of the function targetnew is always 1 row, I don't know if it's enough to make simultink happy.

댓글을 달려면 로그인하십시오.


Steven Lord
Steven Lord 2019년 2월 28일
What in your code guarantees that idx is a scalar?
Could it be a vector? No, given your waypoints matrix it can't.
Could it be empty? What is the size of targetnew if it is?

카테고리

Help CenterFile Exchange에서 Computer Vision with Simulink에 대해 자세히 알아보기

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by