1Make a spider robot in SolidWorks and simulate it {#tutorial_pychrono_demo_spider_robot} 2========================== 3 4This demo is about the simulation of a crawling spider robot with six legs, 5where we control the motion of the legs with 18 actuators. 6 7![](http://projectchrono.org/assets/manual/Tutorial_spider_robot.jpg) 8 9In deail, one performs the following steps: 10- Use SolidWorks to make a 3D CAD model of the crawling robot, 11- export it as a .pyfile using the Chrono::SolidWorks add-in; ex. use the name **spider\_robot.py** 12- create a Python program, ex. use the name **demo\_spider.py**, using the functions of [PyChrono](@ref pychrono_introduction) to load and simulate spider\_robot.py. 13 14For your convenience, the CAD model, the converted **spider\_robot.py** model, and the **demo\_spider.py** program are all available in the following archive: 15 16 17[spider_robot.zip](http://projectchrono.org/assets/downloads/spider_robot.zip). 18 19 20The following is the complete listing of **demo\_spider.py** (it must stay in the same directory where you exported your CAD model with the name **spider\_robot.py**) 21 22Note how we used **mybody = mysystem.SearchBody('...')**; and **mymarker = mybody.SearchMarker('...');** to retrieve object pointers from their names in the 3D CAD model. Also note that a part that shows as *M-410iB-300 -1/ArmBase\<1\>* in the GUI of SolidWorks, becomes *M-410iB-300 -1/ArmBase-1* for the Python side; i.e. the \<N\> suffix becomes -N. 23 24Finally, note how we used ChFunction objects to build some basic loop motions for the actuators, in prescribed rotation mode. 25 26 27<span style="color:red;font-weight:bold">ATTENTION!</span> The source code listed below may not be compatible with your current version of PyChrono and may need to be slightly adjusted to reflect any recent API changes. 28 29~~~~~~~~~~~~~{.py} 30 31 32 33import os 34import math 35import pychrono as chrono 36import pychrono.postprocess as postprocess 37import pychrono.irrlicht as chronoirr 38 39# class to use ChLinkMotorRotationAngle given the markers from the CAD 40class SpiderRobotMotor(chrono.ChLinkMotorRotationAngle): 41 def __init__(self): 42 super().__init__() 43 self.bodylist = [] 44 def Initialize(self, mark1, mark2): 45 body1 = mark1.GetBody() 46 body2 = mark2.GetBody() 47 self.bodylist.append([body1, body2]) 48 frame = mark1.GetAbsFrame() 49 super().Initialize(body1, body2, frame) 50 def Set_rot_funct(self, rotfun): 51 super().SetAngleFunction(rotfun) 52 53print ("Load a model exported by SolidWorks") 54 55 56 57# --------------------------------------------------------------------- 58# 59# Create the simulation system and add items 60# 61 62mysystem = chrono.ChSystemNSC() 63chrono.ChCollisionModel.SetDefaultSuggestedEnvelope(0.05) 64chrono.ChCollisionModel.SetDefaultSuggestedMargin(0.05) 65 66parts = chrono.ImportSolidWorksSystem('./spider_robot') 67 68for ib in parts: 69 mysystem.Add(ib) 70 71# Retrieve objects from their name as saved from the SolidWorks interface 72# (look the spider_robot.py file to guess them, or look their name in SW) 73 74bbody = mysystem.SearchBody('Part3^SPIDER_ROBOT-1') 75bbody.SetBodyFixed(False) 76b1base = mysystem.SearchBody('M-410iB-300 -1/ArmBase-1') 77b1turret = mysystem.SearchBody('M-410iB-300 -1/M-410iB-300-02-1') 78b1bicept = mysystem.SearchBody('M-410iB-300 -1/M-410iB-300-03-1') 79b1forearm = mysystem.SearchBody('M-410iB-300 -1/M-410iB-300-06-1') 80m1_1B = b1base. SearchMarker('marker_M1_B') 81m1_1A = b1turret. SearchMarker('marker_M1_A') 82m1_2B = b1turret. SearchMarker('marker_M2_B') 83m1_2A = b1bicept. SearchMarker('marker_M2_A') 84m1_3B = b1bicept. SearchMarker('marker_M3_B') 85m1_3A = b1forearm.SearchMarker('marker_M3_A') 86b2base = mysystem.SearchBody('M-410iB-300 -2/ArmBase-1') 87b2turret = mysystem.SearchBody('M-410iB-300 -2/M-410iB-300-02-1') 88b2bicept = mysystem.SearchBody('M-410iB-300 -2/M-410iB-300-03-1') 89b2forearm = mysystem.SearchBody('M-410iB-300 -2/M-410iB-300-06-1') 90m2_1B = b2base. SearchMarker('marker_M1_B') 91m2_1A = b2turret. SearchMarker('marker_M1_A') 92m2_2B = b2turret. SearchMarker('marker_M2_B') 93m2_2A = b2bicept. SearchMarker('marker_M2_A') 94m2_3B = b2bicept. SearchMarker('marker_M3_B') 95m2_3A = b2forearm.SearchMarker('marker_M3_A') 96b3base = mysystem.SearchBody('M-410iB-300 -3/ArmBase-1') 97b3turret = mysystem.SearchBody('M-410iB-300 -3/M-410iB-300-02-1') 98b3bicept = mysystem.SearchBody('M-410iB-300 -3/M-410iB-300-03-1') 99b3forearm = mysystem.SearchBody('M-410iB-300 -3/M-410iB-300-06-1') 100m3_1B = b3base. SearchMarker('marker_M1_B') 101m3_1A = b3turret. SearchMarker('marker_M1_A') 102m3_2B = b3turret. SearchMarker('marker_M2_B') 103m3_2A = b3bicept. SearchMarker('marker_M2_A') 104m3_3B = b3bicept. SearchMarker('marker_M3_B') 105m3_3A = b3forearm.SearchMarker('marker_M3_A') 106b7base = mysystem.SearchBody('M-410iB-300 -7/ArmBase-1') 107b7turret = mysystem.SearchBody('M-410iB-300 -7/M-410iB-300-02-1') 108b7bicept = mysystem.SearchBody('M-410iB-300 -7/M-410iB-300-03-1') 109b7forearm = mysystem.SearchBody('M-410iB-300 -7/M-410iB-300-06-1') 110m7_1B = b7base. SearchMarker('marker_M1_B') 111m7_1A = b7turret. SearchMarker('marker_M1_A') 112m7_2B = b7turret. SearchMarker('marker_M2_B') 113m7_2A = b7bicept. SearchMarker('marker_M2_A') 114m7_3B = b7bicept. SearchMarker('marker_M3_B') 115m7_3A = b7forearm.SearchMarker('marker_M3_A') 116b8base = mysystem.SearchBody('M-410iB-300 -8/ArmBase-1') 117b8turret = mysystem.SearchBody('M-410iB-300 -8/M-410iB-300-02-1') 118b8bicept = mysystem.SearchBody('M-410iB-300 -8/M-410iB-300-03-1') 119b8forearm = mysystem.SearchBody('M-410iB-300 -8/M-410iB-300-06-1') 120m8_1B = b8base. SearchMarker('marker_M1_B') 121m8_1A = b8turret. SearchMarker('marker_M1_A') 122m8_2B = b8turret. SearchMarker('marker_M2_B') 123m8_2A = b8bicept. SearchMarker('marker_M2_A') 124m8_3B = b8bicept. SearchMarker('marker_M3_B') 125m8_3A = b8forearm.SearchMarker('marker_M3_A') 126b9base = mysystem.SearchBody('M-410iB-300 -9/ArmBase-1') 127b9turret = mysystem.SearchBody('M-410iB-300 -9/M-410iB-300-02-1') 128b9bicept = mysystem.SearchBody('M-410iB-300 -9/M-410iB-300-03-1') 129b9forearm = mysystem.SearchBody('M-410iB-300 -9/M-410iB-300-06-1') 130m9_1B = b9base. SearchMarker('marker_M1_B') 131m9_1A = b9turret. SearchMarker('marker_M1_A') 132m9_2B = b9turret. SearchMarker('marker_M2_B') 133m9_2A = b9bicept. SearchMarker('marker_M2_A') 134m9_3B = b9bicept. SearchMarker('marker_M3_B') 135m9_3A = b9forearm.SearchMarker('marker_M3_A') 136 137 138 139period = 2 140mfunc_sineS = chrono.ChFunction_Sine(0, 1.0/period, 0.2) # phase, frequency, amplitude 141mfunc_swingSa = chrono.ChFunction_Repeat() 142mfunc_swingSa.Set_fa(mfunc_sineS) 143mfunc_swingSa.Set_window_length(period) 144mfunc_swingSa.Set_window_start(0) 145mfunc_swingSb = chrono.ChFunction_Repeat() 146mfunc_swingSb.Set_fa(mfunc_sineS) 147mfunc_swingSb.Set_window_length(period) 148mfunc_swingSb.Set_window_start(period/2.0) 149mfunc_sineD = chrono.ChFunction_Sine(0, 1.0/period, -0.2) # phase, frequency, amplitude 150mfunc_swingDb = chrono.ChFunction_Repeat() 151mfunc_swingDb.Set_fa(mfunc_sineD) 152mfunc_swingDb.Set_window_length(period) 153mfunc_swingDb.Set_window_start(period/2.0) 154mfunc_swingDa = chrono.ChFunction_Repeat() 155mfunc_swingDa.Set_fa(mfunc_sineD) 156mfunc_swingDa.Set_window_length(period) 157mfunc_swingDa.Set_window_start(0) 158 159 160mfunc_sigma = chrono.ChFunction_Sigma() 161mfunc_sigma.Set_amp(-0.2) 162mfunc_sigma.Set_end(0.5) 163mfunc_const = chrono.ChFunction_Const() 164mfunc_sigmb = chrono.ChFunction_Sigma() 165mfunc_sigmb.Set_amp(0.2) 166mfunc_sigmb.Set_end(0.5) 167mfunc_seq = chrono.ChFunction_Sequence() 168mfunc_seq.InsertFunct(mfunc_sigma, 0.5, 1, True) # fx, duration, weight, C0 continuity 169mfunc_seq.InsertFunct(mfunc_const, 1.0, 1, True) # fx, duration, weight, C0 continuity 170mfunc_seq.InsertFunct(mfunc_sigmb, 0.5, 1, True) # fx, duration, weight, C0 continuity 171mfunc_updownA = chrono.ChFunction_Repeat() 172mfunc_updownA.Set_fa(mfunc_seq) 173mfunc_updownA.Set_window_length(period) 174mfunc_updownB = chrono.ChFunction_Repeat() 175mfunc_updownB.Set_fa(mfunc_seq) 176mfunc_updownB.Set_window_length(period) 177mfunc_updownB.Set_window_phase(period/2.0) 178 179# Add actuators to Leg n.1 180 181motor1_1 = SpiderRobotMotor() 182motor1_1.Initialize(m1_1A, m1_1B) 183motor1_1.Set_rot_funct(mfunc_swingSa) 184mysystem.Add(motor1_1) 185 186motor1_2 = SpiderRobotMotor() 187motor1_2.Initialize(m1_2A, m1_2B) 188motor1_2.Set_rot_funct(mfunc_updownA) 189mysystem.Add(motor1_2) 190 191motor1_3 = SpiderRobotMotor() 192motor1_3.Initialize(m1_3A, m1_3B) 193motor1_3.Set_rot_funct(mfunc_const) 194mysystem.Add(motor1_3) 195 196# Add actuators to Leg n.2 197 198motor2_1 = SpiderRobotMotor() 199motor2_1.Initialize(m2_1A, m2_1B) 200motor2_1.Set_rot_funct(mfunc_swingSb) 201mysystem.Add(motor2_1) 202 203motor2_2 = SpiderRobotMotor() 204motor2_2.Initialize(m2_2A, m2_2B) 205motor2_2.Set_rot_funct(mfunc_updownB) 206mysystem.Add(motor2_2) 207 208motor2_3 = SpiderRobotMotor() 209motor2_3.Initialize(m2_3A, m2_3B) 210motor2_3.Set_rot_funct(mfunc_const) 211mysystem.Add(motor2_3) 212 213# Add actuators to Leg n.3 214 215motor3_1 = SpiderRobotMotor() 216motor3_1.Initialize(m3_1A, m3_1B) 217motor3_1.Set_rot_funct(mfunc_swingSa) 218mysystem.Add(motor3_1) 219 220motor3_2 = SpiderRobotMotor() 221motor3_2.Initialize(m3_2A, m3_2B) 222motor3_2.Set_rot_funct(mfunc_updownA) 223mysystem.Add(motor3_2) 224 225motor3_3 = SpiderRobotMotor() 226motor3_3.Initialize(m3_3A, m3_3B) 227motor3_3.Set_rot_funct(mfunc_const) 228mysystem.Add(motor3_3) 229 230# Add actuators to Leg n.9 231 232motor9_1 = SpiderRobotMotor() 233motor9_1.Initialize(m9_1A, m9_1B) 234motor9_1.Set_rot_funct(mfunc_swingDb) 235mysystem.Add(motor9_1) 236 237motor9_2 = SpiderRobotMotor() 238motor9_2.Initialize(m9_2A, m9_2B) 239motor9_2.Set_rot_funct(mfunc_updownB) 240mysystem.Add(motor9_2) 241 242motor9_3 = SpiderRobotMotor() 243motor9_3.Initialize(m9_3A, m9_3B) 244motor9_3.Set_rot_funct(mfunc_const) 245mysystem.Add(motor9_3) 246 247# Add actuators to Leg n.8 248 249motor8_1 = SpiderRobotMotor() 250motor8_1.Initialize(m8_1A, m8_1B) 251motor8_1.Set_rot_funct(mfunc_swingDa) 252mysystem.Add(motor8_1) 253 254motor8_2 = SpiderRobotMotor() 255motor8_2.Initialize(m8_2A, m8_2B) 256motor8_2.Set_rot_funct(mfunc_updownA) 257mysystem.Add(motor8_2) 258 259motor8_3 = SpiderRobotMotor() 260motor8_3.Initialize(m8_3A, m8_3B) 261motor8_3.Set_rot_funct(mfunc_const) 262mysystem.Add(motor8_3) 263 264# Add actuators to Leg n.7 265 266motor7_1 = SpiderRobotMotor() 267motor7_1.Initialize(m7_1A, m7_1B) 268motor7_1.Set_rot_funct(mfunc_swingDb) 269mysystem.Add(motor7_1) 270 271motor7_2 = SpiderRobotMotor() 272motor7_2.Initialize(m7_2A, m7_2B) 273motor7_2.Set_rot_funct(mfunc_updownB) 274mysystem.Add(motor7_2) 275 276motor7_3 = SpiderRobotMotor() 277motor7_3.Initialize(m7_3A, m7_3B) 278motor7_3.Set_rot_funct(mfunc_const) 279mysystem.Add(motor7_3) 280 281# 282# Create a floor 283 284mfloor = chrono.ChBody() 285mfloor.SetBodyFixed(True) 286mfloor.GetCollisionModel().ClearModel() 287mymat = chrono.ChMaterialSurfaceNSC() 288mymat.SetRestitution(0.0) 289mfloor.GetCollisionModel().AddBox(mymat, 10,0.5,10, chrono.ChVectorD(0,0.8,0)) 290mfloor.GetCollisionModel().BuildModel() 291mfloor.SetCollide(True) 292mysystem.Add(mfloor) 293 294mfloorshape = chrono.ChBoxShape() 295mfloorshape.GetBoxGeometry().Size = chrono.ChVectorD(10,0.5,10) 296mfloorshape.GetBoxGeometry().Pos = chrono.ChVectorD(0,0.8,0) 297mfloor.AddAsset(mfloorshape) 298 299mfloorcolor = chrono.ChColorAsset(0.2,0.2,0.2) 300mfloor.AddAsset(mfloorcolor) 301 302# --------------------------------------------------------------------- 303# 304# Create an Irrlicht application to visualize the system 305# 306 307myapplication = chronoirr.ChIrrApp(mysystem, 'Test', chronoirr.dimension2du(1280,720)) 308 309myapplication.AddTypicalSky('./data/skybox/') 310myapplication.AddTypicalCamera(chronoirr.vector3df(2.8,2.6,2.8),chronoirr.vector3df(0.0,2.6,0.0)) 311myapplication.AddTypicalLights() 312myapplication.AddLightWithShadow(chronoirr.vector3df(10,20,10),chronoirr.vector3df(0,2.6,0), 10 ,10,40, 60, 512) 313 314 # ==IMPORTANT!== Use this function for adding a ChIrrNodeAsset to all items 315 # in the system. These ChIrrNodeAsset assets are 'proxies' to the Irrlicht meshes. 316 # If you need a finer control on which item really needs a visualization proxy in 317 # Irrlicht, just use application.AssetBind(myitem) on a per-item basis. 318 319myapplication.AssetBindAll() 320 321 # ==IMPORTANT!== Use this function for 'converting' into Irrlicht meshes the assets 322 # that you added to the bodies into 3D shapes, they can be visualized by Irrlicht! 323 324myapplication.AssetUpdateAll() 325 326 # ==IMPORTANT!== Use this function for enabling cast soft shadows 327 328myapplication.AddShadowAll() 329 330# --------------------------------------------------------------------- 331# 332# Run the simulation 333# 334solver = chrono.ChSolverBB() 335solver.SetMaxIterations(200) 336mysystem.SetSolver(solver) 337myapplication.SetTimestep(0.001) 338 339 340while(myapplication.GetDevice().run()): 341 myapplication.BeginScene() 342 myapplication.DrawAll() 343 myapplication.DoStep() 344 myapplication.EndScene() 345 346~~~~~~~~~~~~~ 347