00001 /*************************************************************************** 00002 * Copyright (C) 2005-2011 LpzRobots development team * 00003 * Georg Martius <georg dot martius at web dot de> * 00004 * Frank Guettler <guettler at informatik dot uni-leipzig dot de * 00005 * Frank Hesse <frank at nld dot ds dot mpg dot de> * 00006 * Ralf Der <ralfder at mis dot mpg dot de> * 00007 * Guillaume de Chambrier <s0672742 at sms dot ed dot ac dot uk> * 00008 * * 00009 * This program is free software; you can redistribute it and/or modify * 00010 * it under the terms of the GNU General Public License as published by * 00011 * the Free Software Foundation; either version 2 of the License, or * 00012 * (at your option) any later version. * 00013 * * 00014 * This program is distributed in the hope that it will be useful, * 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00017 * GNU General Public License for more details. * 00018 * * 00019 * You should have received a copy of the GNU General Public License * 00020 * along with this program; if not, write to the * 00021 * Free Software Foundation, Inc., * 00022 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 00023 * * 00024 ***************************************************************************/ 00025 /* 00026 This file concerns material implementation in the simulator. 00027 00028 Terminology: 00029 Since "Material" is used for OpenGL stuff and also in OSG 00030 we should use something else for the physical material: substance 00031 00032 So how to implement substance to cover all collission cases and requirements. 00033 It would be nice to keep the collisioncontrol as it is for compatibility reasons. 00034 In general: 00035 00036 - every ode geom should get a user data pointer to the primitive 00037 - primitive has a certain substance 00038 - 2 substance define collision parameters 00039 - also an optional callback function for user defined handling 00040 - collission detection is done globally. 00041 - via joint connected geoms are stored in a set (globally) 00042 - spaces are globally registered 00043 00044 ***************************************************************************/ 00045 #ifndef __SUBSTANCE_H 00046 #define __SUBSTANCE_H 00047 00048 #include<ode-dbl/common.h> 00049 #include<ode-dbl/contact.h> 00050 00051 namespace lpzrobots { 00052 00053 // Todo: maybe add bounce 00054 00055 class GlobalData; 00056 class Substance; 00057 class Axis; 00058 00059 /** function to be called at a collision event between the two geoms. 00060 @param params surface parameter, which should be changed/calculated by this function 00061 @param globaldata global information 00062 @param userdata pointer to user data for this callback (stored in substance) 00063 @param contacts array of contact information 00064 @param numContacts length of contact information array 00065 @param o1 geom corresponding to substance of this callback 00066 @param o2 other geom 00067 @param s1 substance of this callback 00068 @param s2 other substance 00069 @return 0 if collision should not be treated; 00070 1 if collision should be treated otherwise (by other callback or standard methods); 00071 2 if collision to be treated and parameters for collision are set in params 00072 */ 00073 typedef int (*CollisionCallback)(dSurfaceParameters& params, GlobalData& globaldata, void *userdata, 00074 dContact* contacts, int numContacts, 00075 dGeomID o1, dGeomID o2, const Substance& s1, const Substance& s2); 00076 00077 /** 00078 Physical substance definition, used for collision detection/treatment 00079 What we need is mu, slip and kp,kd parameter for the collision 00080 Definition of substance parameters: 00081 <pre> 00082 Parameter interval collision_parameter 00083 roughness: [0-] mu = roughness1*roughness2 00084 slip: [0-] slip = slip1+slip2 00085 hardness: [0-] kp = hardness1 * hardness2 / (hardness1 + hardness2) (two springs serial) 00086 elasticity: [0-1] kd = (1-elasticity1) * s2.hardness + (1-elasticity2) * s1.hardness) / 00087 (s1.hardness + s2.hardness); 00088 </pre> 00089 For the calculation of the spring/damping constant we use the following schema: 00090 The collision can be considered as 2 springs serially connected. 00091 The spring constant of each collision side is given by hardness (here kp). The spring constant of 00092 the entire spring is given by \f[ 1/kp = 1/kp_1 + 1/kp_2\f]. 00093 The damping (kd) is derived from the elasticity (e), but it is more difficult to compute. 00094 Consider the damping in form of energy lost. 00095 We can write the energy or work done by each spring as: \f[ W_i = F*s_i = F^2/p \f] with \f[s_i=F*kp_i\f]. 00096 The energy lost though damping is \f[ W_1^D = W_i*(1-e_i) \f]. 00097 The final damping is now: \f[ kd = (1-e) = W^D/W = \frac{(1-e_1)/kp_1 + (1-e_2)/kp_2}{1/kp_1 + 1/kp_2} 00098 = \frac{(1-e_1)kp_2 + (1-e_2)kp_1}{kp_1+kp_2}\f]. 00099 00100 Note that you cannot add any member variables to derived classes 00101 since they do not fit into the substance object in OdeHandle! 00102 */ 00103 class Substance { 00104 public: 00105 Substance(); 00106 Substance( float roughness, float slip, float hardness, float elasticity); 00107 00108 public: 00109 00110 float roughness; 00111 float slip; 00112 float hardness; 00113 float elasticity; 00114 00115 void setCollisionCallback(CollisionCallback func, void* userdata); 00116 00117 CollisionCallback callback; 00118 void* userdata; 00119 00120 public: 00121 /// Combination of two surfaces 00122 static void getSurfaceParams(dSurfaceParameters& sp, const Substance& s1, const Substance& s2, double stepsize); 00123 00124 static void printSurfaceParams(const dSurfaceParameters& surfParams); 00125 00126 //// Factory methods 00127 00128 /// default substance is plastic with roughness=0.8 00129 static Substance getDefaultSubstance(); 00130 void toDefaultSubstance(); 00131 00132 /// very hard and elastic with slip roughness [0.1-1] 00133 static Substance getMetal(float roughness); 00134 /// very hard and elastic with slip roughness [0.1-1] 00135 void toMetal(float roughness); 00136 00137 /// high roughness, no slip, very elastic, hardness : [5-50] 00138 static Substance getRubber(float hardness); 00139 /// high roughness, no slip, very elastic, hardness : [5-50] 00140 void toRubber(float hardness); 00141 00142 /// medium slip, a bit elastic, medium hardness, roughness [0.5-2] 00143 static Substance getPlastic(float roughness); 00144 /// medium slip, a bit elastic, medium hardness, roughness [0.5-2] 00145 void toPlastic(float roughness); 00146 00147 /// large slip, not elastic, low hardness [1-30], high roughness 00148 static Substance getFoam(float _hardness); 00149 /// large slip, not elastic, low hardness [1-30], high roughness 00150 void toFoam(float _hardness); 00151 00152 /** variable slip and roughness [0-1], not elastic, high hardness for solid snow 00153 slip = 1 <--> roughness=0.0, slip = 0 <--> roughnes=1.0 */ 00154 static Substance getSnow(float _slip); 00155 /** variable slip and roughness, not elastic, high hardness for solid snow 00156 slip = 1 <--> roughness=0.0, slip = 0 <--> roughnes=1.0 */ 00157 void toSnow(float _slip); 00158 00159 /// @see toNoContact() 00160 static Substance getNoContact(); 00161 /** set the collsion callback to ignores everything 00162 Usually it is better to use the "ignorePairs" from odeHandle but 00163 if this particular one substance should not collide with any other, this is easier. 00164 WARNING: this sets the collisionCallback. This will not convert to other 00165 substances without manually setting the callback to 0 00166 */ 00167 void toNoContact(); 00168 00169 /** enables anisotrop friction. 00170 The friction along the given axis is ratio fold of the friction in the other directions. 00171 If ratio = 0.1 and axis=Axis(0,0,1) then the fiction along the z-axis 00172 is 1/10th of the normal friction. 00173 Useful to mimic scales of snakes or the like. 00174 WARNING: this sets the collisionCallback! 00175 To disable the collisionCallback has to set to 0 manually 00176 */ 00177 void toAnisotropFriction(double ratio, const Axis& axis); 00178 }; 00179 00180 00181 class DebugSubstance : public Substance { 00182 public: 00183 DebugSubstance(); 00184 DebugSubstance( float roughness, float slip, float hardness, float elasticity); 00185 protected: 00186 static int dbg_output(dSurfaceParameters& params, GlobalData& globaldata, void *userdata, 00187 dContact* contacts, int numContacts, 00188 dGeomID o1, dGeomID o2, const Substance& s1, const Substance& s2); 00189 }; 00190 00191 } 00192 00193 #endif 00194 00195