![]() |
Web Development »
Applications & Tools »
Tools with source code
Advanced
License: A Public Domain dedication
2D LUA Based Robot SimulatorBy auraliusAn article on designing your own robot simulator |
VC6, Windows, MFC, GDI, VS2008, Dev
|
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||
Here I would like to introduce a self-made 2D robot simulator. With this simulator, we can design how a robot will navigate in a 2D world by using a set of rules that we design. The rules are designed by using Lua script. For the world editor, we use GDI Device Context programming. Here are the overall features:
A little knowledge in Lua is necessary. You can check Lua website.
The robot that we have here is a wheeled robot. It has two wheels. It navigates with a differentially steered drive system. Differentially steered drive system is like a wheeled chair. Steering a wheeled chair can be done by varying the speed of its wheels. If one wheel is rotating faster, the wheeled chair will make a curved path. If both wheels are on the same speed, it will make a straight path.
I am not good at math. It gives me quite a headache. Better you check on G.W. Lucas tutorial. Let's make it simple. Here are the equations that I am using to model differential steering behaviour.
Now if the left wheel and the right wheel are at the same speed? The equation above cannot be implemented since it will result in division by zero error. Using L'Hospital's rule, it can be shown that the equation has limits approaching straight line (check again on G.W. Lucas tutorial). So, when the left wheel and the right wheel are at the same speed, use this equation. Please notice that dx/dt means the difference between current x position and previous x position.
![]()
To get the current position of the robot, we only need to input time, left wheel speed and right wheel speed to the equation above. Robot angle is something that we also need to calculate. Here is the equation to calculate the robot angle.
Finally, here is the implementation code of those equations:
void CRobot::goRobotGo(double *t){
if (canResetTime){
*t = 0;
canResetTime = false;
}
int plusFactor = m_robot.rWheelSpeed + m_robot.lWheelSpeed;
int minusFactor = m_robot.lWheelSpeed - m_robot.rWheelSpeed;
if (m_robot.lWheelSpeed - m_robot.rWheelSpeed != 0.0){
m_robot.pos.x = m_puos0.x + m_robot.size / 2 * plusFactor / minusFactor /
2 *(sin(minusFactor * (*t) / m_robot.size / 2 + m_robot.theta)
- sin(m_robot.theta));
m_robot.pos.y = m_pos0.y - m_robot.size / 2 * plusFactor / minusFactor /
2 *(cos(minusFactor * (*t) / m_robot.size / 2 + m_robot.theta)
- cos(m_robot.theta));
m_robot.theta = m_theta0 + minusFactor * (*t) / m_robot.size ;
}
else{
m_robot.pos.x = plusFactor / 2 * cos(m_robot.theta) * (*t) + m_pos0.x;
m_robot.pos.y = plusFactor / 2 * sin(m_robot.theta) * (*t) + m_pos0.y;
}
}
All things related to the robot are put in class CRobot in file Robot.h and Robot.cpp.
The world editor is simply an implementation of GDI device context programming. We use simple graphs such as rectangle, ellipse, and line to create rooms and obstacles. With a little math, we can make those graphs selectable, moveable, and resizable. This world editor is based on my own previous work. I know it is very simple and also not good since I received several bad responses on it. I will make it better if I have time. All things related to the world editor are in CCanvas in files Canvas.h and Canvas.cpp.
For the code editor, I use Scintilla library. With Scintilla library, we can make an editor that supports syntax colorization easily. I learned about this library from an article I found on CodeProject. Check here and here. All things related to the world editor are in the file EditorDlg.h and EditorDlg.cpp.
Lua is a very nice programming language. It is a light-weight, small footprint programming language designed for extending applications. Here I embed four C++ functions to Lua by using Lua script C++ wrapper created by RhicadS. Lua is a very nice programming language. It is a light-weight, small footprint programming language designed for extending applications.
initsensor() accepts nothing; returns nothing. You must issue at the very beginning of your code. readsensor(int index) accepts sensor index; returns measured distance. setspeed(int left, int right) accepts left and right wheel speed; returns nothing. getangle() accepts nothing; returns current angular position of the robot (in radians). debug(char *msg) accepts message to be displayed on log; returns nothing. debug(char *msg or function) accepts message or another function to be displayed on log; returns nothing. You can display code editor window by clicking View >> Editor or by clicking View code editor on toolbar. Output log is where all error and debug messages are displayed. It can be loaded from menu View >> Output Log or View output log on toolbar. A world file is saved with *.wrl extension while code file is saved with *.lua extension. Loading and saving them are done separately.
Let's try. First draw a big ellipse on the world editor. Then drag the robot so that the right side of the robot is close to the inner side of the ellipse. Load code editor and paste the following code. Run the simulation. When the robot disappears, click menu Robot >> Reset Position.
function this.main(this)
this:initsensor()
this:setspeed(20,20)
while true do
a = this:readsensor(1)
b = this:readsensor(2)
if (a - b > 2) then
this:setspeed(30,20)
end
if (a - b < -2) then
this:setspeed(20,30)
end
if( (a - b > -2) and (a - b < 2) ) then
this:setspeed(20,20)
end
end
end
The above code is to make the robot move forward following the right wall. See how it reads the sensor value. There are six sensors in the robot (by default). You can modify the number of sensors from menu Robot >> Set properties. They are all laser beam type distance. As we know there are also sonar type distance sensor. Take a look at the picture. Sensor numbering starts from the right side and the index is increasing in clockwise direction.
Let's try another. Within the demo, I included two files trinity.wrl and trinity.lua. Load the two files. Copy and paste the following code:
function this.moveforward(this)
-- to much to the left, so turn right
while(this:readsensor(1) - this:readsensor(5) > 20) do
this:setspeed(30,20);
end
--to much to the right, so turn left
while(this:readsensor(1) - this:readsensor(5) < -20) do
this:setspeed(20,30);
end
this:setspeed(30,30);
end
function this.sharpturnright(this)
th = this:getangle()
while(this:getangle() < th + 3.14 / 2) do
this:setspeed(30,0);
end
end
function this.sharpturnleft(this)
th = this:getangle()
while(this:getangle() > th - 3.14 / 2) do
this:setspeed(0,30);
end
end
-----------------------------------------------------------
--main function
function this.main(this)
this:initsensor()
while(true) do
while(this:readsensor(0) > 50) do
this:moveforward()
end
if (this:readsensor(1) - this:readsensor(5) > 0) then
this:sharpturnright()
else
this:sharpturnleft()
end
end
end
Let's take a closer look. The function this.main(this) will always be first called. It's the main function. Function is always written with something like this: function this.functionname(this) and we call it with: this:functionname(parameterifexisit). In the code above, function this.moveforward(this) will read the difference between right front and left front sensor. If they show a big difference (more than 20 units), it will turn the robot to the proper direction. If the robot senses a wall at the front, it will check which direction is free. Finally, it will turn sharply in that direction.
There have been plenty of improvements I made since the first release. In the first release, there was an issue that the sensors didn't read right. That's why now we have initsensor command. I also added the debug command so that you can print sensor value in runtime mode. However I still need feedback so that I can make it better. For your information, now this simulator is developed with Visual Studio 2008. If you want to try the demo, you may need to install VS2008 Redistributable package. I hope you like it and it can be helpful for you.
| You must Sign In to use this message board. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 8 Mar 2009 Editor: Deeksha Shenoy |
Copyright 2009 by auralius Everything else Copyright © CodeProject, 1999-2009 Web19 | Advertise on the Code Project |