← Back to team overview

yade-dev team mailing list archive

[Branch ~yade-dev/yade/trunk] Rev 2531: 1. Add HdapsGravityEngine which reads acceleration from real accelerometer in thinkpads (toy engine)

 

------------------------------------------------------------
revno: 2531
committer: Václav Šmilauer <eu@xxxxxxxx>
branch nick: yade
timestamp: Fri 2010-11-05 15:13:01 +0100
message:
  1. Add HdapsGravityEngine which reads acceleration from real accelerometer in thinkpads (toy engine)
  2. Fix bug in qt4 interface where multi-number entries (Vector3r etc) might have some values zeroed due to wrong order of initial update and signal connects.
added:
  scripts/test/hdaps.py
modified:
  SConstruct
  gui/qt4/SerializableEditor.py
  pkg/common/GravityEngines.cpp
  pkg/common/GravityEngines.hpp


--
lp:yade
https://code.launchpad.net/~yade-dev/yade/trunk

Your team Yade developers is subscribed to branch lp:yade.
To unsubscribe from this branch go to https://code.launchpad.net/~yade-dev/yade/trunk/+edit-subscription
=== modified file 'SConstruct'
--- SConstruct	2010-10-26 13:41:30 +0000
+++ SConstruct	2010-11-05 14:13:01 +0000
@@ -159,9 +159,9 @@
 
 # do not propagate PATH from outside, to ensure identical builds on different machines
 #env.Append(ENV={'PATH':['/usr/local/bin','/bin','/usr/bin']})
-# ccache needs $HOME to be set; colorgcc needs $TERM; distcc wants DISTCC_HOSTS
+# ccache needs $HOME to be set, also CCACHE_PREFIX if used; colorgcc needs $TERM; distcc wants DISTCC_HOSTS
 # fakeroot needs FAKEROOTKEY and LD_PRELOAD
-propagatedEnvVars=['HOME','TERM','DISTCC_HOSTS','LD_PRELOAD','FAKEROOTKEY','LD_LIBRARY_PATH']
+propagatedEnvVars=['HOME','TERM','DISTCC_HOSTS','LD_PRELOAD','FAKEROOTKEY','LD_LIBRARY_PATH','CCACHE_PREFIX']
 for v in propagatedEnvVars:
 	if os.environ.has_key(v): env.Append(ENV={v:os.environ[v]})
 if env.has_key('PATH'): env.Append(ENV={'PATH':env['PATH']})
@@ -585,11 +585,11 @@
 
 if env['mono']:
 	env['topLevelDir']=os.path.abspath(os.getcwd())
-	env.SConscript('SConscript-mono',build_dir=buildDir,duplicate=0)
+	env.SConscript('SConscript-mono',variant_dir=buildDir,duplicate=0)
 
 else:
-	# read top-level SConscript file. It is used only so that build_dir is set. This file reads all necessary SConscripts
-	env.SConscript(dirs=['.'],build_dir=buildDir,duplicate=0)
+	# read top-level SConscript file. It is used only so that variant_dir is set. This file reads all necessary SConscripts
+	env.SConscript(dirs=['.'],variant_dir=buildDir,duplicate=0)
 
 #################################################################################
 ## remove plugins that are in the target dir but will not be installed now

=== modified file 'gui/qt4/SerializableEditor.py'
--- gui/qt4/SerializableEditor.py	2010-10-13 14:03:59 +0000
+++ gui/qt4/SerializableEditor.py	2010-11-05 14:13:01 +0000
@@ -214,8 +214,9 @@
 			w=QSpinBox()
 			w.setRange(int(-1e9),int(1e9)); w.setSingleStep(1);
 			self.grid.addWidget(w,row,col);
-			w.valueChanged.connect(self.update)
-		self.refresh()
+		self.refresh() # refresh before connecting signals!
+		for row,col in itertools.product(range(self.rows),range(self.cols)):
+			self.grid.itemAtPosition(row,col).widget().valueChanged.connect(self.update)
 	def refresh(self):
 		val=self.getter()
 		for row,col in itertools.product(range(self.rows),range(self.cols)):

=== modified file 'pkg/common/GravityEngines.cpp'
--- pkg/common/GravityEngines.cpp	2010-10-13 16:23:08 +0000
+++ pkg/common/GravityEngines.cpp	2010-11-05 14:13:01 +0000
@@ -6,10 +6,13 @@
 *  GNU General Public License v2 or later. See file LICENSE for details. *
 *************************************************************************/
 
-#include"GravityEngines.hpp"
+#include<yade/pkg-common/GravityEngines.hpp>
+#include<yade/pkg-common/PeriodicEngines.hpp>
 #include<yade/core/Scene.hpp>
+#include<boost/regex.hpp>
+//#include<stdio.h>
 
-YADE_PLUGIN((GravityEngine)(CentralGravityEngine)(AxialGravityEngine));
+YADE_PLUGIN((GravityEngine)(CentralGravityEngine)(AxialGravityEngine)(HdapsGravityEngine));
 
 void GravityEngine::action(){
 	/* skip bodies that are within a clump;
@@ -55,3 +58,32 @@
 		scene->forces.addForce(b->getId(),acceleration*b->state->mass*toAxis);
 	}
 }
+
+
+Vector2i HdapsGravityEngine::readSysfsFile(const string& name){
+	char buf[256];
+	ifstream f(name.c_str());
+	if(!f.is_open()) throw std::runtime_error(("HdapsGravityEngine: unable to open file "+name).c_str());
+	f.read(buf,256);f.close();
+	const boost::regex re("\\(([0-9+-]+),([0-9+-]+)\\).*");
+   boost::cmatch matches;
+	if(!boost::regex_match(buf,matches,re)) throw std::runtime_error(("HdapsGravityEngine: error parsing data from "+name).c_str());
+	//cerr<<matches[1]<<","<<matches[2]<<endl;
+	return Vector2i(lexical_cast<int>(matches[1]),lexical_cast<int>(matches[2]));
+
+}
+
+void HdapsGravityEngine::action(){
+	if(!calibrated) { calibrate=readSysfsFile(hdapsDir+"/calibrate"); calibrated=true; }
+	Real now=PeriodicEngine::getClock();
+	if(now-lastReading>1e-3*msecUpdate){
+		Vector2i a=readSysfsFile(hdapsDir+"/position");
+		lastReading=now;
+		a-=calibrate;
+		if(abs(a[0]-accel[0])>updateThreshold) accel[0]=a[0];
+		if(abs(a[1]-accel[1])>updateThreshold) accel[1]=a[1];
+		Quaternionr trsf(AngleAxisr(.5*accel[0]*M_PI/180.,-Vector3r::UnitY())*AngleAxisr(.5*accel[1]*M_PI/180.,-Vector3r::UnitX()));
+		gravity=trsf*zeroGravity;
+	}
+	GravityEngine::action();
+}

=== modified file 'pkg/common/GravityEngines.hpp'
--- pkg/common/GravityEngines.hpp	2010-10-13 16:23:08 +0000
+++ pkg/common/GravityEngines.hpp	2010-11-05 14:13:01 +0000
@@ -50,3 +50,20 @@
 };
 REGISTER_SERIALIZABLE(AxialGravityEngine);
 
+class HdapsGravityEngine: public GravityEngine{
+	public:
+	Vector2i readSysfsFile(const std::string& name);
+	virtual void action();
+	YADE_CLASS_BASE_DOC_ATTRS(HdapsGravityEngine,GravityEngine,"Read accelerometer in Thinkpad laptops (`HDAPS <http://en.wikipedia.org/wiki/Active_hard_drive_protection>`__ and accordingly set gravity within the simulation. This code draws from `hdaps-gl <https://sourceforge.net/project/showfiles.php?group_id=138242>`__ .",
+		((string,hdapsDir,"/sys/devices/platform/hdaps",,"Hdaps directory; contains ``position`` (with accelerometer readings) and ``calibration`` (zero acceleration)."))
+		((Real,msecUpdate,50,,"How often to update the reading."))
+		((int,updateThreshold,4,,"Minimum difference of reading from the file before updating gravity, to avoid jitter."))
+		((Real,lastReading,-1,Attr::hidden|Attr::noSave,"Time of the last reading."))
+		((Vector2i,accel,Vector2i::Zero(),(Attr::noSave|Attr::readonly),"reading from the sysfs file"))
+		((Vector2i,calibrate,Vector2i::Zero(),,"Zero position; if NaN, will be read from the *hdapsDir* / calibrate."))
+		((bool,calibrated,false,,"Whether *calibrate* was already updated. Do not set to ``True`` by hand unless you also give a meaningful value for *calibrate*."))
+		((Vector3r,zeroGravity,Vector3r(0,0,-1),,"Gravity if the accelerometer is in flat (zero) position."))
+	);
+};
+REGISTER_SERIALIZABLE(HdapsGravityEngine);
+

=== added file 'scripts/test/hdaps.py'
--- scripts/test/hdaps.py	1970-01-01 00:00:00 +0000
+++ scripts/test/hdaps.py	2010-11-05 14:13:01 +0000
@@ -0,0 +1,21 @@
+
+# With Thinkpad laptops, control the sphere's motion by tilting the
+# laptop.
+
+O.bodies.append(
+	utils.facetBox(center=(0,0,.1),extents=(.5,.5,.1),wallMask=31,color=(0,0,1))+
+	[utils.sphere((0,0,.1),.04,color=(1,1,1))]
+)
+
+O.engines=[
+	ForceResetter(),
+	InsertionSortCollider([Bo1_Sphere_Aabb(),Bo1_Facet_Aabb()]),
+	InteractionLoop([Ig2_Facet_Sphere_ScGeom()],[Ip2_FrictMat_FrictMat_FrictPhys()],[Law2_ScGeom_FrictPhys_CundallStrack()]),
+	HdapsGravityEngine(calibrate=(-495,-495),calibrated=True,zeroGravity=(0,0,-1)),
+	NewtonIntegrator(damping=.3),
+]
+O.dt=utils.PWaveTimeStep()
+
+import yade.qt
+yade.qt.View()
+O.run()