Related to the optimization of the control parameters of physics simulation, I'm trying to form an intuition about the properties of the related fitness function landscapes. It's impossible to accurately visualize the landscapes of high-dimensional biped motor control and planning problems, but here's a simple 2d physics example: throwing a ball in 2d with the angle and speed as the optimized variables, and allowing damped rebounds from the ground so that the ball trajectory is not just a simple parabola. This isn't exactly rocket science, but I wrote the code to as an exercise in interactive visualization in Matlab, which I stopped using while working outside Aalto.
It was my first time I tried to do implement the "up and down the ladder of abstraction", that is, letting the user explore a summary view (the fitness landscape) to browse concrete examples (the ball trajectories). There was some non-intuitive searching for the right places to put the getCursorInfo(), pause() and subplot() commands to prevent the display from freezing - hope this helps if anyone wants to do the same. I also tried to implement the UI using Matlab's linked data, but couldn't get the display refreshed.
Edit 29.1.2013: I was asked why there's peaks where there should be a continuous ridge. It's apparently because of the large timestep that causes a simulation error that varies as a function of how the floor contacts align with the timestep grid. It also depends on how the contact handling is implemented. The Matlab code below uses a smaller timestep and produces a more continuous ridge.
Here's the Matlab code:
minVel=1;
maxVel=5.0;
minAngle=-0.5*pi;
maxAngle=0.5*pi;
timeStep=0.02;
nSteps=100;
startPos=[0,1.5];
velSteps=64;
angleSteps=64;
E=zeros(velSteps,angleSteps);
target=[2, 0.5];
curve=zeros(nSteps,2);
curves=zeros(nSteps,2,velSteps,angleSteps);
%step over all ball launch speed and angle combinations
for velStep=0:velSteps,
speed=minVel+(maxVel-minVel)*velStep/velSteps;
for angleStep=0:angleSteps,
angle=minAngle+(maxAngle-minAngle)*angleStep/angleSteps;
pos=startPos;
vel=[speed*cos(angle), speed*sin(angle)];
closestDist=10000;
closest=[0; 0];
closestTime=0;
%simulate the ball trajectory for this launch velocity
for n=1:nSteps,
%save this trajectory point
curve(n,:)=pos;
%update closest to target
dist=norm(pos-target,2);
if (dist<closestDist)
closestDist=dist;
closest=pos;
closestTime=n*timeStep;
end
%physics update
pos=pos+vel*timeStep;
vel(2)=vel(2)-9.81*timeStep;
%bounce from floor
if (pos(2)<0 && vel(2)<0)
timeInsideGround=pos(2)/vel(2);
vel(2)=-0.7*vel(2);
timeAfterBounce=max(0,timeStep-timeInsideGround);
pos(2)=timeAfterBounce*vel(2);
end
end
%store the whole trajectory
curves(:,:,velStep+1,angleStep+1)=curve;
%update fitness
distanceThreshold=0.1;
fitness=0.5+0.5*tanh(-(closestDist-distanceThreshold)/0.05);
%soft threshold for hitting time
timeThreshold=1;
fitness=fitness*(0.5+0.5*tanh(-(closestTime-timeThreshold)/0.05));
%store fitness function value for these params
E(velStep+1,angleStep+1)=fitness;
end
end
%plot the fitness surface
subplot(1,2,1);
surf(E);
%get the handle for querying data cursor info about the fitness
h=gcf;
dcm_obj = datacursormode(h)
%plot a trajectory of the ball
subplot(1,2,2);
curve=curves(:,:,1,1);
plot(curve(:,1),curve(:,2));
%in a loop, keep plotting the ball trajectories
pause on;
while 1
info_struct = getCursorInfo(dcm_obj);
if size(info_struct)~=0
curve=curves(:,:,floor(info_struct.Position(2)),floor(info_struct.Position(1)));
subplot(1,2,2);
plot(curve(:,1),curve(:,2));
axis([0 4.5 0 3])
hold on;
plot(target(1),target(2),'c+:')
hold off;
end
%have to pause to let the display refresh
pause(0.01);
end