基于Meshcat的相机视角配置

image from 夏眠
此问题是在进行有关Renderer之后得到Robot image的部分出现的,在次进行相应记录。

问题描述
由于Meshcat中貌似默认设置了视角会自动朝向机器人所在的方向(以Z轴:前后为分界线),所以导致无法 使在Z轴正半轴的相机看向正半轴方向。
解决思路
最后通过模拟了一个类似镜像变换的方式,使可以正常看向前方,如下图所示(示例中都只有右机械臂):

但很显然,出现了镜像的效果。
解决方案:在录完视频之后,对视频进行左右镜像即可,效果图如下:

相关代码
- 有关相机位置姿态设置的函数代码如下:
def look_at(viz, camera_pos, target_pos, up=np.array([0, 0, 1])):
camera_pos = np.array(camera_pos)
target_pos = np.array(target_pos)
# 设置焦点
T = np.eye(4)
T[:3, 3] = target_pos
viz.viewer["/Cameras/default"].set_transform(T)
# 相机相对焦点的偏移
offset = camera_pos - target_pos
viz.viewer["/Cameras/default/rotated/<object>"].set_property("position", offset.tolist())
# ---- 关键:修正旋转,使相机真的看向目标 ----
# forward = -Z 方向
forward = (target_pos - camera_pos)
forward /= np.linalg.norm(forward)
right = np.cross(up, forward)
right /= np.linalg.norm(right)
true_up = np.cross(forward, right)
R = np.eye(4)
R[:3, 0] = right
R[:3, 1] = true_up
R[:3, 2] = -forward # 注意这里是 +Z/-Z,可能需要 flip
viz.viewer["/Cameras/default/rotated"].set_transform(R)
其中”/Cameras/default”代表默认相机,通过transform变化设置相机需要看到的焦点(target);
“/Cameras/default/rotated”这是默认相机的一个子节点,通常 MeshCat 会在这里挂一些辅助的坐标变换,你添加的物体一般会挂在 “/meshcat” 或 “/object” 路径下。
“/Cameras/default/rotated/<object>“则是修改默认相机下面的一个子节点<object>的属性。set_property(position)相当于传入了当前相机位置相对于焦点的偏移量,从而得到相机的位置。
之后再main函数中调用look_at函数即可:
# 可以放在vis.display的后面
look_at(viz,camera_pos=[-0.0032, 0.01, 1.9526],target_pos=[-0.0032, -0.5903, 1.3026])
有不懂的也可以参考这篇文章:【学习笔记】MeshCat
- 进行视频镜像调整之前,需要先安装必要的库依赖。进入虚拟环境后运行以下命令:
安装moviepy和imageio库:
pip install moviepy imageio[ffmpeg]
升级imageio库:
pip install --upgrade imageio
升级imageio-ffmpeg库:
pip install --upgrade imageio-ffmpeg
有关视频镜像处理的代码如下:
只需要把对应需要处理的视频路径配置到input_video参数就好。
from moviepy.editor import VideoFileClip, vfx
def mirror_video(input_path, output_path):
"""
对视频进行左右镜像处理
:param input_path: 输入视频路径
:param output_path: 输出视频路径
"""
# 读取视频 - 直接使用VideoFileClip
clip = VideoFileClip(input_path)
# 左右镜像(水平翻转) - 使用正确的语法
flipped_clip = clip.fx(vfx.mirror_x)
# 输出视频
flipped_clip.write_videofile(
output_path,
codec="libx264",
audio_codec="aac",
fps=clip.fps
)
# 释放资源
clip.close()
flipped_clip.close()
⭐⭐⭐后续若有更好的方法也会进行更新~