Coverage for farmbot_sidecar_starter_pack/functions/movements.py: 100%

68 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-08-31 13:41 -0700

1""" 

2MovementControls class. 

3""" 

4 

5# └── functions/movements.py 

6# ├── [BROKER] get_xyz() 

7# ├── [BROKER] move() 

8# ├── [BROKER] set_home() 

9# ├── [BROKER] find_home() 

10# ├── [BROKER] find_axis_length() 

11# └── [BROKER] check_position() 

12 

13from .broker import BrokerConnect 

14from .information import Information 

15 

16AXES = ["x", "y", "z", "all"] 

17 

18def validate_axis(axis): 

19 """Validate axis.""" 

20 if axis not in AXES: 

21 raise ValueError(f"Invalid axis: {axis} not in {AXES}") 

22 

23class MovementControls(): 

24 """MovementControls class.""" 

25 def __init__(self, state): 

26 self.broker = BrokerConnect(state) 

27 self.info = Information(state) 

28 self.state = state 

29 

30 def move(self, x, y, z): 

31 """Moves to the specified (x, y, z) coordinate.""" 

32 self.state.print_status(description=f"Moving to ({x}, {y}, {z}).") 

33 

34 def axis_overwrite(axis, value): 

35 return { 

36 "kind": "axis_overwrite", 

37 "args": { 

38 "axis": axis, 

39 "axis_operand": { 

40 "kind": "numeric", 

41 "args": { 

42 "number": value 

43 } 

44 } 

45 } 

46 } 

47 

48 move_message = { 

49 "kind": "move", 

50 "args": {}, 

51 "body": [ 

52 axis_overwrite("x", x), 

53 axis_overwrite("y", y), 

54 axis_overwrite("z", z) 

55 ] 

56 } 

57 

58 self.broker.publish(move_message) 

59 

60 def set_home(self, axis="all"): 

61 """Sets the current position as the home position for a specific axis.""" 

62 self.state.print_status(description="Setting home position") 

63 

64 validate_axis(axis) 

65 

66 set_home_message = { 

67 "kind": "zero", 

68 "args": { 

69 "axis": axis 

70 } 

71 } 

72 self.broker.publish(set_home_message) 

73 

74 def find_home(self, axis="all", speed=100): 

75 """Moves the device to the home position for a specified axis.""" 

76 self.state.print_status(description="Finding home position") 

77 

78 validate_axis(axis) 

79 

80 if speed > 100 or speed < 1: 

81 error = "ERROR: Speed constrained to 1-100." 

82 self.state.print_status(description=error, update_only=True) 

83 self.state.error = error 

84 return 

85 

86 message = { 

87 "kind": "find_home", 

88 "args": { 

89 "axis": axis, 

90 "speed": speed 

91 } 

92 } 

93 self.broker.publish(message) 

94 

95 def find_axis_length(self, axis="all"): 

96 """Finds the length of a specified axis.""" 

97 self.state.print_status(description="Finding axis length") 

98 

99 validate_axis(axis) 

100 

101 find_axis_length_message = { 

102 "kind": "calibrate", 

103 "args": { 

104 "axis": axis 

105 } 

106 } 

107 

108 self.broker.publish(find_axis_length_message) 

109 

110 def get_xyz(self): 

111 """Returns the current (x, y, z) coordinates of the FarmBot.""" 

112 self.state.print_status(description="Getting current coordinates") 

113 

114 tree_data = self.info.read_status() 

115 if tree_data is None: 

116 error = "ERROR: No location data available." 

117 self.state.print_status(description=error, update_only=True) 

118 self.state.error = error 

119 return None 

120 position = tree_data["location_data"]["position"] 

121 

122 x_val = position["x"] 

123 y_val = position["y"] 

124 z_val = position["z"] 

125 

126 self.state.print_status(description=f"Current position: {position}.", update_only=True) 

127 return position 

128 

129 def check_position(self, user_x, user_y, user_z, tolerance): 

130 """Verifies position of the FarmBot within specified tolerance range.""" 

131 

132 user_values = {'x': user_x, 'y': user_y, 'z': user_z} 

133 self.state.print_status(description=f"Checking if position is {user_values} with tolerance: {tolerance}.") 

134 

135 actual_vals = self.get_xyz() 

136 

137 if actual_vals is None: 

138 return False 

139 

140 x_val = actual_vals["x"] 

141 y_val = actual_vals["y"] 

142 z_val = actual_vals["z"] 

143 

144 for axis in ['x', 'y', 'z']: 

145 user_value = user_values[axis] 

146 actual_value = actual_vals[axis] 

147 if not actual_value - tolerance <= user_value <= actual_value + tolerance: 

148 self.state.print_status( 

149 description=f"Farmbot is NOT at position.\n Current position: {actual_vals}.", 

150 update_only=True) 

151 return False 

152 

153 self.state.print_status( 

154 description=f"Farmbot is at position: {actual_vals}.", 

155 update_only=True) 

156 return True