views:

77

answers:

2

I have 4 files and the code 'works' as expected.

I try to clean everything up, place code into functions, etc... and everything looks fine... and it doesn't work. Can somebody please explain why MatLab is so quirky... or am I just stupid?

Normally, I type

terminator = simulation(100,20,0,0,0,1);
terminator.animate();

and it should produce a map of trees with the terminator walking around in a forest. Everything rotates to his perspective.

When I break it into functions... everything ceases to work.

I really only changed a few lines of code, shown in comments.

Code that works:

classdef simulation
properties
    landmarks
    robot
end

methods
    function obj = simulation(mapSize, trees, x,y,heading,velocity)
        obj.landmarks = landmarks(mapSize, trees);
        obj.robot = robot(x,y,heading,velocity);
    end
    function animate(obj)
        %Setup Plots
        fig=figure;
        xlabel('meters'), ylabel('meters')
        set(fig, 'name', 'Phil''s AWESOME 80''s Robot Simulator')
        xymax = obj.landmarks.mapSize*3;
        xymin = -(obj.landmarks.mapSize*3);
        l=scatter([0],[0],'bo');
        axis([xymin xymax xymin xymax]);
        obj.landmarks.apparentPositions
        %Simulation Loop  THIS WAS ORGANIZED
        for n = 1:720,
            %Calculate and Set Heading/Location
            obj.robot.headingChange = navigate(n);

            %Update Position
            obj.robot.heading = obj.robot.heading + obj.robot.headingChange;
            obj.landmarks.heading = obj.robot.heading;
            y = cosd(obj.robot.heading);
            x = sind(obj.robot.heading);     
            obj.robot.x = obj.robot.x + (x*obj.robot.velocity);
            obj.robot.y = obj.robot.y + (y*obj.robot.velocity);
            obj.landmarks.x = obj.robot.x;
            obj.landmarks.y = obj.robot.y;

            %Animate
            set(l,'XData',obj.landmarks.apparentPositions(:,1),'YData',obj.landmarks.apparentPositions(:,2));
            rectangle('Position',[-2,-2,4,4]);
            drawnow
        end
    end
end
end

-----------
classdef landmarks
properties
    fixedPositions  %# positions in a fixed coordinate system. [ x, y ]
    mapSize = 10;  %Map Size.  Value is side of square
    x=0;
    y=0;
    heading=0;
    headingChange=0;
end
properties (Dependent)
    apparentPositions
end
methods
    function obj = landmarks(mapSize, numberOfTrees)
        obj.mapSize = mapSize;
        obj.fixedPositions = obj.mapSize * rand([numberOfTrees, 2]) .* sign(rand([numberOfTrees, 2]) - 0.5);
    end
    function apparent = get.apparentPositions(obj)
        %-STILL ROTATES AROUND ORIGINAL ORIGIN
        currentPosition = [obj.x ; obj.y];
        apparent = bsxfun(@minus,(obj.fixedPositions)',currentPosition)';
        apparent = ([cosd(obj.heading)  -sind(obj.heading) ; sind(obj.heading)  cosd(obj.heading)] * (apparent)')';
    end
end
end

----------
classdef robot

properties
    x
    y
    heading
    velocity
    headingChange
end

methods
    function obj = robot(x,y,heading,velocity)
        obj.x = x;
        obj.y = y;
        obj.heading = heading;
        obj.velocity = velocity;
    end
end
end

----------
function headingChange = navigate(n)
%steeringChange = 5 * rand(1) * sign(rand(1) - 0.5); Most chaotic shit
%Draw an S
if n <270
    headingChange=1;
elseif n<540
    headingChange=-1;
elseif n<720
    headingChange=1;
else
    headingChange=1;
end
end

Code that does not work...

classdef simulation
properties
    landmarks
    robot
end

methods
    function obj = simulation(mapSize, trees, x,y,heading,velocity)
        obj.landmarks = landmarks(mapSize, trees);
        obj.robot = robot(x,y,heading,velocity);
    end
    function animate(obj)
        %Setup Plots
        fig=figure;
        xlabel('meters'), ylabel('meters')
        set(fig, 'name', 'Phil''s AWESOME 80''s Robot Simulator')
        xymax = obj.landmarks.mapSize*3;
        xymin = -(obj.landmarks.mapSize*3);
        l=scatter([0],[0],'bo');
        axis([xymin xymax xymin xymax]);
        obj.landmarks.apparentPositions
        %Simulation Loop
        for n = 1:720,
            %Calculate and Set Heading/Location

            %Update Position
            headingChange = navigate(n); 
            obj.robot.updatePosition(headingChange); 
            obj.landmarks.updatePerspective(obj.robot.heading, obj.robot.x, obj.robot.y);

            %Animate
            set(l,'XData',obj.landmarks.apparentPositions(:,1),'YData',obj.landmarks.apparentPositions(:,2));
            rectangle('Position',[-2,-2,4,4]);
            drawnow
        end
    end
end
end

-----------------
classdef landmarks
properties
    fixedPositions;  %# positions in a fixed coordinate system. [ x, y ]
    mapSize;  %Map Size.  Value is side of square
    x;
    y;
    heading;
    headingChange;
end
properties (Dependent)
    apparentPositions
end
methods
    function obj = createLandmarks(mapSize, numberOfTrees)
        obj.mapSize = mapSize;
        obj.fixedPositions = obj.mapSize * rand([numberOfTrees, 2]) .* sign(rand([numberOfTrees, 2]) - 0.5);
    end
    function apparent = get.apparentPositions(obj)
        %-STILL ROTATES AROUND ORIGINAL ORIGIN
        currentPosition = [obj.x ; obj.y];
        apparent = bsxfun(@minus,(obj.fixedPositions)',currentPosition)';
        apparent = ([cosd(obj.heading)  -sind(obj.heading) ; sind(obj.heading)  cosd(obj.heading)] * (apparent)')';
    end
    function updatePerspective(obj,tempHeading,tempX,tempY)
        obj.heading = tempHeading;
        obj.x = tempX;
        obj.y = tempY;
    end
end
end

-----------------
classdef robot

properties
    x
    y
    heading
    velocity
end

methods
    function obj = robot(x,y,heading,velocity)
        obj.x = x;
        obj.y = y;
        obj.heading = heading;
        obj.velocity = velocity;
    end
    function updatePosition(obj,headingChange)
        obj.heading = obj.heading + headingChange;
        tempy = cosd(obj.heading);
        tempx = sind(obj.heading);     
        obj.x = obj.x + (tempx*obj.velocity);
        obj.y = obj.y + (tempy*obj.velocity);  
    end
end
end

The navigate function is the same...

I would appreciate any help as to why things aren't working.

All I did was take the code from the first section from under comment: %Simulation Loop THIS WAS ORGANIZED and break it into 2 functions. One in robot and one in landmarks.

Is a new instance created every time because it's constantly printing the same heading for this line int he robot class obj.heading = obj.heading + headingChange;

+1  A: 

Replace your definitions with:

classdef landmarks <handle 
classdef robots <handle

Then have a look at: http://www.mathworks.com/access/helpdesk/help/techdoc/matlab_oop/brfylq3.html

hash blue
Made those two simple changes and now:Non-singleton dimensions of the two input arrays must match each other Error in ==> landmarks>landmarks.get.apparentPositions at 21 apparent = bsxfun(@minus,(obj.fixedPositions)',currentPosition)';Matlab seems ridiculously quirky coming from c++.
pinnacler
I have no idea why things started working, they did. Typical Matlab... or me.
pinnacler
+1  A: 

I'll give you an explanation.

By default, when you call a method on a MATLAB object, the framework creates a copy of the object and calls the method on this copy. This is a completely different paradigm to C++. In C++, when you call an object's method, you are calling the method on a reference to that object instance.

So, when you call

obj.robot.updatePosition(headingChange);

It is creating a new copy of the robot object, and calling updatePosition on this copy. The state of the original robot remains unchanged.

An alternative to using handles is to code like this:

obj.robot = obj.robot.updatePosition(headingChange);

The other approach is to make che class inherit from handle. In this case, every copy operation copies a reference to the class, not an instance, which is why the update functions change the actual objects state.

Andrew Shepherd