From 35b82ced04c8a158ca625912e94c590fcb674a16 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gr=C3=A9goire=20Payen=20de=20La=20Garanderie?=
 <gregoire.payendelagaranderie@telecom-bretagne.eu>
Date: Sun, 16 Jan 2011 00:22:07 +0100
Subject: [PATCH] =?UTF-8?q?Ajout=20d=E2=80=99une=20petite=20simulation=20p?=
 =?UTF-8?q?hysique=20avec=20Box2D?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 include/simul/element.h       | 13 ++---
 include/simul/robot.h         |  5 +-
 include/simul/table.h         |  4 ++
 simulation/Makefile.am        |  1 +
 simulation/aclocal.m4         |  1 +
 simulation/configure.ac       |  6 ++-
 simulation/m4/ax_dep_check.m4 | 42 ++++++++++++++++
 src/asservissement.cpp        |  6 ++-
 src/roue.cpp                  |  1 +
 src/simul/element.cpp         | 29 +++++++++++
 src/simul/robot.cpp           | 93 +++++++++++++++++++++++++----------
 src/simul/table.cpp           | 60 ++++++++++++++++++++--
 12 files changed, 221 insertions(+), 40 deletions(-)
 create mode 100644 simulation/m4/ax_dep_check.m4
 create mode 100644 src/simul/element.cpp

diff --git a/include/simul/element.h b/include/simul/element.h
index b125b1d1..25c78aa6 100644
--- a/include/simul/element.h
+++ b/include/simul/element.h
@@ -3,6 +3,7 @@
 
 #include "Position.h"
 #include <QPainter>
+#include "Box2D/Box2D.h"
 
 class Element
 {
@@ -17,11 +18,9 @@ public:
 
 	Type type;
 
-	Element(Position p, Type t)
-	{
-		this->p = p;
-		type = t;
-	}
+	b2Body* body;
+
+	Element(b2World & world, Position p, Type t);
 
 	void paint(QPainter & pa)
 	{
@@ -29,8 +28,10 @@ public:
 		pa.setBrush(QBrush(QColor("yellow")));
 		pa.setPen(QBrush(QColor("yellow")));
 
-		pa.drawEllipse(QPoint(p.x.getValueInMillimeters(),p.x.getValueInMillimeters()),150,150);
+		pa.drawEllipse(QPoint(p.x.getValueInMillimeters(),p.y.getValueInMillimeters()),100,100);
 	}
+
+	void updatePos();
 };
 
 #endif //PION_H_INCLUDED
diff --git a/include/simul/robot.h b/include/simul/robot.h
index 43e3a51f..ebeaaf53 100644
--- a/include/simul/robot.h
+++ b/include/simul/robot.h
@@ -5,6 +5,7 @@
 #include <QKeyEvent>
 #include <boost/circular_buffer.hpp>
 #include "PositionPlusAngle.h"
+#include <Box2D/Box2D.h>
 
 class Robot
 {
@@ -19,11 +20,13 @@ public:
 	class OdoRobot* odometrie;
 	class Strategie* strategie;
 	
+	b2Body* body;
 
-	Robot();
+	Robot(b2World &world);
 
 	void paint(QPainter &p, int dt);
 	void keyPressEvent(QKeyEvent* evt,bool press);
+	void updateForces(int dt);
 };
 
 #endif //ROBOT_H_INCLUDED
diff --git a/include/simul/table.h b/include/simul/table.h
index b54da675..b36e7929 100644
--- a/include/simul/table.h
+++ b/include/simul/table.h
@@ -3,6 +3,7 @@
 
 #include <QWidget>
 #include "element.h"
+#include <Box2D/Box2D.h>
 
 class Table : public QWidget
 {
@@ -10,6 +11,9 @@ private:
 	int dt;
 	std::vector<class Element*> elements;
 	std::vector<class Robot*> robots;
+
+	b2World world;
+	b2Body* tableBody;
 public:
 
 	static const int tableWidth = 3000;
diff --git a/simulation/Makefile.am b/simulation/Makefile.am
index beba2e3d..05565af3 100644
--- a/simulation/Makefile.am
+++ b/simulation/Makefile.am
@@ -4,6 +4,7 @@ INCLUDES = -Iinclude -Iimpl -Imoc -I.
 
 
 paprika_SOURCES=\
+src/simul/element.cpp \
 src/simul/main.cpp \
 src/simul/main_window.cpp \
 src/simul/table.cpp \
diff --git a/simulation/aclocal.m4 b/simulation/aclocal.m4
index c89e5f68..939b3946 100644
--- a/simulation/aclocal.m4
+++ b/simulation/aclocal.m4
@@ -1108,3 +1108,4 @@ AC_SUBST([am__untar])
 ]) # _AM_PROG_TAR
 
 m4_include([m4/ax_boost_base.m4])
+m4_include([m4/ax_dep_check.m4])
diff --git a/simulation/configure.ac b/simulation/configure.ac
index 34eb3a37..f352465e 100644
--- a/simulation/configure.ac
+++ b/simulation/configure.ac
@@ -23,6 +23,8 @@ AX_BOOST_BASE([1.40], [AC_MSG_RESULT(yes) ] , [AC_MSG_RESULT(no) ] )
 
 CXXFLAGS=
 
+AX_DEP_CHECK(Box2D, [/usr/lib /usr/local/lib], libBox2D.so,[/usr/include /usr/local/include],Box2D/Box2D.h, -lBox2D)
+
 AC_ARG_ENABLE([debug], AS_HELP_STRING([--enable-debug],[Turn on debugging]), [enable_debug=$enableval],[enable_debug="no"])
 AC_MSG_CHECKING(debug)
 AC_MSG_RESULT($enable_debug)
@@ -30,8 +32,8 @@ if test "x$enable_debug" = "xyes"; then
 	CXXFLAGS="$CXXFLAGS -g3 -ggdb -Wall -DDEBUG"
 fi
 
-CXXFLAGS="$CXXFLAGS   $AM_CXXFLAGS $QT_CFLAGS $BOOST_CFLAGS"
-LDFLAGS="$LDFLAGS $AM_LDFLAGS $QT_LIBS $BOOST_LDFLAGS"
+CXXFLAGS="$CXXFLAGS   $AM_CXXFLAGS $QT_CFLAGS $BOOST_CFLAGS $Box2D_CFLAGS"
+LDFLAGS="$LDFLAGS $AM_LDFLAGS $QT_LIBS $BOOST_LDFLAGS $Box2D_LIBS"
 AC_SUBST([CFLAGS])
 
 AC_HEADER_STDC
diff --git a/simulation/m4/ax_dep_check.m4 b/simulation/m4/ax_dep_check.m4
new file mode 100644
index 00000000..f17b1af7
--- /dev/null
+++ b/simulation/m4/ax_dep_check.m4
@@ -0,0 +1,42 @@
+
+AC_DEFUN([AX_DEP_CHECK],
+[
+
+libluabindpath="/usr/lib /usr/local/lib"
+libluabindname=libluabind.so
+libluabindheader="/usr/include /usr/local/include"
+
+AC_MSG_CHECKING(for $1 libs)
+
+for l in $2; do
+	if test -f $l/$3; then
+		AC_MSG_RESULT($l/$3)
+		$1_LIBS="-L$l $6"
+		break
+	fi
+done
+
+if test -z "${$1_LIBS}"; then
+	AC_MSG_RESULT(not found)
+	exit 1
+fi
+
+AC_MSG_CHECKING(for $1 headers)
+
+for l in $4; do
+	if test -f $l/$5; then
+		AC_MSG_RESULT($l)
+		$1_CFLAGS="-I$l"
+		break
+	fi
+done
+
+if test -z "${$1_CFLAGS}"; then
+	AC_MSG_RESULT(not found)
+	exit 1
+fi
+
+AC_SUBST($1_CFLAGS)
+AC_SUBST($1_LIBS)
+
+])
diff --git a/src/asservissement.cpp b/src/asservissement.cpp
index ab7be00b..e3e7c970 100755
--- a/src/asservissement.cpp
+++ b/src/asservissement.cpp
@@ -62,7 +62,8 @@ Asservissement::Asservissement(Odometrie* _odometrie) :
     en_mouvement = false;
     Asservissement::asservissement = this;
 
-        *((uint32_t *)(STK_CTRL_ADDR)) = 0x03; // CLKSOURCE:0 ; TICKINT: 1 ; ENABLE:1
+#ifdef ROBOTHW
+    *((uint32_t *)(STK_CTRL_ADDR)) = 0x03; // CLKSOURCE:0 ; TICKINT: 1 ; ENABLE:1
     *((uint32_t *)(STK_LOAD_ADDR)) = 9000*nb_ms_between_updates; // valeur en ms*9000 (doit etre inférieur à 0x00FFFFFF=16 777 215)
 
     NVIC_InitTypeDef SysTick_IRQ;
@@ -72,15 +73,18 @@ Asservissement::Asservissement(Odometrie* _odometrie) :
     SysTick_IRQ.NVIC_IRQChannelPreemptionPriority = 0;
     SysTick_IRQ.NVIC_IRQChannelSubPriority = 1;
     NVIC_Init(&SysTick_IRQ);
+#endif
 }
 
 int asserCount = 0;
 
 void Asservissement::update(void)
 {
+/*#ifdef ROBOTHW
     roues.gauche.tourne(0.1);
     roues.droite.tourne(0.1);
     return;
+#endif*/
     //PositionPlusAngle before(odometrie.positionPlusAngle);
     asserCount++;
 
diff --git a/src/roue.cpp b/src/roue.cpp
index 6afae2f7..16d5663c 100755
--- a/src/roue.cpp
+++ b/src/roue.cpp
@@ -29,6 +29,7 @@ Roue::Roue(unsigned char OCx, GPIO_TypeDef * GPIOx_Sens, uint16_t GPIO_Pin_Sens)
 
 void Roue::tourne(float rapport)
 {
+    rapport = 0;
     if(rapport >= 0){
         GPIO_WriteBit(GPIOx_Sens, GPIO_Pin_Sens, Bit_RESET);
     }
diff --git a/src/simul/element.cpp b/src/simul/element.cpp
new file mode 100644
index 00000000..61c441bc
--- /dev/null
+++ b/src/simul/element.cpp
@@ -0,0 +1,29 @@
+#include "simul/element.h"
+
+Element::Element(b2World & world, Position p, Type t)
+{
+	this->p = p;
+	type = t;
+
+	b2BodyDef bodyDef;
+	bodyDef.type = b2_dynamicBody;
+	bodyDef.position.Set(p.x.getValueInMillimeters()/100., p.y.getValueInMillimeters()/100.);
+	
+	body = world.CreateBody(&bodyDef);
+
+	b2CircleShape circle;
+	circle.m_p.Set(0.,0.);
+	circle.m_radius = 1.0f;
+
+	b2FixtureDef fixtureDef;
+	fixtureDef.shape = &circle;
+	fixtureDef.density = 1.0f;
+	fixtureDef.friction = 0; //0.3f;
+	body->CreateFixture(&fixtureDef);
+}
+
+void Element::updatePos()
+{
+	p.x = 100.*body->GetPosition().x;
+	p.y = 100.*body->GetPosition().y;
+}
diff --git a/src/simul/robot.cpp b/src/simul/robot.cpp
index e3dd2e10..a880b438 100644
--- a/src/simul/robot.cpp
+++ b/src/simul/robot.cpp
@@ -23,12 +23,12 @@ public:
 		return robot->pos;
 	}
 
-	Distance vitesseLineaire()
+	Distance getVitesseLineaire()
 	{
 		return robot->deriv.position.getNorme();
 	}
 
-	Angle vitesseAngulaire()
+	Angle getVitesseAngulaire()
 	{
 		return robot->deriv.angle;
 	}
@@ -40,11 +40,8 @@ public:
 };
 
 
-Robot::Robot() : olds(10000)
+Robot::Robot(b2World & world) : olds(10000)
 {
-	pos.position.x=1000;
-	pos.position.y=500;
-	pos.angle=0;
 
 	deriv.position.x = 0;
 	deriv.position.y = 0;
@@ -55,22 +52,72 @@ Robot::Robot() : olds(10000)
 	odometrie = new OdoRobot(this);
 	asservissement = new Asservissement(odometrie);
 	strategie = new Strategie(true, asservissement);
+
+	pos.position.x=1000.;
+	pos.position.y=500.;
+	pos.angle=0;
+
 	asservissement->strategie = strategie;
+
+	b2BodyDef bodyDef;
+	bodyDef.type = b2_dynamicBody;
+	bodyDef.position.Set(pos.position.x.getValueInMillimeters()/100., pos.position.y.getValueInMillimeters()/100.);
+	bodyDef.angle = pos.angle.getValueInRadian();
+	
+	body = world.CreateBody(&bodyDef);
+
+	b2PolygonShape box;
+	box.SetAsBox(1.,1., b2Vec2(1,1),0);
+
+	b2FixtureDef fixtureDef;
+	fixtureDef.shape = &box;
+	fixtureDef.density = 10.0f;
+	fixtureDef.friction = 0.f;
+	body->CreateFixture(&fixtureDef);
+}
+
+void Robot::updateForces(int dt)
+{
+	if(dt == 0)
+		return;
+
+	Position impulse;
+	impulse.x = (deriv.position.x*cos(pos.angle.getValueInRadian()) - deriv.position.y*sin(pos.angle.getValueInRadian()));
+	impulse.y = (deriv.position.x*sin(pos.angle.getValueInRadian()) + deriv.position.y*cos(pos.angle.getValueInRadian()));
+
+	float32 rdt = 1000./(float)dt;
+
+	b2Vec2 bimpulse = 10*(0.01*rdt*b2Vec2(impulse.x.getValueInMillimeters(),impulse.y.getValueInMillimeters()) - body->GetLinearVelocity());
+	//body->SetLinearVelocity(bimpulse);
+	body->ApplyForce(body->GetMass()*bimpulse, body->GetWorldCenter());
+	//body->SetAngularVelocity(deriv.angle.getValueInRadian()*(1000./(float)dt));
+	body->ApplyTorque((deriv.angle.getValueInRadian()*rdt - body->GetAngularVelocity())*body->GetInertia());
+
 }
 
+
 void Robot::paint(QPainter &p, int dt)
 {
-	if(manual)
-	{
-		keyPressEvent(NULL,false);
-		deriv.position.x = deriv.position.x* 0.99;
-		deriv.angle = deriv.angle * 0.9;
-	}
-	else
+	if(dt)
 	{
-		Asservissement::asservissement->update();
-		deriv.position.x = asservissement->vitesse_lineaire_a_atteindre;
-		deriv.angle = asservissement->vitesse_angulaire_a_atteindre;
+		pos.position.x = 100*body->GetWorldCenter().x;
+		pos.position.y = 100*body->GetWorldCenter().y;
+		pos.angle = body->GetAngle();
+
+		olds.push_back(pos);
+		if(manual)
+		{
+			keyPressEvent(NULL,false);
+			deriv.position.x = deriv.position.x* 0.97;
+			deriv.angle = deriv.angle * 0.9;
+		}
+		else
+		{
+			Asservissement::asservissement->update();
+			deriv.position.x = asservissement->vitesse_lineaire_a_atteindre;
+			deriv.position.y = 0;
+			deriv.angle = asservissement->vitesse_angulaire_a_atteindre;
+		}
 	}
 
 	p.setWorldTransform(QTransform().translate(pos.position.x.getValueInMillimeters(),pos.position.y.getValueInMillimeters()).rotateRadians(pos.angle.getValueInRadian()));
@@ -87,16 +134,9 @@ void Robot::paint(QPainter &p, int dt)
 	p.drawLine(0,100*pos.angle.getValueInRadian(),0,0);
 	p.setWorldTransform(QTransform());
 
-	if(dt)
-	{
-		olds.push_back(pos);
-		pos.position.x += (deriv.position.x*cos(pos.angle.getValueInRadian()) - deriv.position.y*sin(pos.angle.getValueInRadian()));
-		pos.position.y += (deriv.position.x*sin(pos.angle.getValueInRadian()) + deriv.position.y*cos(pos.angle.getValueInRadian()));
-		pos.angle += deriv.angle;
-	}
 
 	p.setPen(QColor(Qt::green));
-	for(unsigned int i=0; i < olds.size()-1; i++)
+	for(unsigned int i=0; i+1 < olds.size(); i++)
 		p.drawLine(olds[i].position.x.getValueInMillimeters(), olds[i].position.y.getValueInMillimeters(), olds[i+1].position.x.getValueInMillimeters(), olds[i+1].position.y.getValueInMillimeters());	
 }
 
@@ -111,8 +151,8 @@ void Robot::keyPressEvent(QKeyEvent* evt, bool press)
 
 	if(manual)
 	{
-		float dinc = 0.1;
-		float ainc = 0.003;
+		float dinc = .5;
+		float ainc = 0.005;
 
 		IF_KEYSWITCH(avant,evt->key() == Qt::Key_Up)
 			deriv.position.x += dinc;
@@ -122,7 +162,6 @@ void Robot::keyPressEvent(QKeyEvent* evt, bool press)
 			deriv.angle += ainc;
 		IF_KEYSWITCH(droite,evt->key() == Qt::Key_Left)
 			deriv.angle -= ainc;
-		std::cout << deriv.position.x.getValueInMillimeters() << " & " << deriv.angle.getValueInRadian() << std::endl;
 	}
 }
 
diff --git a/src/simul/table.cpp b/src/simul/table.cpp
index f78b368e..d570d655 100644
--- a/src/simul/table.cpp
+++ b/src/simul/table.cpp
@@ -3,7 +3,7 @@
 #include <iostream>
 #include <QPainter>
 
-Table::Table(QWidget* parent) : QWidget(parent)
+Table::Table(QWidget* parent) : QWidget(parent), world(b2Vec2(0.f,0.f), false)
 {
 	dt=0;
 	setAutoFillBackground(true);
@@ -12,9 +12,56 @@ Table::Table(QWidget* parent) : QWidget(parent)
 	p.setColor(QPalette::Window,QColor(Qt::darkGray));
 	setPalette(p);
 
-	robots.push_back(new Robot());
+	robots.push_back(new Robot(world));
 
-	elements.push_back(new Element(Position(300,300),Element::Pion));
+	elements.push_back(new Element(world,Position(900,900),Element::Pion));
+
+	//Geometry
+	b2BodyDef bodyDef;
+	bodyDef.position.Set(0., 0.);
+	
+	tableBody = world.CreateBody(&bodyDef);
+
+	
+	b2PolygonShape box;
+	b2FixtureDef fixtureDef;
+	fixtureDef.shape = &box;
+	fixtureDef.friction = 0;
+	fixtureDef.density = 0;
+
+	box.SetAsBox(30,1, b2Vec2(0,-1),0);
+	tableBody->CreateFixture(&fixtureDef);
+
+	box.SetAsBox(1,21, b2Vec2(-1,0),0);
+	tableBody->CreateFixture(&fixtureDef);
+
+	box.SetAsBox(1,21, b2Vec2(31,0),0);
+	tableBody->CreateFixture(&fixtureDef);
+
+	box.SetAsBox(30.,1., b2Vec2(0,22),0);
+	tableBody->CreateFixture(&fixtureDef);
+
+	//Starting zones borders
+	box.SetAsBox(4.00,.11, b2Vec2(0.,4.), 0.);
+	tableBody->CreateFixture(&fixtureDef);
+	box.SetAsBox(4.00,.11, b2Vec2(30.,4.), 0.);
+	tableBody->CreateFixture(&fixtureDef);
+
+	//Blocked zones
+	box.SetAsBox(3.50,1.20, b2Vec2(8,21), 0.);
+	tableBody->CreateFixture(&fixtureDef);
+	box.SetAsBox(3.50,1.20, b2Vec2(22,21), 0.);
+	tableBody->CreateFixture(&fixtureDef);
+
+	box.SetAsBox(.11,0.65, b2Vec2(4.61,19.15), 0.);
+	tableBody->CreateFixture(&fixtureDef);
+	box.SetAsBox(.11,0.65, b2Vec2(18.61,19.15), 0.);
+	tableBody->CreateFixture(&fixtureDef);
+
+	box.SetAsBox(.11,0.65, b2Vec2(11.39,19.15), 0.);
+	tableBody->CreateFixture(&fixtureDef);
+	box.SetAsBox(.11,0.64, b2Vec2(25.39,19.15), 0.);
+	tableBody->CreateFixture(&fixtureDef);
 }
 
 Table::~Table()
@@ -24,6 +71,13 @@ Table::~Table()
 void Table::update(int dt)
 {
 	this->dt = dt;
+	for(unsigned int i=0; i < robots.size(); i++)
+		robots[i]->updateForces(dt);
+
+	world.Step((float)dt/1000., 10, 10);
+	world.ClearForces();
+	for(unsigned int i=0; i < elements.size(); i++)
+		elements[i]->updatePos();
 	repaint();
 }
 
-- 
GitLab