Hanjie's Blog

一只有理想的羊驼

罗汉杰. 机械臂的控制方法和装置:中国,201610984458[P/OL]. 2017-03-01 [2018-03-20]. https://patentimages.storage.googleapis.com/7c/c5/c2/165019b55f0bee/CN106346478A.pdf

Introduction

机械臂的轨迹规划程序中,程序会接受用户提供的起点,终点位置信息,然后程序会在两点之间生成一系列的插补点来描述机械臂末端应该运行的轨迹。

当用户提供多条直线线段,并且要求机械臂末端依次沿着直线运行时,程序需要在每两条线段的手尾位置规划出一个过渡段,使得机械臂终端能够平稳地从一个运动方向转到另一个运动方向。为保证机械臂运行效率和精度,需要机械臂在整个运行过程中位移,速度,加速度参数必须连续。

本文提出了一种用于机械臂的轨迹规划算法,能够使得机械臂从当前状态开始规划出一条位移,速度,加速度连续的过渡轨迹,到要运行的直线轨迹上。

Approach

给定机械臂目标直线的起点\(P_1\),终点 \(P_2\)。其中\(P\)表示笛卡尔坐标系下的位置参数\(P_i=[x_i,y_i,z_i ]^T\)。给定当前的机械臂关节空间角度\(Q_0=[q_0,q_1,…,q_n ]^T\),其中\(n\)为机械臂的关节数目,同理给定机械臂关节角速度\({\dot Q_0}\),关节角加速度\({\ddot Q_0}\)

使用S 型(Double S)速度规划/多阶样条插值/b样条插补等方法,规划出直线线段\(P_1 P_2\)在笛卡尔坐标系下的插补点\(P_t=[x_t,y_t,z_t ]^T\),速度\(\dot P_t=[\dot x_t,\dot y_t,\dot z_t ]^T\),加速度\(\ddot P_t=[\ddot x_t,\ddot y_t,\ddot z_t ]^T\)\(t\)为时间点,总运行时间为\(t_{line\_all}\)

给定参数时刻\(t_s (0≤t_s≤t_{line\_all})\)(可根据给定的一个比例参数\(r_s\) 获得参数\(t_s=t_{line\_all}*r_s)\),并从已规划出的直线\(P_1 P_2\)上,获得时刻\(t_s\)时的坐标点\(P_s\),速度\(\dot P_s\),加速度\(\ddot P_s\),将此点作为过渡段的终点。

使用逆运动学方法,将笛卡尔坐标系下的\(P_s\)转换到此时刻关节空间下的参数\(Q_s\)。使用以下公式将\(\dot P_s\)\(\ddot P_s\)转换为\(\dot Q_s\)\(\ddot Q_s\)

\[\begin{align} \label{e1} \dot Q &= J^+ \dot P \newline \label{e2} \ddot Q &= J^+ (\ddot P- \dot J \dot Q) \end{align}\]

其中,\(J\)为雅可比(Jacobian)矩阵,\(\dot J\)为雅可比矩阵的一阶导,\(J^+\)\(J\)的伪逆(Pseudoinverse)。

使用基于多阶多项式/三角函数等的曲轨迹生成方法,在以\(Q_0\)\(\dot Q_0\)\(\ddot Q_0\)为起点,\(Q_s\)\(\dot Q_s\)\(\ddot Q_s\)为终点,在轴空间规划出一条连续过度段轨迹,整个运行时长为\(t_{trans}\)。以五阶多项式曲线为例,先代入以下公式计算出系数参数:

\[\begin{align} a_0 &= Q_0 \notag \newline a_1 &= \dot Q_0 \notag \newline a_2 &= \ddot Q_0 / 2 \notag \newline a_3 &= \frac{20h-(8\dot Q_s+12\dot Q_0 ) t_{trans}-(3\ddot Q_0- \ddot Q_s ) t_{trans}^2 }{2t_{trans}^3} \newline a_4 &= \frac{-30h+(14\dot Q_s+16\dot Q_0 ) t_{trans}+(3\ddot Q_0-2\ddot Q_s ) t_{trans}^2}{2t_{trans}^4 } \notag \newline a_5 &= \frac{12h-6(\dot Q_s+\dot Q_0 ) t_{trans}+(\ddot Q_0-\ddot Q_s ) t_{trans}^2}{2t_{trans}^5 } \notag \label{e3} \end{align}\]

然后就可以根据以下公式计算出任意时刻\(t(0≤t≤t_{trans})\)时的关节角位置\(Q_t\),角速度\(\dot Q_t\),角加速度\(\ddot Q_t\)

\[\begin{align} \label{e4} Q_t&=Q_0+a_1 t+a_2 t^2+a_3 t^3+a_4 t^4+a_5 t^5 \newline \label{e5} \dot Q_t&=a_1+2a_2 t+3a_3 t^2+4_4 t^3+5a_5 t^4 \newline \label{e6} \ddot Q_t&=2a_2+6a_3 t+12a_4 t^2+20a_5 t^3 \end{align}\]

该过渡段的重点是,当运行到过渡段的终点时,此时的\(Q_{trans}\)\(\dot Q_{trans}\)\(\ddot Q_{trans}\),与在步骤2规划的直线线段在时刻\(t_s\)时的\(Q_s\)\(\dot Q_s\)\(\ddot Q_s\)相等,从而保证了位置,速度和加速度在数值上的连续。

所以,整个路径规划出来的线段包括过渡段和直线轨迹两个部分,其中过渡段用时\(t_{trans}\),直线段用时\(t_{line}\),总用时\(t_{all}\),其中:

\[\begin{align} \label{e7} t_{line} & =t_{line\_all}-t_s \newline \label{e8} t_{all} & =t_{trans}-t_{line} \end{align}\]

Flow Diagram

manipulation flow diagra

Experiment

下图显示了SCARA型四轴机械臂末端从坐标\([0.6,0,0]^T\)直线运行到\([0.344,0.128,0]^T\),然后使用上文提出的算法,从当前位置规划出一个过渡段曲线到\([0.189,0.2,0]^T\),然后直线运行到终点\([0,0.2,0]^T\)

manipulation d1

下图显示了机械臂的前三个轴各自在各个时刻的\(Q_t\)\(\dot Q_t\)\(\ddot Q_t\)。从图可以看到,无论是轴的角度,角速度,角加速度都连续。

manipuation d2

Conclusion

在传统的机械臂中,当要连续执行多条直线轨迹的时候,需要先执行完一条轨迹,然后停止,再执行另外一条,这种运动方式效率十分低。

另外一些机械臂中,需要预先给出所有要运行的线段,然后才能在必要的地方规划出过渡段。

在本方法中,过渡段只与机械臂当前状态,起点,终点有关,不需要其余信息,方便使用;在整个运行过程中,机械臂不需要停止,规划出来的轨迹平稳,效率高。

在使用ZED Camera时,我希望获得原始的照片(未经过校正,对齐处理)。但由于系统是Ubuntu 14.04,只有ZED SDK 1.1.0版本支持,而对应的zed-ros-wrapper v1.0.0只能订阅已经经过校正对齐的照片/camera/left/image_rect_color/camera/rgb/image_rect_color(不过zed-ros-wrapper v1.2.0版本开始就开始提供原始照片的订阅,Topic为/camera/left/image_raw_color/camera/right/image_raw_color)。

如果直接使用ZED SDK所提供的图片获取接口'grab(); retrieveImage()',按照说明也是已经经过了对齐操作了,并非是原始照片。

还好由于ZED Camera是标准的网络摄像头,使用v4l2-ctl --all指令,有以下显示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
Driver Info (not using libv4l2):
Driver name : uvcvideo
Card type : ZED
Bus info : usb-0000:00:14.0-3
Driver version: 4.4.59
Capabilities : 0x84200001
Video Capture
Streaming
Device Capabilities
Device Caps : 0x04200001
Video Capture
Streaming
Priority: 2
Video input : 0 (Camera 1: ok)
Format Video Capture:
Width/Height : 2560/720
Pixel Format : 'YUYV'
Field : None
Bytes per Line: 5120
Size Image : 3686400
Colorspace : SRGB
Custom Info : feedcafe
Crop Capability Video Capture:
Bounds : Left 0, Top 0, Width 2560, Height 720
Default : Left 0, Top 0, Width 2560, Height 720
Pixel Aspect: 1/1
Selection: crop_default, Left 0, Top 0, Width 2560, Height 720
Selection: crop_bounds, Left 0, Top 0, Width 2560, Height 720
Streaming Parameters Video Capture:
Capabilities : timeperframe
Frames per second: 30.000 (30/1)
Read buffers : 0
brightness (int) : min=0 max=8 step=1 default=4 value=4
contrast (int) : min=0 max=8 step=1 default=4 value=4
saturation (int) : min=0 max=8 step=1 default=4 value=4
hue (int) : min=0 max=11 step=1 default=0 value=0
white_balance_temperature_auto (bool) : default=1 value=1
gain (int) : min=0 max=8 step=1 default=4 value=4
power_line_frequency (menu) : min=0 max=2 default=1 value=1
white_balance_temperature (int) : min=2800 max=6500 step=100 default=4600 value=4600 flags=inactive
sharpness (int) : min=0 max=8 step=1 default=4 value=4
exposure_auto (menu) : min=0 max=3 default=0 value=2
exposure_absolute (int) : min=5000 max=80000 step=5000 default=60000 value=45000 flags=inactive
exposure_auto_priority (bool) : default=0 value=0

所以可以使用OpenCV(opencv-2.4.13.2版本)自带的VideoCapture函数获取原始照片:

1
2
3
4
5
6
7
8
9
10
11
cv::VideoCapture* camera_ = new cv::VideoCapture(0);
cv::Mat raw, left_image, right_image;
if (camera_->grab()) {
camera_->retrieve(raw);
cv::Rect left_rect(0, 0, width_ / 2, height_);
cv::Rect right_rect(width_ / 2, 0, width_ / 2, height_);
left_image = raw(left_rect);
right_image = raw(right_rect);
cv::waitKey(10);
return true;
}

但在读取,设置摄像头快门速度(EXPOSURE)时,

1
2
camera_->set(CV_CAP_PROP_EXPOSURE, exposure_);
exposure_ = camera_->get(CV_CAP_PROP_EXPOSURE);

出现了以下错误:

1
2
HIGHGUI ERROR: V4L2: Unable to get property Exposure(9963793) - Invalid argument
HIGHGUI ERROR: V4L: Exposure control in V4L is not supported

发现是OpenCV的bug1,并且在最新的3.*版本已经修复,对于opencv-2.4.13.2版本需要手动修复。

解决方法

>在opencv-2.4.13.2/modules/highgui/src/cap_v4l.cpp文件中,将V4L2_CID_EXPOSURE替换为V4L2_CID_EXPOSURE_ABSOLUTE,重新build一次。

重新运行程序,发现读取问题解决了,但是设置参数时依然出现问题:

1
2
3
HIGHGUI ERROR: V4L2: Failed to set control "10094850": Input/output error (value 12500)
HIGHGUI WARNING: Setting property 10094850 through v4l2 failed. Trying with v4l1.
HIGHGUI ERROR: V4L: Exposure control in V4L is not supported

后来终于找到解决方法,需要先通过设置'exposure_auto',关闭自动模式,才能进行快门设置2。终端中运行:

1
v4l2-ctl --set-ctrl=exposure_auto=2

很奇怪,exposure_auto貌似只能设置为0/2。

为了让exposure_absolute生效,还需设置:

1
v4l2-ctl --set-ctrl=exposure_auto_priority=1

现在可以在C++中通过OpenCV设置摄像头的快门了。

以上方法经过测试发现都是无效的,V4L2无法对快门速度进行设置。

后来,发现可以通过对zed-ros-wrapper进行修改,进行快门设置。

zed_wrapper_nodelet.cpp中添加控制exposure的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
int main(int argc, char **argv) {

// Defines the exposure control. A -1 value enable the AutoExposure/AutoGain control.
// Affected value should be between 0 and 100 for manual control.
// A 0 value only disable automode without modifing the last auto values,
// while a 1 to 100 value disable auto mode and set exposure to chosen value
int exposure = 50;

nh_ns.getParam("exposure", exposure);

// before zed->grab()
zed->setCameraSettingsValue(sl::zed::ZED_EXPOSURE, exposure);
}

然后就可以在launch文件中添加控制快门语句:

1
<param name="exposure" value="50"/>

  1. https://github.com/opencv/opencv/pull/6393↩︎

  2. https://askubuntu.com/questions/211971/v4l2-ctl-exposure-auto-setting-fails↩︎

0%