This commit is contained in:
LiangShiyun 2025-06-12 20:06:35 +08:00
parent 4441f03110
commit af42d0c71b
473 changed files with 112 additions and 78 deletions

View File

@ -1990,6 +1990,7 @@ class TaskBase(smach.State):
use_algorithm = self.resources.use_algorithm
if self.resources.choose_task != "ion" and self.resources.motion_task[5] == "point":
self.resources.use_algorithm = "hybridPid"
print("self.resources.use_algorithm:",self.resources.use_algorithm)
code = self.resources.robot.move_to_point(pose=self.resources.target_points, t=self.resources.motion_task[6], timeout=0.5, interpolation="circle", algorithm=self.resources.use_algorithm,is_interrupt=False,is_switch_controller = self.resources.is_switch_controller)
self.resources.use_algorithm = use_algorithm
else:

View File

@ -74,6 +74,8 @@ except:
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import select
current_file_path = os.path.abspath(__file__)
MassageRobot_Dobot_Path = os.path.dirname(os.path.dirname(os.path.dirname(current_file_path)))
print(MassageRobot_Dobot_Path)
@ -165,17 +167,17 @@ class MassageRobot:
self.adjust_wrench = np.zeros(6,dtype=np.float64)
self.skip_pos = np.zeros(6,dtype=np.float64)
#按摩头参数暂时使用本地数据
# massage_head_dir = self.arm_config['massage_head_dir']
# all_items = os.listdir(massage_head_dir)
# head_config_files = [f for f in all_items if os.path.isfile(os.path.join(massage_head_dir, f))]
# self.playload_dict = {}
# for file in head_config_files:
# file_address = massage_head_dir + '/' + file
# play_load = read_yaml(file_address)
# self.playload_dict[play_load['name']] = play_load
# 按摩头参数暂时使用本地数据
massage_head_dir = self.arm_config['massage_head_dir']
all_items = os.listdir(massage_head_dir)
head_config_files = [f for f in all_items if os.path.isfile(os.path.join(massage_head_dir, f))]
self.playload_dict = {}
for file in head_config_files:
file_address = massage_head_dir + '/' + file
play_load = read_yaml(file_address)
self.playload_dict[play_load['name']] = play_load
self.playload_dict = self.vtxdb.get("robot_config", "massage_head")
# self.playload_dict = self.vtxdb.get("robot_config", "massage_head")
# print(self.playload_dict)
self.current_head = 'none'
self.is_waitting = False
@ -196,9 +198,13 @@ class MassageRobot:
self.x_tcp = np.zeros(6)
self.P_tcp = np.eye(6)
# 过程噪声协方差矩阵
self.Q_tcp = np.eye(6) * 0.01
# self.Q_tcp = np.eye(6) * 0.01
self.Q_tcp = np.eye(6) * 0.05
# 测量噪声协方差矩阵
self.R_tcp = np.eye(6) * 0.1
# self.R_tcp = np.eye(6) * 0.1
self.R_tcp = np.diag([0.5, 0.5, 0.5, 0.05, 0.05, 0.05])
# 传感器故障计数器
self.sensor_fail_count = 0
# 机械臂初始化,适配中间层
@ -421,7 +427,8 @@ class MassageRobot:
self.logger.log_blue(f"current position and orientation:{self.arm_state.arm_position},{self.arm_state.arm_orientation}")
self.logger.log_yellow("---------------------change----------------------")
self.arm.change_end_effector(self.playload_dict[name])
self.logger.log_info(f"切换到{name}按摩头")
self.logger.log_info(f"切换到{name}按摩头,{self.arm.tcp_offset}")
R_matrix = R.from_euler('xyz',self.ready_pose[3:] ,degrees=False).as_matrix()
ready_position = self.ready_pose[:3] + R_matrix @ self.playload_dict[self.current_head]['tcp_offset'][:3]
ready_orientation = R_matrix @ R.from_euler('xyz',self.playload_dict[self.current_head]['tcp_offset'][3:],degrees=False).as_matrix()
@ -563,7 +570,7 @@ class MassageRobot:
pose_processed[:3] = temp_pose[:3] - target_matrix @ np.array(self.arm.tcp_offset[:3])*1000
pose_processed[3:] = R.from_matrix(target_matrix).as_euler("xyz",degrees = True)
print(f"pose_processed:{pose_processed},{self.arm_state.arm_position_command * 1000}")
# print(f"pose_processed:{pose_processed},{self.arm_state.arm_position_command * 1000}")
tcp_command = (
f"ServoP({pose_processed[0]:.3f},{pose_processed[1]:.3f},"
@ -647,11 +654,11 @@ class MassageRobot:
self.arm_state.arm_orientation = quat_rot
for i in range(20):
self.controller_manager.step(self.control_rate.to_sec())
self.logger.log_blue(f"position command: {self.arm_state.arm_position_command}")
self.logger.log_blue(f"orientation command: {R.from_quat(self.arm_state.arm_orientation_command).as_euler('xyz',degrees=True)}")
# self.logger.log_blue(f"position command: {self.arm_state.arm_position_command}")
# self.logger.log_blue(f"orientation command: {R.from_quat(self.arm_state.arm_orientation_command).as_euler('xyz',degrees=True)}")
position, quat_rot = self.arm.get_arm_position()
self.logger.log_blue(f"position current:{position}")
self.logger.log_blue(f"orientation current: {R.from_quat(quat_rot).as_euler('xyz',degrees=False)}")
# self.logger.log_blue(f"position current:{position}")
# self.logger.log_blue(f"orientation current: {R.from_quat(quat_rot).as_euler('xyz',degrees=False)}")
# print("self.arm.feedbackData.robotMode:",self.arm.feedbackData.robotMode)
self.command_rate.precise_sleep()
@ -678,6 +685,9 @@ class MassageRobot:
self.interrupt_event.clear()
self.arm_control_thread.join()
self.arm_measure_thread.join()
# clear_time = time.time()
# self.clear_socket_buffer(self.arm.dashboard.socket_dobot)
# print(f"==={time.time()-clear_time}===")
def stop(self):
for i in range(3):
@ -691,6 +701,21 @@ class MassageRobot:
# else:
# self.logger.log_error(f"未找到{name}按摩头")
# def clear_socket_buffer(self, sock):
# # 使用 select 检查 socket 是否有数据
# print("clear_socket_buffer")
# while True:
# ready, _, _ = select.select([sock], [], [], 0)
# if ready:
# try:
# data = sock.recv(4096)
# if not data:
# break # 对方关闭连接
# except BlockingIOError:
# break
# else:
# print("socket_buffer EMPTY")
# break # 没有更多数据了
# def stop(self):
# if not self.exit_event.is_set():
@ -1535,7 +1560,7 @@ class MassageRobot:
pos_traj, quat_traj = spline_interpolate(positions=pose_matrix[:, :3], quaternions=pose_matrix[:, 3:], time_points=time_points, time_step=dt)
elif interpolation == 'circle':
if self.ion is not None:
pos_traj = circle_trajectory(center=pose, radius=0.07,time_points=time_points,time_step=dt,**kwargs)
pos_traj = circle_trajectory(center=pose, radius=0.09,time_points=time_points,time_step=dt,**kwargs)
else:
pos_traj = circle_trajectory(center=pose,time_points=time_points,time_step=dt,**kwargs)
quat_traj = np.tile(R.from_euler('xyz', np.array(pose[0][3:])).as_quat(), (pos_traj.shape[0], 1))
@ -1771,11 +1796,12 @@ if __name__ == "__main__":
robot.force_sensor.set_zero()
time.sleep(0.5)
robot.force_sensor.enable_active_transmission()
robot.set_position(pose = ready_pose)
# robot.set_position(pose = ready_pose)
robot.init_hardwares(ready_pose)
time.sleep(3)
robot.switch_payload("finger_head")
print("111111111111111111111111111111111111111111111111111111111111111111111111111111")
robot.controller_manager.switch_controller('admittance')
# position,quat_rot = robot.arm.get_arm_position()
# euler_rot = R.from_quat(quat_rot).as_euler('xyz')
@ -1787,9 +1813,14 @@ if __name__ == "__main__":
# # robot.arm.move_joint(q = robot.arm.off_pos)
# # robot.arm.move_joint(q = robot.arm.init_pos)
# pose1 = [0.353467,-0.1349880,0.403604,-180.0000*np.pi/180,-30.0000*np.pi/180,0.0042*np.pi/180]
# # robot.set_position(pose = pose1)
# print("arm_position1:",robot.arm.get_arm_position())
# print("end_position1:",robot.arm.get_end_position())
# pose1 = [0.3736677762541832, 0.11722785977006844, 0.3835904171566223, -3.141592653589793, -0.5235987755982988, 7.330382858376184e-05]
# pose1 = [0.4486,0.1172,0.2536,np.pi,-0.5236,0]
pose1 = [0.44866777605267877, 0.11723335755720732, 0.2536866065889565, 2.7069577869199146, -0.7176783797852828, 0.0]
robot.set_position(pose = pose1)
# print("get_pos:",robot.ge)
print("arm_position1:",robot.arm.get_arm_position())
print("end_position1:",robot.arm.get_end_position())
# print("joint1:",robot.arm.getAngel())
# robot.arm.move_joint(q=robot.arm.init_pos)
# # robot.set_position([0.12189544299531646, -0.31364670468715944, 0.00733569473686102, 2.153932270623249, 0.6209756952505509, 0.0])

View File

@ -59,6 +59,8 @@ class HybridAdmitController(BaseController):
wrench_err = self.state.external_wrench_tcp - self.state.desired_wrench
# z方向力导纳控制
self.state.arm_desired_acc[2] = 1/self.M_z * (wrench_err[2] - self.D_z * (self.state.arm_desired_twist[2] - self.state.desired_twist[2]) - self.K_z * self.state.pose_error[2])
# print("self.state.arm_desired_acc[2]:",self.state.arm_desired_acc[2],self.M_z,wrench_err[2],self.K_z,self.D_z)
self.pose_integral_error += self.state.pose_error * dt
# 位控制
self.state.arm_desired_acc[:2] = -self.Kd @ self.state.arm_desired_twist[:2] - self.Kp @ self.state.pose_error[:2] - self.Ki @ self.pose_integral_error[:2]

View File

@ -359,7 +359,7 @@ def resample_curve_strict(points, num_resampled_points):
def circle_trajectory(center, omega=8.0, radius=0.04, reverse=False, time_points=None, time_step=0.01, start_transition_duration=None, end_transition_duration=None):
def circle_trajectory(center, omega=8.0, radius=0.06, reverse=False, time_points=None, time_step=0.01, start_transition_duration=None, end_transition_duration=None):
if time_points is None or len(time_points) < 2:

View File

@ -5,9 +5,9 @@ stiff_rot: [11, 11, 11]
damp_rot: [1.1, 1.1, 1.1]
desired_xi: 1.0
mass_z: [3.0]
mass_z: [7.0]
stiff_z: [0]
damp_z: [30]
damp_z: [75]
# 位控参数
Kp: [20,20]

View File

@ -1,8 +1,8 @@
name: 'hybridAdmit'
mass_z: [3.0]
mass_z: [7.0]
stiff_z: [0]
damp_z: [30]
damp_z: [75]
desired_xi: 1.0
# 位控参数

View File

@ -6,6 +6,7 @@ import json
import threading
import time
from time import sleep
import time
import select
alarmControllerFile = "files/alarmController.json"
@ -153,7 +154,7 @@ class DobotApi:
self.socket_dobot.send(str.encode(string, 'utf-8'))
break
except Exception:
sleep(1)
sleep(0.1)
def wait_reply(self):
"""
@ -161,7 +162,10 @@ class DobotApi:
"""
data = ""
try:
# print("time1:",time.time())
data = self.socket_dobot.recv(1024)
# print("end_time:",time.time())
# print('recvdata:',data)
except Exception as e:
print(e)
self.socket_dobot = self.reConnect(self.ip, self.port)
@ -225,7 +229,10 @@ class DobotApi:
"""
with self.__globalLock:
self.send_data(string)
send_time = time.time()
print(f"send_data:{string}")
recvData = self.wait_reply()
print(f"===={time.time()-send_time}s====recvData:{string}")
if not self.ParseResultId(recvData):
return None
return recvData

View File

@ -307,6 +307,8 @@ class dobot_nova5:
def waitArrival(self, command):
sendCommandID = self.parseResultprocess(command)[1]
# print("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$")
self.logger.log_blue(f"self.feedbackData.robotMode")
# print("self.feedbackData.robotMode6:",self.feedbackData.robotMode)
# print("self.parseResultprocess(command)",self.parseResultprocess(command))
while True:
@ -317,7 +319,7 @@ class dobot_nova5:
self.dashboard.EmergencyStop(mode=1)
return -1
if self.feedbackData.EnableState:
# print("self.feedbackData.robotCurrentCommandID",self.feedbackData.robotCurrentCommandID)
# self.logger.log_blue("self.feedbackData.robotCurrentCommandID",self.feedbackData.robotCurrentCommandID)
if self.feedbackData.robotCurrentCommandID > sendCommandID:
break
else:
@ -341,7 +343,7 @@ class dobot_nova5:
command = self.dashboard.MovJ(*joints_list_deg,1)
if command == None:
return -1
print("###################################")
is_arrived = self.waitArrival(command)
if is_arrived == 0:
# self.dashboard.MovJ()
@ -413,10 +415,13 @@ class dobot_nova5:
cnt = 0
print("self.robotmode3:",self.feedbackData.robotMode)
poses_list_mm_deg = self.__transform_m_rad_2_mm_deg(pose)
# self.feedFour.flush_recv_buffer()
# joint_list = self.getInverseKin(poses_list_mm_deg)
while cnt < max_retry_count:
cnt += 1
print("self.robotmode4:",self.feedbackData.robotMode)
command = self.dashboard.MovJ(*poses_list_mm_deg,0)
# command = self.dashboard.MovJ(*joint_list,1)
if command == None:
return -1
print("self.robotmode5:",self.feedbackData.robotMode)
@ -648,7 +653,7 @@ class dobot_nova5:
pose = [float(x.strip()) for x in pose_str.split(",")]
return pose
def getInverseKin(self,poses_list,user=1,tool=-1,useJointNear=1,JointNear=''):
def getInverseKin(self,poses_list,user=1,tool=-1,useJointNear=0,JointNear=''):
'''
poses_list X Y Z RX RY RZ
useJointNear 0 或不携带 表示 JointNear无效
@ -913,11 +918,9 @@ class dobot_nova5:
return -1, None
def chooseRightFrame(self):
self.chooseBaseFrame(i=1)
# self.chooseEndEffector(i=0)
self.setBaseFrame(i=1, base_i="{0,0,0,0,0,-45}")
return
if __name__ == "__main__":
# print(R.from_euler("xyz", np.array([180, 0, 0]), degrees=True).as_matrix())
@ -925,7 +928,7 @@ if __name__ == "__main__":
dobot = dobot_nova5("192.168.5.1")
dobot.init()
dobot.dashboard.LogExportUSB(0)
# dobot.dashboard.LogExportUSB(0)
# # dobot.move_joint_jog(q=dobot.init_pos)
@ -946,25 +949,25 @@ if __name__ == "__main__":
# joint1 = [-44.8416*np.pi/180, 39.5626*np.pi/180, -80.5683*np.pi/180, -18.0396*np.pi/180, -89.4168*np.pi/180, -90.0026*np.pi/180]
# try:
dobot.start_drag()
# dobot.start_drag()
# # dobot.move_joint(q = joint)
# # dobot.move_joint(q = joint1)
# # pose1 = [0.353467,-0.1349880,0.403604,-180.0000*np.pi/180,-30.0000*np.pi/180,0.0042*np.pi/180]
# pose1 = [0.353467,-0.1349880,0.403604,-180.0000*np.pi/180,-30.0000*np.pi/180,0.0042*np.pi/180]
# # dobot.RunPoint_P_inPose_M_RAD(pose=pose1)
# dobot.RunPoint_P_inPose_M_RAD(pose=pose1)
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
print("joint:",dobot.getAngel())
# robot_thread.join()
dobot.stop_drag()
# dobot.stop_drag()
print("用户中断操作。")
except Exception as e:
print("joint:",dobot.getAngel())
# robot_thread.join()
dobot.stop_drag()
# dobot.stop_drag()
print("Exception occurred at line:", e.__traceback__.tb_lineno)
print("发生异常:", e)
# # dobot.RunPoint_P_inJoint(posJ)

View File

@ -1,40 +1,24 @@
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import copy
from scipy.spatial.transform import Rotation as R
import math
# 定义你的坐标系(原点 + 欧拉角,单位为角度)
frames = [
{"origin": [0, 0, 0], "euler": [0, 0, 0]},
{"origin": [2, 2, 2], "euler": [0, 150, 90]},
{"origin": [3, 3, 3], "euler": [-180, -30, 0]},
]
def draw_frame(ax, origin, rot_matrix, length=0.5):
origin = np.array(origin)
x_axis = origin + rot_matrix @ np.array([length, 0, 0])
y_axis = origin + rot_matrix @ np.array([0, length, 0])
z_axis = origin + rot_matrix @ np.array([0, 0, length])
ax.quiver(*origin, *(x_axis - origin), color='r')
ax.quiver(*origin, *(y_axis - origin), color='g')
ax.quiver(*origin, *(z_axis - origin), color='b')
print(math.sin(math.atan2(0.4,0.84))*0.93)
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.set_box_aspect([1,1,1])
# point = np.array([0.3670603416735574, -0.36714597755113015, -0.8546756909720299])
for frame in frames:
origin = frame["origin"]
euler_deg = frame["euler"]
rotation = R.from_euler('xyz', euler_deg, degrees=True)
rot_matrix = rotation.as_matrix()
draw_frame(ax, origin, rot_matrix)
ax.set_xlim(-1, 3)
ax.set_ylim(-1, 3)
ax.set_zlim(-1, 3)
ax.set_xlabel("X")
ax.set_ylabel("Y")
ax.set_zlabel("Z")
plt.title("Multiple 3D Coordinate Frames (Euler Angles)")
plt.show()
# temp_point = copy.deepcopy(point)
# if point[2]<= 0:
# temp_point[0] = -math.atan2(point[1],-np.sqrt(1-point[1]*point[1]))
# else:
# temp_point[0] = -math.atan2(point[1],np.sqrt(1-point[1]*point[1]))
# temp_point[1] = -math.atan2(point[0], -point[2])
# temp_point[2] = 0
# # temp_point[0] = -math.asin(point[1])
# # temp_point[1] = -math.atan2(-point[0],point[2])
# # temp_point[2] = 0
# print(temp_point)

View File

@ -189,8 +189,8 @@ if __name__ == '__main__':
sensor.disable_active_transmission()
sensor.disable_active_transmission()
atexit.register(sensor.disconnect)
identifier = Identifier(arm=arm,sensor=sensor,config_path="/home/jsfb/jsfb_ws/global_config/massage_head/finger_playload.yaml")
ready_pose = [0.353467*1000,-0.1349880*1000,0.403604*1000,-180.0000,-30.0000,0.0042]
identifier = Identifier(arm=arm,sensor=sensor,config_path="/home/jsfb/jsfb_ws/global_config/massage_head/shockwave_playload.yaml")
ready_pose = [0.403467*1000,-0.1349880*1000,0.423604*1000,-180.0000,-30.0000,0.0042]
# ready_pose = [250.0, -135.0, 344.3392, -180.0, 0.0, -90.0]
time.sleep(1)
identifier.identify_param_auto(ready_pose,15)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 355 KiB

After

Width:  |  Height:  |  Size: 391 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 355 KiB

After

Width:  |  Height:  |  Size: 391 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 355 KiB

After

Width:  |  Height:  |  Size: 391 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 354 KiB

After

Width:  |  Height:  |  Size: 391 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 395 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 395 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 355 KiB

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 395 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 395 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 354 KiB

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 355 KiB

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 395 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 395 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 354 KiB

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 395 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 395 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 354 KiB

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 355 KiB

After

Width:  |  Height:  |  Size: 395 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 395 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 395 KiB

Some files were not shown because too many files have changed in this diff Show More