018_位置和偏移

本文详细介绍了jQuery中offset(), position(), scrollLeft()和scrollTop()四个方法的使用。offset()返回元素相对于文档的位置,position()返回相对于父元素的位置,scrollLeft()和scrollTop()则分别用于获取和设置元素的滚动条位置。通过实例代码展示了这些方法的用法,帮助理解它们在实际开发中的应用。

1. offset()方法

1.1. offset()方法返回或设置匹配元素相对于文档的偏移(位置)。

1.2. 返回偏移坐标

1.2.1. offset()方法返回第一个匹配元素的偏移坐标。

1.2.2. offset()方法返回的对象包含两个整型属性: top和left, 以像素计。此方法只对可见元素有效。

1.2.3. 语法

$(selector).offset()

1.3. 设置偏移坐标

1.3.1. offset(value)方法设置每个匹配元素的偏移坐标。

1.3.2. 语法

$(selector).offset(value)

1.3.3. 参数

1.4. 使用函数来设置偏移坐标

1.4.1. offset(function(index,oldoffset))使用函数来设置每一个匹配元素的偏移坐标。

1.4.2. 语法

$(selector).offset(function(index,oldoffset))

1.4.3. 参数

1.5. 例子

1.5.1. 代码

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title>offset</title>
		
		<script type="text/javascript" src="jquery.js"></script>
		<script type="text/javascript">
			$(document).ready(function(){
				$('#btn1').click(function(){
					var x = $("p").offset();
    				alert("p元素相对于文档左偏移: " + x.left + " ,上偏移: " + x.top);
				});

				$('#btn2').click(function(){
					$("p:first").offset({left: 10, top: 10});
				});
			});
		</script>
		<style type="text/css">
			* {margin: 0; padding: 0;}
			div {background-color: pink; margin: 10px; padding: 7px;}
			p {margin: 10px; padding: 7px;}
		</style>
	</head>
	<body>
		<div><p style="background-color: red;">offset()方法返回或设置匹配元素相对于文档的偏移(位置)。</p></div>
		<div><p style="background-color: green;">offset()返回第一个匹配元素的偏移坐标。</p></div>
		<button id="btn1">文档的偏移</button> <button id="btn2">设置偏移</button>
	</body>
</html>

1.5.2. 效果图

2. position()方法

2.1. position()方法返回第一个匹配元素相对于父元素的位置(偏移)。

2.2. position()方法返回的对象包含两个整型属性: top和left, 以像素计。

2.3. 此方法只对可见元素有效。

2.4. 语法

$(selector).position()

2.5. 例子

2.5.1. 代码

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title>position()方法</title>
		

		<script type="text/javascript" src="jquery.js"></script>
		<script type="text/javascript">
			$(document).ready(function(){
				$('#btn1').click(function(){
					var x = $("p").position();
    				alert("相对于父元素左边位置: " + x.left + " ,相对于父元素上边位置: " + x.top);
				});

				$('#btn2').click(function(){
					var x = $("#div2 > p").position();
    				alert("相对于父元素左边位置: " + x.left + " ,相对于父元素上边位置: " + x.top);
				});
			});
		</script>
		<style type="text/css">
			* {margin: 0; padding: 0;}
			div {
				width: 600px;
				height: 200px;
			}
			#div1 {
				background: red;
				padding: 10px 20px;
			}
			#div2 {
				background: green;
				position: relative;
			}
			p {
				background: pink;
				width: 300px;
				height: 100px;
			}
			#div2 > p {
				position: absolute;
				top: 30px;
				left: 50px;
			}
		</style>
	</head>
	<body>
		<div id="div1"><p>position()方法返回第一个匹配元素相对于父元素的位置(偏移)。</p></div>
		<div id="div2"><p>position()方法返回的对象包含两个整型属性: top和left, 以像素计。</p></div>
		<br /><button id="btn1">相对于父元素的位置</button> <button id="btn2">绝对定位相对于父元素的位置</button>
	</body>
</html>

2.5.2. 效果图

3. scrollLeft()方法

3.1. scrollLeft()方法返回或设置匹配元素的滚动条的水平位置。

3.2. 滚动条的水平位置指的是从其左侧滚动过的像素数。当滚动条位于最左侧时, 位置是0。

3.3. 该方法对于可见元素和不可见元素均有效。

3.4. 返回水平滚动条位置

3.4.1. scrollLeft()方法返回第一个匹配元素的水平滚动条位置。

3.4.2. 语法

$(selector).scrollLeft()

3.5. 设置水平滚动条位置

3.5.1. scrollLeft(position)方法设置每一个匹配元素的水平滚动条位置。

3.5.2. 语法

$(selector).scrollLeft(position)

3.5.3. 参数

4. scrollTop()方法

4.1. scrollTop()方法返回或设置匹配元素的滚动条的垂直位置。

4.2. 滚动条的垂直位置指的是从其顶部滚动过的像素数。当滚动条位于最顶部时, 位置是0。

4.3. 该方法对于可见元素和不可见元素均有效。

4.4. 返回垂直滚动条位置

4.4.1. scrollTop()方法返回第一个匹配元素的垂直滚动条位置。

4.4.2. 语法

$(selector).scrollTop()

4.5. 设置垂直滚动条位置

4.5.1. scrollTop(offset)方法设置每一个匹配元素的垂直滚动条位置。

4.5.2. 语法

$(selector).scrollTop(offset)

4.5.3. 参数

4.6. 例子

4.6.1. 代码

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title>scrollLeft()和scrollTop()方法</title>
		
		<script type="text/javascript" src="jquery.js"></script>
		<script type="text/javascript">
			$(document).ready(function(){
				$('#btn1').click(function(){
    				alert("第一个div左边滚动条的位置: " + $("div").scrollLeft() + " ,第一个div上边滚动条的位置: " + $("div").scrollTop());
				});
				$('#btn2').click(function(){
					$("div").scrollLeft(20);
					$("div").scrollTop(50);
				});
			});
		</script>
		<style type="text/css">
			div {
				width: 200px;
				height: 200px;
				background: red;
				overflow: auto;
			}
		</style>
	</head>
	<body>
		<div>
			<p>
				<h2>scrollLeft()方法</h2>
				1. scrollLeft()方法返回或设置匹配元素的滚动条的水平位置。<br />
				2. 滚动条的水平位置指的是从其左侧滚动过的像素数。当滚动条位于最左侧时, 位置是0。
				<h3>返回水平滚动条位置</h3>
				1. scrollLeft()方法返回第一个匹配元素的水平滚动条位置。<br />
				2. 语法<br />
				$(selector).scrollLeft()
				<h3>设置水平滚动条位置</h3>
				1. scrollLeft(position)方法设置每一个匹配元素的水平滚动条位置。<br />
				2. 语法<br />
				$(selector).scrollLeft(position)
			</p>
		</div>
		<div>
			<p>
				<h2>scrollTop()方法</h2>
				1. scrollTop()方法返回或设置匹配元素的滚动条的垂直位置。<br />
				2. 滚动条的垂直位置指的是从其顶部滚动过的像素数。当滚动条位于最顶部时, 位置是0。
				<h3>返回垂直滚动条位置</h3>
				1. scrollTop()方法返回第一个匹配元素的垂直滚动条位置。<br />
				2. 语法<br />
				$(selector).scrollTop()
				<h3>设置垂直滚动条位置</h3>
				1. scrollTop(offset)方法设置每一个匹配元素的垂直滚动条位置。<br />
				2. 语法<br />
				$(selector).scrollTop(offset)
			</p>
		</div>
		<br /><button id="btn1">返回滚动条的位置</button> <button id="btn2">设置滚动条的位置</button>
	</body>
</html>

4.6.2. 效果图

 

这是完整代码,利用你刚刚提出的方法帮我修改并给我一个完整的代码import time, math, cv2, numpy as np, logging from XRobot.envs import RobotEnv from XRobot.commons.cv_utils import get_cam_intrinsic import XRobot.commons.transform as T logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) # ---------- 参数 ---------- CUBE_PICK_Z_W = 0.004 # 低夹取 NUT_PICK_Z_W = 0.002 Z_SAFE = 0.30 Z_PLACE_FINAL = 0.018 DROP_SMOOTH = 200 DROP_PAUSE = 50 # ✅ 合并红色橙色为同一类别 COLOR_RANGES = { "red_orange": [ ([0, 15, 15], [40, 255, 255]), # 更宽的范围,降低饱度/明度阈值 ([160, 15, 15], [180, 255, 255]) ], # "red_orange": [([0, 20, 20], [10, 255, 255]), ([165, 20, 20], [180, 255, 255])], # 合并红橙 "green": [([35, 20, 20], [85, 255, 255])], "blue": [([100, 20, 20], [130, 255, 255])], } CUBE_MIN, TARGET_MIN = 150, 600 # ---------- 坐标转换 ---------- def get_pos_world(point_img, target_z_w): K_full = get_cam_intrinsic() K = K_full[:3, :3] if K_full.shape == (4, 4) or K_full.shape == (3, 4) else K_full K_inv = np.linalg.inv(K) T_matrix = np.array([[0, 1, 0, 0.5], [-1, 0, 0, 0], [0, 0, -1, 0.98], [0, 0, 0, 1]]) ray_c = np.dot(K_inv, np.array(point_img, dtype=np.float32).reshape(3, 1)).flatten() R_wc, t_wc = T_matrix[:3, :3], T_matrix[:3, 3] alpha = (target_z_w - t_wc[2]) / (R_wc[2, :] @ ray_c + 1e-6) P_w = R_wc @ (alpha * ray_c) + t_wc return P_w[0], P_w[1] # ---------- 视觉:长边中点 + 垂直角度 ---------- def get_objects_and_targets_pose(cv_image): hsv = cv2.cvtColor(cv_image, cv2.COLOR_RGB2HSV) # ✅ 修改目标存储结构,支持多个同色目标 res = { 'cubes': [], 'square_nut': None, 'targets': { 'red_orange': [], # 改为列表,存储多个目标位置 'green': [], 'blue': [], 'basket': None } } img_cx = cv_image.shape[1] // 2 for color, ranges in COLOR_RANGES.items(): mask = np.zeros(cv_image.shape[:2], dtype=np.uint8) for (l, h) in ranges: mask = cv2.bitwise_or(mask, cv2.inRange(hsv, np.array(l), np.array(h))) mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, np.ones((5, 5), np.uint8)) cnts, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) for c in cnts: area = cv2.contourArea(c) M = cv2.moments(c) if M["m00"] == 0: continue cx, cy = int(M["m10"] / M["m00"]), int(M["m01"] / M["m00"]) if cx < img_cx and CUBE_MIN <= area < TARGET_MIN: rect = cv2.minAreaRect(c) (rc_x, rc_y), (w, h), ang = rect # ✅ 长边中点 + 垂直角度 long_edge_vec = np.array([math.cos(ang * math.pi / 180), math.sin(ang * math.pi / 180)]) long_edge_len = max(w, h) mid_offset = long_edge_vec * long_edge_len * 0.5 pick_px = rc_x + mid_offset[0] pick_py = rc_y + mid_offset[1] x_w, y_w = get_pos_world(np.array([pick_px, pick_py, 1.0]), CUBE_PICK_Z_W) if x_w is None: continue grip_yaw = ang * math.pi / 180.0 + math.pi / 2 if grip_yaw > math.pi: grip_yaw -= 2 * math.pi if grip_yaw <= -math.pi: grip_yaw += 2 * math.pi res['cubes'].append((color, x_w, y_w, grip_yaw)) elif cx >= img_cx and area >= TARGET_MIN: x_w, y_w = get_pos_world(np.array([cx, cy, 1.0]), 0.00) if x_w is None: continue # ✅ 改为追加到列表,而不是覆盖 res['targets'][color].append((x_w, y_w)) # 2. 方形螺母(逻辑保留) gray = cv2.cvtColor(cv_image, cv2.COLOR_RGB2GRAY) _, nut_mask = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU) nut_mask = cv2.morphologyEx(nut_mask, cv2.MORPH_OPEN, np.ones((5, 5), np.uint8)) cnts_nut, _ = cv2.findContours(nut_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) nut_candidates = [] for c in cnts_nut: area = cv2.contourArea(c) M = cv2.moments(c) if M["m00"] == 0: continue cx = int(M["m10"] / M["m00"]) if cx >= img_cx or area < 50 or area > 2000: continue cy = int(M["m01"] / M["m00"]) peri = cv2.arcLength(c, True) approx = cv2.approxPolyDP(c, 0.04 * peri, True) rect = cv2.minAreaRect(approx if len(approx) >= 4 else c) x_w, y_w = get_pos_world(np.array([cx, cy, 1.0]), 0.03) if x_w is None: continue angle = rect[2] if rect[1][0] < rect[1][1]: angle += 90 yaw = angle * math.pi / 180 corners = [] for pt in (approx if len(approx) >= 4 else c): px, py = pt[0] x_c, y_c = get_pos_world(np.array([px, py, 1.0]), 0.03) if x_c is not None: corners.append((x_c, y_c)) if not corners: continue protrusion = max(corners, key=lambda p: (p[0] - x_w) ** 2 + (p[1] - y_w) ** 2) dx, dy = protrusion[0] - x_w, protrusion[1] - y_w grab_yaw = math.atan2(dy, dx) + math.pi / 2 if grab_yaw > math.pi: grab_yaw -= 2 * math.pi if grab_yaw <= -math.pi: grab_yaw += 2 * math.pi nut_candidates.append({'area': area, 'pose': (x_w, y_w, yaw), 'grab': (protrusion[0], protrusion[1], grab_yaw)}) if nut_candidates: best = max(nut_candidates, key=lambda x: x['area']) res['square_nut'] = best # 3. 篮子(逻辑保留) canny = cv2.Canny(gray, 10, 10) closed = cv2.morphologyEx(canny, cv2.MORPH_CLOSE, np.ones((8, 8), np.uint8)) cnts_b, _ = cv2.findContours(closed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) best_basket = None; max_area = 0 for c in cnts_b: if cv2.contourArea(c) < 500: continue rect = cv2.minAreaRect(c) cx, cy = rect[0] if cx < img_cx: continue x_w, y_w = get_pos_world(np.array([cx, cy, 1.0]), 0.00) if x_w is None: continue if abs(y_w) < 0.10: y_w = -0.01 if rect[1][0] * rect[1][1] > max_area: max_area = rect[1][0] * rect[1][1] best_basket = (x_w, y_w) res['targets']['basket'] = best_basket if best_basket else (0.50, -0.01) return res # ---------- 运动:更低夹取 + 超缓降 ---------- def move_and_grasp(env, pos, yaw, z_pick, z_safe=0.30, lift_after=True): x, y = pos q = T.euler_2_quat(np.array([0, 0, yaw])) action = np.array([x, y, z_safe, q[3], q[0], q[1], q[2]]) # 1. 安全高度 for _ in range(200): env.robot.end['arm0'].open(); env.step(action) # 2. 超缓降 action_end = action.copy() action_end[2] = z_pick for i in range(200): act = action.copy() act[2] = action[2] + (action_end[2] - action[2]) * (i / 200) env.robot.end['arm0'].open(); env.step(act) # 3. 末端稳释 for _ in range(50): env.robot.end['arm0'].open(); env.step(action_end) # 4. 夹取 for _ in range(50): env.robot.end['arm0'].close(); env.step(action_end) # 5. 抬升 if lift_after: action[2] = z_safe for _ in range(100): env.step(action) return action def move_and_place_gentle(env, pos, z_place=0.018, z_safe=0.30): x, y = pos q = T.euler_2_quat(np.array([0, 0, 0])) action = np.array([x, y, z_safe, q[3], q[0], q[1], q[2]]) # 1. 平移 for _ in range(200): env.step(action) # 2. 超缓降 action_end = action.copy() action_end[2] = z_place for i in range(200): act = action.copy() act[2] = action[2] + (action_end[2] - action[2]) * (i / 200) env.step(act) # 3. 末端稳释 for _ in range(50): env.robot.end['arm0'].open(); env.step(action_end) # 4. 释放 for _ in range(50): env.robot.end['arm0'].open(); env.step(action_end) # 5. 温柔抬离 action[2] = z_safe for _ in range(100): env.step(action) # ---------- 主任务:全部立方体 + 螺母 ---------- def execute_task(env): img = env.render("rgb_array") poses = get_objects_and_targets_pose(img) # 1. 按颜色分组处理立方体 disk_map = poses['targets'] # ✅ 按颜色分组立方体 color_groups = {} for color, x, y, yaw in poses['cubes']: if color not in color_groups: color_groups[color] = [] color_groups[color].append((x, y, yaw)) # ✅ 对每个颜色组的立方体进行分拣 for color, cubes in color_groups.items(): targets = disk_map.get(color, []) # ✅ 如果目标数量少于立方体数量,重复使用最后一个目标 for i, (x, y, yaw) in enumerate(cubes): if i < len(targets): tx, ty = targets[i] elif targets: # 如果目标不够,使用最后一个目标 tx, ty = targets[-1] else: logger.warning("No target found for color %s", color) continue logger.info("Pick %s cube %d @ %.3f %.3f", color, i + 1, x, y) move_and_grasp(env, (x, y), yaw, CUBE_PICK_Z_W) logger.info("Place %s cube to target %d @ %.3f %.3f", color, i + 1, tx, ty) move_and_place_gentle(env, (tx, ty)) # 2. 方形螺母 → 篮子(中心偏移 1 cm)- 完全不变 if poses['square_nut'] is not None and poses['targets']['basket'] is not None: grab_x, grab_y, grab_yaw = poses['square_nut']['grab'] basket_x, basket_y = poses['targets']['basket'] drop_x = basket_x - 0.08 # ← 往中心 1 cm drop_y = basket_y + 0.02 # ← 往中心 1 cm logger.info("Pick square nut @ %.3f %.3f", grab_x, grab_y) move_and_grasp(env, (grab_x, grab_y), grab_yaw, NUT_PICK_Z_W, lift_after=False) # 空中平移 + 缓降释放 action = np.array([grab_x, grab_y, 0.4, 1, 0, 0, 0]) for t in range(100): env.step(action) action[0] = drop_x; action[1] = drop_y for t in range(200): env.step(action) for i in range(200): act = action.copy() act[2] = 0.4 - 0.2 * (i / 200) env.step(act) for _ in range(50): env.robot.end['arm0'].open(); env.step(action) action[2] = 0.4 for _ in range(100): env.step(action) # 回中间 q = T.euler_2_quat(np.array([0, 0, 0])) for _ in range(100): env.step(np.array([0.4, 0.0, 0.30, q[3], q[0], q[1], q[2]])) def main(): env = RobotEnv(robot='UR5eGrasp', render_mode='human', control_freq=200, controller='CARTIK', is_show_camera_in_cv=True, is_render_camera_offscreen=True, camera_in_render="0_cam") env.reset() execute_task(env) env.close() if __name__ == "__main__": main()
最新发布
10-29
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值