What is causing dimension 1 to vary?
1 次查看(过去 30 天)
显示 更早的评论
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].
0 个评论
回答(2 个)
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 个评论
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
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?
0 个评论
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Computer Vision with Simulink 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!