Saturday, July 14, 2012

Postdoc position in virtual testing of advanced automotive safety systems

Halmstad University has an immediate opening for a postdoctoral associate in virtual testing of advanced automotive safety systems. Virtual testing involves extensive use of high-fidelity modeling and simulation methods.  The successful applicant will work within the project Next Generation Test Methods for Active Safety Functions, funded by Sweden’s Innovation Agency VINNOVA under the Strategic Vehicle Research Partnership FFI.

The description of work for the advertised position is to:

  • Develop and experimentally validate a series of increasingly sophisticated mathematical models as relevant to the automated testing of future advanced driver assistance systems (ADAS). Aspects of interest include vehicle dynamics, sensors (GPS, radar, ladar), real-time communication services (V2V, V2I), road conditions, drivers, dependability, and test scenarios.
  • Evaluate existing support for experimental validation of mathematical models using empirically gathered data and statistical methods
  • Evaluate the convenience and fidelity of various modeling and simulation tools for performing virtual experiments during research and development of ADAS, in particular during the early stages of design and requirement specification.
  • Document the results in a technical report valuable to the industrial project partners and establish a suitable basis for a journal paper on the scientific contributions. Depending on the pace of progress, publication in an appropriate journal.

The position is for one year, with a salary in the range of SEK 30’000 to 33’000 per month. Depending on the performance of the successful applicant, there will be opportunities for continued employment within upcoming projects. More details about the project can be found on here and further inquiries can be addressed to Roland Philippsen, Tony Larsson, Walid Taha, or Magnus Jonsson at firstname.lastname@hh.se.

To apply to the position, please send in all application materials as one PDF file attached to an email addressed to registrator@hh.se.  The title of the email must be “Application to NG-Test Postdoc (Position number 6/12)”.  The PDF file must consist of 1) a cover letter stating the reasons for interest in this position, and long term career goals, 2) CV or resume, 3) list of references, 4) examples of published or thesis work, and 5) Copy of PhD degree.


Applications will be processed on a first-come first serve basis. Priority will be given to applications arriving before September 15th, 2012.

Thursday, February 2, 2012

A Model of a Ping Pong Game

Last year in the programming languages course at Halmstad University, students worked in groups to develop different parts of a ping pong game.  Later, Yingfu Zeng combined these projects into one model that streamlined these components and further developed below.  The result is what you find below in the rest of this post.

The model below was used in the first tournament in cyber physical systems course.  Out of seven entries, the winning entry was team Virtue by Victor Vasilev and Carlos Fuentes.  The winning entry was able to score 7.5 out of a maximum of 12 possible points.   The benchmark model, team WiffWaff by Adam Duracz and Yingfu Zeng, shows that it is possible to score 11 out of 12 points.

NEW!  Check out the videos and analysis!


/**
* Program:   3-D ping pong 
* Author :   Yingfu Zeng, Walid Taha
* Date   :   2012/02/11
* License:   BSD, GPL(V2), or other by agreement with Walid Taha
**/
class Ball ()
 private
  mode = "Fly";
  k_z  = [1,1,-0.99];       // Coefficient of restitution
  k2   = 1/6;               // Coefficient of the air resistance
  p    = [0,0,0.5];         // Position of the ball
  p'   = [5,1,-3];
  p''  = [0,0,0];
  _3D  = ["Sphere",[0,0,0.5],0.03,[1,1,1],[0,0,0]];
 end
 _3D [=] ["Sphere",p,0.03,[1,1,1],[0,0,0]];
 // Valid modes
 if mode ~= "Fly" && mode ~= "Bounce" && mode ~= "Freeze"
   mode = "Panic!";
 end;
 switch mode
  case "Fly"
   if dot(p,[0,0,1]) < 0 && dot(p',[0,0,1])< 0
    mode = "Bounce";
   else
    p'' [=] -k2 * norm(p') * p' + [0,0,-9.8];
   end;
  case "Bounce"
    p'   =  p' .* k_z;    // Bouncing  will lose some energy
    mode = "Fly";
  case "Freeze"           // The ball becomes red to show what is going wrong
    p'  [=] [0,0,0]; p'' [=] [0,0,0];
    _3D [=] ["Sphere",p,0.03,[1,0,0],[0,0,0]];
  case "Panic!"
  end
end




class BatActuator(p1)   
 private
  p       = p1;
  p'      = [0,0,0];
  angle   = [0,0,0];
  energy  = 0;
  energy' = 0;  
 end
  if norm(p') > 5
   p' = p'/norm(p') * 5 ;
  end;
  energy' [=] norm(p'); 
end




class Bat(n,p1)
 private
  p     = p1;
  p'    = [0,0,0];
  angle = [0,0,0.1];
  displayAngle = [0,0,0];
  mode  = "Run";
  _3D   = ["Cylinder",p1,[0.15,0.05],[0.1,0.1,0.1],[0,0,0.5]];
 end
 switch mode 
  case "Run"
   if n == 2
     displayAngle  [=] [0,dot(angle,[0,0,1])*(3.14/2)/norm(angle),
                      dot(angle,[0,1,0])*(3.14/2)/norm(angle)]+[0,0,3.14/2];
    _3D            [=] ["Cylinder",p+[0.05,0,0],[0.15,0.05],
                        [0.1,0.1,0.1],displayAngle];
   else
      displayAngle [=] [dot(angle,[0,0,1])*(3.14/2),0,
                    dot(angle,[0,1,0])*(3.14/2)]+[0,0,3.14/2];
     _3D           [=] ["Cylinder",p+[-0.05,0,0],[0.15,0.05],
                        [1,0.1,0.1],-1 * displayAngle];
 end;
  case "Rest"
    p'            [=] [0,0,0];
 _3D           [=] ["Box",p+[-0.05,0,0],[0.3,0.3,0.3],
                        [1,1,0.1],-1 * displayAngle];
 end
end




/**
*Position and velocity of ball(ballp,ballv) always provided estimately;
*Once player decides to hit the ball, change the hit variable to true,
*the Game class will notice and caculate the output velocity of the ball.
**/
class Player(n)
 private
  mode      = "Wait";
  bounced   = false;       // Tell whether the ball bounced or not
  serve = false;           // The Game class will set serve flag to true 
  hit   = false;           // when it's your turn
  count = 0;
  ballv = [0,0,0];
  ballp = [0,0,0];
  batp  = [1.6,0,0.2];
  v     = [0,0,0];         // Bat's speed 
  batAngle   = [0,0,0.1];  // Normal vector of the bat's plane
  batAngle'  = [0,0,0];
  // Player(1) starts at [-1.6,0,0.2], Player(2) starts at [1.6,0,0.2]
  startPoint = [1.6*(-1)^n,0,0.2]; 
  t   = 0;
  t'  = 1;
 end
 if mode ~= "Wait" && mode ~= "Prepare" && mode ~= "Hit"
   mode = "Panic!";
 end;
 t'  [=] 1;
 switch mode
  case "Wait"               // While waiting, moving the bat to starting point
   count      = 0;
   if n == 1 
     v         [=] startPoint-batp;
   else
     v         [=] startPoint + [0,0.75,0] - batp;
   end;
   batAngle' [=] [0,0,0]-batAngle;
   hit    = false;
   if serve == true
    mode    = "Prepare";
    bounced = false;
   else
    mode = "Wait";
   end;
  case "Prepare"             // Prepare to hit the ball
   if bounced == true        // After the ball has bounced,
                             // start moving the bat towards the ball
     v [=] (ballp-batp).*[0,20,0] + (ballp-batp).*[0,0,25] +
           (ballp+[0.12*(-1)^n,0,0]-batp).*[25,0,0];
     if norm(batp - ballp)<0.15 && abs(dot(ballp,[1,0,0])) >= 
                               abs(dot(startPoint,[1,0,0]))
      count = count+1;
      mode  = "Hit";
     end;
   end;
   // When the ball has bounced and it is at the highest position
   if count > 0 && dot(ballv,[0,0,1]) < 0.1 && bounced == true  
    mode = "Hit";     // This player decide to hit.
   end;
   if dot(ballp,[0,0,1]) < 0 && bounced == false
    bounced = true;
   end;
   if(serve ~= true)
     mode = "Wait";
   end;
 case "Hit"           // Decide how you want hit the ball, 
  if n == 2
   if(t<1||t>5)       // you may want to check the formulas 
                      // in the BallActuator() class
    v        = [-1.38,0.40,1.2];
    batAngle = [0.9471,0.25,-0.2];
   else
    if t > 4 && t < 5
     v        = [-0.88,-0.5,0.2];
     batAngle = [0.9471,0.25,-0.2];
 else
     v        = [-1.7,-0.2,3.86];
     batAngle = [0.96,-0.1,-0.2258];
 end;
   end;  
  else
   if(dot(ballv,[0,1,0]) < 0)
    v        = [0.1,-0.15,3.85];
    batAngle = [-0.938,-0.162,-0.29];
   else
    v        = [1,0,2.85];
    batAngle = [-0.938,0.202,-0.29];
    end;
   end;
  serve  = false;
  hit    = true;
  mode   = "Wait";
 case "Panic!"
 end
end




class Table()   // The table
 private
                // Table
 _3D = [["Box", [0,0,-0.05],[3,1.5,0.03],[0.1,0.1,1.0],[0,0,0]],
                // TableBases 1~4 
        ["Box", [-1.4,0.6,-0.3-0.04], [0.05,0.05,0.6], [0.8,0.8,0.8],[0,0,0]], 
        ["Box", [-1.4,-0.6,-0.3-0.04], [0.05,0.05,0.6], [0.8,0.8,0.8],[0,0,0]],
        ["Box", [1.4,-0.6,-0.3-0.04], [0.05,0.05,0.6], [0.8,0.8,0.8],[0,0,0]],
        ["Box", [1.4,0.6,-0.3-0.04], [0.05,0.05,0.6], [0.8,0.8,0.8],[0,0,0]],
          // Net
        ["Box", [0,0,0.125-0.02], [0.05,1.5,0.25], [0.2,0.8,0.2],[0,0,0]], 
                 // MiddleLine  
  ["Box", [0,0,0],[3,0.02,0.02-0.02],[1,1,1],[0,0,0]]]           
 end
end




class BallActuator()  // Calculate result of impact
  private
   mode="Initialize";
   v1 = [0,0,0];      // Input ball speed
   v2 = [0,0,0];      // Output ball speed
   v3 = [0,0,0];      // Bat's speed during the impact
   angle = [0,0,0];   // Bat's normal vector
   done  = false;
   action = 0;
 end
  if mode ~= "Initialize" && mode ~= "Calculate" && mode ~= "Wait"
   mode = "Panic!";
  end;
 switch mode
  case "Initialize"
   done[=]false;
   if action == 1
    mode = "Calculate";
   end;
 case "Calculate"
  v2     = v1-dot(2.*(v1-v3),angle)*angle;
  action = 0;
  if action == 0
   mode = "Wait";
  end;
 case "Wait"
  done [=] true;
 case "Panic!"
 end
end




// Sample the velocity of the ball and feed back to the players.
class BallObserver()  
 private
  mode = "Sample";
  p  = [0,0,0];
  v  = [0,0,0];
  pp = [0,0,0];
  ap = [0,0,0];
  t  = 0;
  t' = 1;
 end
 t'[=]1;
 if mode ~= "Sample" && mode ~= "Estimate0" && mode ~= "Estimate1"
  mode = "Panic!";
 end;
 switch mode
   case "Sample"
    if t > 0
     pp  = p;
     t   = 0;
     mode= "Estimate0"
    end;
   case "Estimate0"
 if t == 0.01   // Calculate the average speed
     ap   = p;
     mode = "Estimate1";
    end;
   case "Estimate1"
    v    = dot((ap-pp),[1,0,0])/0.01*[1,0,0]+dot((ap-pp),[0,0,1])/0.01*[0,0,1]+
        dot((ap-pp),[0,1,0])/0.01*[0,1,0];
    mode = "Sample";
    t    = 0;
   case "Panic!"
  end
end




class Referee()  // This class will monitors the whole process of the game.
 private
  mode="Initialize";
  x = 0;x' = 0;
  z = 0;z' = 0;
  y = 0;
  t = 0;t' = 1;
  player1Score = 0;
  player2Score = 0;
  serveNumber  = 2;
  lastHit      = 0;
  reason       = "Nothing";
  checked      = false;    // For the net checking
  bounced      = false;
  restart      = 0;        // Tell the Game to restart
  acknowledged = 0;        // Check if the Game class has received 
                           //  the restart signal
  bounceTime   = 0;
  status       = "Normal"
 end
 if mode ~= "Initialize" && mode ~= "Player1Lost" && mode ~= "Player2Lost" 
    && mode ~= "SendMessage" && status ~= "Normal" && reason ~= "Nothing"
    && status ~= "Report" && reason ~= "BallOutOfBoundary"
 && reason ~= "BallBouncedTwice" && reason ~= "BallTouchNet"
  mode = "Panic!";
 end;
  t'[=]1;
  if z<0.05 && z'<0 && status == "Normal"  // Check if anyone fouls
   if (abs(y)>0.78||abs(x)>1.53) && status == "Normal"
    reason     = "BallOutOfBoundary";
    if bounced == false
     if x>0
      mode = "Player1Lost";
     else
      mode = "Player2Lost";
     end;
    else
     if bounced == "YesIn2"    // The ball has bounced in player2's court, 
      mode = "Player2Lost"     // and out of boundary now, so player2 lose.
     end;
     if bounced == "YesIn1"
      mode = "Player1Lost";
     end;
    end;
    status = "Report";
   end;
   if(abs(y)<0.78 && abs(x)<1.53) && bounced ~= false  
      && t>(bounceTime+0.1) && status=="Normal"
 // The ball has bounced twice in player2's court  
    if bounced == "YesIn2" && x > 0 
     mode   = "Player2Lost";
     reason = "BallBouncedTwice";
bounceTime = t;
    end;
 // The ball has bounced twice in player1's court
    if bounced == "YesIn1" && x < 0 
     mode   = "Player1Lost";
     reason = "BallBouncedTwice";
bounceTime = t;
    end;
   end;
   if x<0 && x>-1.5 && bounced == false && status == "Normal"
    bounced    = "YesIn1";
    bounceTime = t;
   end;
   if x>=0 && x<1.5 && bounced == false && status == "Normal"
    bounced    = "YesIn2";
    bounceTime = t;
   end;
 end;




 if bounced == "YesIn1" && x>0 && status == "Normal"
  bounced = false
 end;
 if bounced == "YesIn2" && x<=0 && status == "Normal"
  bounced = false
 end;
  // Time to check if the ball touches the net
 if abs(x)<0.025 && t>0.1 && checked == false && status == "Normal"   
  if z<0.25
    if x'>0
     mode   = "Player1Lost";
    else
     mode   = "Player2Lost"
    end;
    reason  = "BallTouchNet";
    checked = true;
  end;
 end;
switch mode
 case "Initialize"
 case "Player1Lost"
  player2Score = player2Score+1;
  mode = "SendMessage";
 case "Player2Lost"
  player1Score = player1Score+1;
  mode = "SendMessage";
 case "SendMessage"
  t = 0; // Wait until the Game class gets the restart signal
  restart = 1;
  if acknowledged == 1
    mode = "Initialize";
    acknowledged = 0;
    restart = 0;
    status  = "Normal";
    checked = false;
    bounced = false;
  end;
  case "Panic!"
 end
end




/**
* The parent of all the other classes, who controls the
* whole process of the game.
**/
class Game ()
 private
  ball    = create Ball ();
  ballob  = create BallObserver();
  actuator= create BallActuator();
  batActuator1 = create BatActuator([-1.6,0,0.2]);
  batActuator2 = create BatActuator([1.6,0,0.2]);
  player1 = create Player(1);
  player2 = create Player(2);
  bat1    = create Bat(1,[-1.6,0,0.2]);
  bat2    = create Bat(2,[1.6,0,0.2]);
  table   = create Table();
  gameMonitor = create Referee();
  mode    = "Player2Serve";       // Player2 starts first
  player2Score = 0;
  player1Score = 0;
  serveNumber  = 2;
  t  = 0;
  t' = 1;
  maxEnergy    = 18;
 end
  if mode ~= "Restart" && mode ~= "Player1Serve" && mode ~= "Player2Serve" 
  && mode ~= "Impact"  && mode ~= "Freeze" && mode ~= "ChangeSide"
  && mode ~= "Act"
   mode = "Panic!"
  end;
  t'[=]1;
  gameMonitor.x  [=] dot(ball.p,[1,0,0]);
  gameMonitor.x' [=] dot(ball.p',[1,0,0]);
  gameMonitor.z  [=] dot(ball.p,[0,0,1]);
  gameMonitor.z' [=] dot(ball.p',[0,0,1]);
  gameMonitor.y  [=] dot(ball.p,[0,1,0]);
  gameMonitor.serveNumber [=] serveNumber;
  player1Score  [=] gameMonitor.player1Score;
  player2Score  [=] gameMonitor.player2Score;
  ballob.p          [=] ball.p;
  player1.ballp     [=] ballob.p;
  player2.ballp     [=] ballob.p;  
  player1.ballv     [=] ballob.v;
  player2.ballv     [=] ballob.v;
  if bat1.mode ~= "Rest"
   batActuator1.p' [=] player1.v;
  end;
  if bat2.mode ~= "Rest"
   batActuator2.p' [=] player2.v;
  end;
  player1.batp  [=] bat1.p;
  player2.batp  [=] bat2.p;
  batActuator1.angle [=] player1.batAngle;
  batActuator2.angle [=] player2.batAngle;
  bat1.p  [=] batActuator1.p;
  bat1.p' [=] batActuator1.p';
  bat2.p  [=] batActuator2.p;
  bat2.p' [=] batActuator2.p';
  bat1.angle [=] batActuator1.angle;
  bat2.angle [=] batActuator2.angle;
  if batActuator1.energy > maxEnergy
     bat1.mode = "Rest";
 bat1.p'   = [0,0,0];
 batActuator1.p' [=] [0,0,0];
  end;
  if batActuator2.energy > maxEnergy
     bat2.mode = "Rest";
 bat2.p'   = [0,0,0];
 batActuator2.p' [=] [0,0,0];
  end; 
 switch mode
  case "Restart" // Put everything back to the starting point
   ball.p            = [0,0,0.5];
   ball.p'           = [5,1,-3];
   bat2.p            = [1.6,0,0.2];
   player2.batp      = [1.6,0,0.2];
   player2.v         = [0,0,0];
   player2.batAngle  = [0.01,0,0];
   player2.bounced   = false;
   player2.ballp     = [1.6,0,0.2];
   bat1.p            = [-1.6,0,0.2];
   player1.batp      = [-1.6,0,0.2];
   player1.v         = [0,0,0];
   player1.batAngle  = [0.01,0,0];
   player1.bounced   = false;
   player1.ballp     = [-1.6,0,0.2];
   batActuator1.p    = [-1.6,0,0.2];
   batActuator2.p    = [1.6,0,0.2];
   serveNumber       = 2;
   gameMonitor.bounced      = false;
   gameMonitor.checked      = false;
   gameMonitor.acknowledged = 1;
   mode         = "Player2Serve";
   player1.mode = "Wait";
   player2.mode = "Wait";
  case "Player2Serve" // Player 2 is serving
   player1.serve [=] false;
   player2.serve [=]  true;
   if player2.hit == true && norm(bat2.p - ball.p) < 0.15
    mode = "Impact"
   end;
   if gameMonitor.restart == 1
    mode = "Freeze";
    t    = 0;
   end;
 case "Player1Serve" // Player 1 is serving
  player2.serve [=] false;
  player1.serve [=] true;
  if player1.hit == true && norm(bat1.p - ball.p) < 0.15
   mode = "Impact"
  end;
  if gameMonitor.restart == 1
   mode = "Freeze";
   t    = 0;
  end;
 case "Impact" // When one player hits the ball
  actuator.v1 = ball.p';
  if serveNumber == 2 // Give player2's data to actuator
   batActuator2.p' = player2.v;
   bat2.p'         = batActuator2.p';
   actuator.v3     = bat2.p';
   bat2.angle      = player2.batAngle;
   actuator.angle  = bat2.angle;
   actuator.action = 1; // Tell actuator to act
   gameMonitor.lastHit = 2;
   mode = "Act";
    if gameMonitor.restart == 1
      mode = "Freeze";
      t = 0;
    end;
  end;
  if serveNumber == 1 // Give player1's data to actuator
   batActuator1.p' = player1.v;
   bat1.p'         = batActuator1.p';
   actuator.v3     = bat1.p';
   bat1.angle      = player1.batAngle;
   actuator.angle  = bat1.angle;
   actuator.action = 1; // Tell actuator to act
   gameMonitor.lastHit = 1;
   mode = "Act";
   if gameMonitor.restart == 1
    mode = "Freeze";
    t    = 0;
   end;
  end
 case "Act" // Wait till actuator finish
  if gameMonitor.restart == 1
   mode = "Freeze";
   t    = 0;
  end;
  if actuator.done == true
   ball.p'       = actuator.v2;
   actuator.mode = "Initialize";
   mode          = "ChangeSide";
  end;
 case "ChangeSide" // Change the serve number
  if gameMonitor.restart == 1
   mode = "Freeze";
   t    = 0;
  end;
  if serveNumber == 2 && dot(ball.p,[1,0,0]) >0 && gameMonitor.restart ~= 1
   serveNumber     = 1;
   mode            = "Player1Serve";
   player1.mode    = "Wait";
   player1.bounced = false;
  end;
  if serveNumber == 1 && dot(ball.p,[1,0,0]) <= 0 && gameMonitor.restart ~= 1
   serveNumber     = 2;
   mode            = "Player2Serve";
   player2.mode    = "Wait";
   player2.bounced = false;
  end; 
 // When someone fouls, showing what's going wrong for 1 second
 case "Freeze"          
   if t<1
    ball.mode = "Freeze";
   else
    mode      = "Restart";
    ball.mode = "Fly";
   end;
 case "Panic!"
 end
end




class Main(simulator)
 private
  mode = "Initialize";
 end
switch mode
 case "Initialize"
  simulator.endTime = 20;
  create Game();
  mode = "Persist";
 case   "Persist"
 end
end