@@ -208,6 +208,7 @@ TWorld_ODE = class
208208 { TFViewer }
209209
210210 TFViewer = class (TForm)
211+ GLBitmapFont: TGLBitmapFont;
211212 GLScene: TGLScene;
212213 GLCadencer: TGLCadencer;
213214 GLSceneViewer: TGLSceneViewer;
@@ -443,10 +444,12 @@ procedure nearCallback (data : pointer; o1, o2 : PdxGeom); cdecl;
443444 if (o1.data <> nil ) and (TSolid(o1.data).kind in [skOmniWheel, skOmniSurface, skMecanumWheel_L, skMecanumWheel_R]) then begin
444445 n_mode := n_mode or cardinal(dContactMu2 or dContactFDir1);
445446 if TSolid(o1.data).kind = skOmniWheel then begin
446- dBodyVectorToWorld(b1, 0 , 0 , 1 , n_fdir1);
447- tmp := n_mu2;
448- n_mu2 := n_mu;
449- n_mu := tmp;
447+ // dBodyVectorToWorld(b1, 0, 0, 1, n_fdir1);
448+ // tmp := n_mu2;
449+ // n_mu2 := n_mu;
450+ // n_mu := tmp;
451+ dBodyVectorToWorld(b1, 0 , 0 , 1 , aux_v1);
452+ n_fdir1 := Vector3Cross(contact[0 ].geom.normal, aux_v1);
450453 end else if TSolid(o1.data).kind = skMecanumWheel_L then begin
451454 // dBodyVectorToWorld(b1, 0, 0, 1, n_fdir1);
452455 dBodyVectorToWorld(b1, 0 , 0 , 0.707106781186547 , aux_v1); // 1/sqrt(2)
@@ -464,10 +467,12 @@ procedure nearCallback (data : pointer; o1, o2 : PdxGeom); cdecl;
464467 n_mode := n_mode or cardinal(dContactMu2 or dContactFDir1);
465468 // dBodyVectorToWorld(b2, 0, 0, 1, n_fdir1);
466469 if TSolid(o2.data).kind = skOmniWheel then begin
467- dBodyVectorToWorld(b2, 0 , 0 , 1 , n_fdir1);
468- tmp := n_mu2;
469- n_mu2 := n_mu;
470- n_mu := tmp; // 0.001;
470+ // dBodyVectorToWorld(b2, 0, 0, 1, n_fdir1);
471+ // tmp := n_mu2;
472+ // n_mu2 := n_mu;
473+ // n_mu := tmp; //0.001;
474+ dBodyVectorToWorld(b2, 0 , 0 , 1 , aux_v1);
475+ n_fdir1 := Vector3Cross(contact[0 ].geom.normal, aux_v1);
471476 end else if TSolid(o2.data).kind = skMecanumWheel_L then begin
472477 // dBodyVectorToWorld(b2, 0, 0, 1, n_fdir1);
473478 dBodyVectorToWorld(b2, 0 , 0 , 0.707106781186547 , aux_v1); // 1/sqrt(2)
@@ -2466,8 +2471,14 @@ procedure TWorld_ODE.LoadObstaclesFromXML(XMLFile: string; OffsetDef: TSolidDef;
24662471 Vec: TDVector3;
24672472 NewObstacle: TSolid;
24682473
2474+ hasCanvas: boolean;
2475+ CanvasWidth, CanvasHeigth: integer;
2476+
24692477 Surf: TdSurfaceParameters; // TOD=: unify with solids
24702478begin
2479+ hasCanvas := false;
2480+ CanvasWidth := 256 ; CanvasHeigth := 256 ;
2481+
24712482 XML := LoadXML(XMLFile, XMLErrors);
24722483 if XML = nil then exit;
24732484
@@ -2514,6 +2525,11 @@ procedure TWorld_ODE.LoadObstaclesFromXML(XMLFile: string; OffsetDef: TSolidDef;
25142525 Surf.bounce := GetNodeAttrRealParse(prop, ' bounce' , Surf.bounce, Parser);
25152526 Surf.bounce_vel := GetNodeAttrRealParse(prop, ' bounce_tresh' , Surf.bounce_vel, Parser);
25162527 end ;
2528+ if prop.NodeName = ' canvas' then begin
2529+ hasCanvas := true;
2530+ CanvasWidth := round(GetNodeAttrRealParse(prop, ' width' , CanvasWidth, Parser));
2531+ CanvasHeigth := round(GetNodeAttrRealParse(prop, ' heigth' , CanvasHeigth, Parser));
2532+ end ;
25172533 prop := prop.NextSibling;
25182534 end ;
25192535 // Create and position the obstacle
@@ -2527,6 +2543,37 @@ procedure TWorld_ODE.LoadObstaclesFromXML(XMLFile: string; OffsetDef: TSolidDef;
25272543 end ;
25282544 if obstacle.NodeName = ' cuboid' then begin
25292545 CreateObstacleBox(NewObstacle, sizeX, sizeY, sizeZ, posX, posY, posZ);
2546+ if HasCanvas then begin
2547+ (NewObstacle.GLObj as TGLCube).Parts := (NewObstacle.GLObj as TGLCube).Parts - [cpfront]; // remove the side where the canvas will be placed
2548+ NewObstacle.CanvasGLObj := TGLSceneObject(NewObstacle.GLObj.AddNewChild(TGLPlane));
2549+
2550+ NewObstacle.PaintBitmap := TBitmap.Create;
2551+ NewObstacle.PaintBitmap.Width := CanvasWidth;
2552+ NewObstacle.PaintBitmap.Height := CanvasHeigth;
2553+ NewObstacle.PaintBitmap.PixelFormat := pf24bit;
2554+ NewObstacle.PaintBitmap.Canvas.Brush.Color := clWhite;
2555+ NewObstacle.PaintBitmap.Canvas.pen.Color := clblack;
2556+ NewObstacle.PaintBitmap.Canvas.FillRect(0 , 0 , CanvasWidth, CanvasHeigth);
2557+ // NewObstacle.PaintBitmap.Canvas.TextOut(0,0,'Hello World!');
2558+ // newSolid.PaintBitmap.Canvas.Ellipse(0,0,127,127);
2559+ with (NewObstacle.CanvasGLObj as TGLPlane) do begin
2560+ position.Z := sizeZ/2 ;
2561+ width := sizeX;
2562+ Height := sizeY;
2563+ // Material.Texture.Image.LoadFromFile('gy_logo.jpg');
2564+ Material.Texture.Image.Assign(NewObstacle.PaintBitmap);
2565+ Material.Texture.Disabled := false;
2566+ Material.Texture.TextureMode := tmModulate;
2567+ end ;
2568+
2569+ with NewObstacle do begin
2570+ PaintBitmapCorner[0 ] := sizeX/2 ;
2571+ PaintBitmapCorner[1 ] := sizeY/2 ;
2572+ PaintBitmapCorner[2 ] := sizeZ/2 ;
2573+ end ;
2574+ HasCanvas := false;
2575+ end ;
2576+
25302577 end else if obstacle.NodeName = ' cylinder' then begin
25312578 CreateCylinderObstacle(NewObstacle, max(radius, sizeX), sizeZ, posX, posY, posZ);
25322579 end else if obstacle.NodeName = ' sphere' then begin
@@ -4021,7 +4068,7 @@ constructor TWorld_ODE.create;
40214068 // Create physic
40224069 world := dWorldCreate();
40234070// dWorldSetQuickStepNumIterations(world, 10);
4024- Ode_QuickStepIters := 10 ;
4071+ Ode_QuickStepIters := 20 ;
40254072 dWorldSetQuickStepNumIterations(world, Ode_QuickStepIters);
40264073 space := dSimpleSpaceCreate(nil );
40274074 // space := dHashSpaceCreate(nil);
@@ -4042,13 +4089,18 @@ constructor TWorld_ODE.create;
40424089 dWorldSetCFM(world, Ode_CFM);
40434090 dWorldSetERP(world, Ode_ERP);
40444091
4045- // dWorldSetAngularDamping(world, 0.8);
4046- // dWorldSetLinearDamping(world, 0.8);
4092+ // dWorldSetAngularDamping(world, 0);
4093+ // dWorldSetLinearDamping(world, 0);
4094+ // dWorldSetMaxAngularSpeed(world, Infinity);
40474095
40484096 // if FileExists('ground.jpg') then begin
40494097 // FViewer.GLMaterialLibrary.AddTextureMaterial('Ground', 'ground.jpg');
40504098 // end;
40514099
4100+ // dWorldSetAutoDisableFlag(world, 1);
4101+ // dWorldSetAngularDampingThreshold(world, 0.01);
4102+ // dWorldSetAngularDamping(world, 0.1);
4103+
40524104 LoadSceneFromXML(' scene.xml' );
40534105
40544106 SetCameraTarget(0 );
@@ -4141,6 +4193,8 @@ procedure TFViewer.FormCreate(Sender: TObject);
41414193 Application.UpdateFormatSettings := false;
41424194 DefaultFormatSettings.DecimalSeparator := ' .' ;
41434195
4196+ // Bmp32 := nil;
4197+
41444198 SetCurrentDir(ExtractFilePath(Application.ExeName));
41454199
41464200 if ParamCount > 0 then begin
@@ -4188,8 +4242,9 @@ procedure TFViewer.FormCreate(Sender: TObject);
41884242 end ;
41894243
41904244 IniPropStorage.IniFileName := GetIniFineName;
4245+ SetProcessAffinityMask(GetCurrentProcess(), 1 );
41914246// GetProcessAffinityMask(
4192- // SetThreadAffinityMask(GetCurrentThreadId (), 1);
4247+ SetThreadAffinityMask(GetCurrentThread (), 1 );
41934248// SetThreadAffinityMask(GetCurrentProcessId(), 1);
41944249 QueryPerformanceFrequency(t_delta);
41954250 t_delta := t_delta div 1000 ;
@@ -4285,6 +4340,7 @@ function TFViewer.GLSceneViewerPick(X, Y: Integer): TGLCustomSceneObject;
42854340var pick : TGLCustomSceneObject;
42864341 Pos: TdVector3;
42874342begin
4343+
42884344 pick:=(GLSceneViewer.Buffer.GetPickedObject(x, y) as TGLCustomSceneObject);
42894345
42904346 if Assigned(pick) then begin
@@ -4316,7 +4372,7 @@ procedure AxisTorqueModel(axis: TAxis; Theta, w, dt: double; var T: double);
43164372 ev, ebt: double;
43174373 Td, dtheta, TB, TK, tau: double;
43184374begin
4319- max_delta_Im := 0.15 ; // A/ms
4375+ max_delta_Im := 0.5 ; // A/ms
43204376 with Axis do begin
43214377 // If active use PID controller
43224378 if Motor.active then begin
@@ -4406,9 +4462,9 @@ procedure AxisTorqueModel(axis: TAxis; Theta, w, dt: double; var T: double);
44064462 Motor.Im := 0 ;
44074463 end ;
44084464
4409- Motor.PowerDrain := Motor.Im * Motor.voltage * WorldODE.Ode_dt ;
4465+ Motor.PowerDrain := Motor.Im * Motor.voltage;
44104466 if Motor.PowerDrain > 0 then begin
4411- Motor.EnergyDrain := Motor.EnergyDrain + Motor.PowerDrain;
4467+ Motor.EnergyDrain := Motor.EnergyDrain + Motor.PowerDrain * WorldODE.Ode_dt ;
44124468 end ;
44134469
44144470 // coulomb friction
@@ -4445,7 +4501,7 @@ procedure AxisTorqueModel(axis: TAxis; Theta, w, dt: double; var T: double);
44454501
44464502 TK := (Motor.KGearBox + sqrt(Motor.KGearBox) * abs(dtheta)) * dtheta;
44474503
4448- Td := TK - TB;
4504+ Td := TK + TB;
44494505
44504506 { if abs(Motor.JRotor / Td) < WorldODE.Ode_dt then begin
44514507 if Td > 0 then Td := 0.5 *Motor.JRotor / WorldODE.Ode_dt
@@ -4462,7 +4518,7 @@ procedure AxisTorqueModel(axis: TAxis; Theta, w, dt: double; var T: double);
44624518 end else begin
44634519 // T := Motor.Im * Motor.Ki * Motor.GearRatio - Friction.Bv * w - Spring.K * diffangle(Theta, Spring.ZeroPos);
44644520 T := Motor.Im * Motor.Ki * Motor.GearRatio - Friction.Bv * w - Spring.K * (Theta - Spring.ZeroPos);
4465- // T := Motor.Im * Motor.Ki * Motor.GearRatio - Friction.Bv * w - Spring.K * (Theta - Spring.ZeroPos) ;
4521+ // if (abs(w) < 0.05) and (abs(T) < abs( Friction.Fc)) then T := 0 ;
44664522 end ;
44674523 end ;
44684524end ;
@@ -4645,6 +4701,11 @@ procedure TFViewer.UpdateGLScene;
46454701 end ;
46464702
46474703 end ;
4704+
4705+ for r := 0 to WorldODE.Obstacles.Count-1 do begin
4706+ WorldODE.Obstacles[r].UpdateGLCanvas;
4707+ end ;
4708+
46484709end ;
46494710
46504711
@@ -4664,7 +4725,7 @@ procedure TFViewer.GLCadencerProgress(Sender: TObject; const deltaTime, newTime:
46644725begin
46654726 // GLScene.CurrentGLCamera.Position := GLDummyCamPos.Position;
46664727 GLCamera.Position := GLDummyCamPos.Position;
4667- if WorldODE.ODEEnable <> False then begin
4728+ if WorldODE.ODEEnable then begin
46684729 QueryPerformanceCounter(t_start);
46694730 t_itot := 0 ;
46704731
@@ -4794,11 +4855,12 @@ procedure TFViewer.GLCadencerProgress(Sender: TObject; const deltaTime, newTime:
47944855 with WorldODE.Robots[r] do begin
47954856 // if not active then continue; //TODO
47964857 theta := Axes[i].GetPos();
4797- w := Axes[i].GetSpeed();
4858+ w := Axes[i].GetSpeed(WorldODE.Ode_dt );
47984859 // if not Axes[i].Motor.active then continue; //TODO
47994860
4861+ Axes[i].TotalTorque := 0 ;
48004862 // AxisTorqueModel(Axes[i], Theta, Axes[i].filt_speed, Tq);
4801- AxisTorqueModel(Axes[i], Theta, w, WorldODE.Ode_dt , Tq);
4863+ AxisTorqueModel(Axes[i], Theta, w, WorldODE.Ode_dt, Tq);
48024864 // Apply it to the axis
48034865 Axes[i].AddTorque(Tq);
48044866 // Apply Extra torque
@@ -4904,6 +4966,7 @@ procedure TFViewer.GLCadencerProgress(Sender: TObject; const deltaTime, newTime:
49044966 t_itot := t_itot + t_i2 - t_i1;
49054967
49064968 // Post Process Sensors
4969+
49074970 for i := 0 to WorldODE.Sensors.Count - 1 do begin
49084971 with WorldODE.Sensors[i] do begin
49094972 PostProcess;
@@ -5158,6 +5221,7 @@ procedure TFViewer.FormShow(Sender: TObject);
51585221 FParams.BSetTrailParsClick(Sender);
51595222
51605223 FParams.ShowParsedScene;
5224+ FParams.BSetFPSClick(Sender);
51615225
51625226 MakeFullyVisible();
51635227 UpdateGLScene;
0 commit comments