def RotateComponents(self, theta, axis): '''Rotates all components in the module theta degrees about the provided axis.''' for _, comp in self.components.items(): comp.RotateAxis(theta, axis) if self.refpoint: self.refpoint = MiroAPI.rotateVector(self.refpoint, theta, axis) if self.refcomp: self.refcomp_relpos = MiroAPI.rotateVector(self.refcomp_relpos, theta, axis)
def RotateModuleY(self, angle): '''Rotate a complete module about the Y axis in degrees''' ref = self.GetBaseComponent().GetPosition() for _, comp in self.components.items(): comp.RotateAxis(angle, [0, 1, 0]) dr = comp.GetPosition() - ref if np.linalg.norm(dr) > 0: dr_new = MiroAPI.rotateVector(dr, angle, [0, 1, 0]) comp.MoveToPosition(ref + dr_new)
def RotateAxis(self, theta, axis): '''Rotates the component an angle theta degrees around axis in global coordinates.''' MiroAPI.rotateBody(self.body, rotAngle=theta, rotAxis=axis) for name, linkp in self.linkpoints.items(): linkp_new = MiroAPI.rotateVector(linkp, rotAngle=theta, rotAxis=axis) self.linkpoints.update({ name: MiroAPI.rotateVector(linkp, rotAngle=theta, rotAxis=axis) }) for name, linkd in self.linkdirs.items(): linkd_new = MiroAPI.rotateVector(linkd, rotAngle=theta, rotAxis=axis) self.linkdirs.update({ name: MiroAPI.rotateVector(linkd, rotAngle=theta, rotAxis=axis) })
def ConnectComponents(self, name_A, point_A, name_B, point_B, dist=0, move=True, show_warning=True, link_name=False, lock_link=False): comp_A = self.components[name_A] comp_B = self.components[name_B] if (move): self.GetComponent(name_B).MoveToMatch(point_B, self.GetComponent(name_A), point_A, dist) # Set Link position to the midpoint between the linkpoints linkpos = (comp_A.GetLinkPoint(point_A) + comp_B.GetLinkPoint(point_B)) / 2 # Get both link directions from the components linkdirA = comp_A.GetLinkDir(point_A) linkdirB = comp_B.GetLinkDir(point_B) # If the dot product is negative, then the angle between the links is > 180 degrees and the links are at least somewhat facing if np.linalg.norm(linkdirA) == 0: linkdir = linkdirB elif np.linalg.norm(linkdirB) == 0: linkdir = linkdirA elif np.dot(linkdirA, linkdirB) < 0: linkdir = linkdirA - linkdirB linkdir = linkdir / np.linalg.norm(linkdir) else: linkdir = linkdirA + linkdirB linkdir = linkdir / np.linalg.norm(linkdir) if show_warning: print( 'Warning: Non-facing links. The links between ' + name_A + '.' + point_A + ' and ' + name_B + '.' + point_B + ' are not facing eachother, check linkpoint and object orientation. Consider removing with MiroModule.RemoveHelpers() before running.' ) hinge_link = MiroAPI.LinkBodies_Hinge(comp_A.GetBody(), comp_B.GetBody(), linkpos, linkdir) # Add the link to the module's dictionary of links if link_name: self.links.update({link_name: hinge_link}) else: name = name_A + "." + point_A + "_TO_" + name_B + "." + point_B self.links.update({name: hinge_link}) self.graph_links.append({ 'Source': name_A, 'Target': name_B, 'Weight': 1 }) if lock_link: rotVec = np.array([1, 1, 1]) if np.dot(rotVec, linkdir) / (np.linalg.norm(rotVec) * np.linalg.norm(rotVec)) < 0.01: rotVec = np.array([1, -1, 1]) rotVec = rotVec - np.dot(rotVec, linkdir) * linkdir rotVec = rotVec / np.linalg.norm(rotVec) # 90 degree rotated link to emulate 0-spin link hinge_link = MiroAPI.LinkBodies_Hinge( comp_A.GetBody(), comp_B.GetBody(), linkpos, MiroAPI.rotateVector(linkdir, 90, rotVec)) if link_name: self.links.update({link_name + '_locker': hinge_link}) else: name = name_A + "." + point_A + "_TO_" + name_B + "." + point_B + '_locker' self.links.update({name: hinge_link})
def Set_Camera(self): '''This sets the camera during simulation. For internal usage when the simulation is being run, use SetPerspective to configure the camera before running the simulation.''' if self.freecam: return if self.cycle: self.cam_to_obs = MiroAPI.rotateVector(self.cam_to_obs, self.cycle_angle / self.fps, [0, 1, 0], rotDegrees=False) self.cam_to_obs = (49 * self.cam_to_obs + self.followmod.GetCenterOfMassVelocity()) / 50 self.cam_to_obs = self.cam_to_obs / np.linalg.norm(self.cam_to_obs) self.cam_pos = self.obs_pos - self.cam_to_obs MiroAPI.SetCamera(self.system_list, self.cam_pos, self.obs_pos) if self.follow_default: if np.linalg.norm(self.followmod.GetCenterOfMassVelocity()) > 1e-2: #oldest working #cam_to_obs[0] = cam_to_obs[0] * np.cos(self.follow_angle) #cam_to_obs[1] = cam_to_obs[0] * np.sin(self.follow_angle) #cam_to_obs[2] = cam_to_obs[2] * np.cos(self.follow_angle) self.obs_pos = (12 * self.obs_pos + self.followmod.GetCenterOfMass()) / 13 self.cam_up = (9 * self.cam_up + np.array([0, 1, 0])) / 10 cam_to_obs = ( self.followmod.GetCenterOfMassVelocity() / np.linalg.norm(self.followmod.GetCenterOfMassVelocity())) cam_to_obs *= self.follow_distance cam_pos = self.obs_pos - self.cam_to_obs cam_pos[1] += self.follow_height self.cam_pos = (9 * self.cam_pos + cam_pos) / 10 # good val = 1/2 MiroAPI.SetCamera(self.system_list, self.cam_pos, self.obs_pos, self.cam_up) cam_to_obs = (49 * self.cam_to_obs + cam_to_obs) / (49 + 1) self.cam_to_obs = cam_to_obs if self.camera_sweep: i = self.sweepstep sweep_divs = 100 self.cam_pos = ( (sweep_divs - i) * self.sweep_cam[self.sweepnr - 1] + (i) * self.sweep_cam[self.sweepnr]) / sweep_divs self.obs_pos = ( (sweep_divs - i) * self.sweep_obs[self.sweepnr - 1] + (i) * self.sweep_obs[self.sweepnr]) / sweep_divs MiroAPI.SetCamera(self.system_list, self.cam_pos, self.obs_pos) self.sweepstep += 1 if self.sweepstep > sweep_divs: self.sweepstep = 0 self.sweepnr += 1 if self.sweepnr >= self.sweepsteps: self.camera_sweep = False if not self.cycle and not self.follow: return