线段树总结


还是那句话, 知其然不知其所以然真的是一件容易引发伤痛的事情。

所以忍不住来一发线段树总结。。

因为当时学线段树的时候也就是刚学了几个月编程, 所以一直觉得它挺长的。

但现在再看一看实在是简洁易懂的, 一个线段树也就三十行而且思路非常的清晰写起来非常的快。

以前对于线段树的lazy思想一直没有系统地想过, 都是在什么时候遇到一道题然后自己YY出来的, 经常调不对, 但事实上lazy思想做的就是不把那些没有必要的细枝末节更新。 比如最后一个更新是把整个区间更新后询问整个区间维护的值, 如果单点修改的话就要把整棵树都修改了然后再询问, 但是这时的询问实际上只用到了tree[1]这一个节点的值, 所以那些更新都是没有意义的。 而我们要改进的就是把作用在一个点上的所有更新都合并起来, 然后等到需要用到这个点的时候再给它更新, 这样理论上的时间复杂度就还是nlogn 的。

注意它维护的那个改变的值 是代表着当前这个点已经更新过了, 但是它的子节点还没有更新过, 所以当访问一个点的子节点的时候先查询这个子节点需不需要改变, 改变了以后再访问这个子节点。

裸题 hdu1698, 做了好几遍了,,,但是这一遍做的自我感觉是最优美的!  四十行

#include <iostream>
#include <cstdio>
#define MAXN 100005
using namespace std;
int t, n, q;
struct Tree{
    int l, r, num, c;    
}tree[MAXN * 4];
void build(int t, int l, int r){
    tree[t].l = l; tree[t].r = r; tree[t].num = r - l + 1;  tree[t].c = 0;
    if(l == r)return;
    int mid = (l + r)>>1;
    build(t + t, l, mid); build(t + t + 1, mid + 1, r);    
}
void update(int l, int r, int z, int t){
    int tl = tree[t].l, tr = tree[t].r; int mid = (tl + tr)>>1;
    if(tl >= l && tr <= r){
        tree[t].c = z;  
        tree[t].num = (tr - tl + 1) * z;    return ;    
    }   
    if(tree[t].c){  int cc = tree[t].c; tree[t].c = 0;          //down
        tree[t + t].c = tree[t + t + 1].c = cc;
        tree[t + t + 1].num = cc * (tree[t + t + 1].r - tree[t + t + 1].l + 1);
        tree[t + t].num = cc * (tree[t + t].r - tree[t + t].l + 1);   
    }
    if(l <= mid)update(l, r, z, t + t);
    if(r >= mid + 1)update(l, r, z, t + t + 1);
    tree[t].num = tree[t + t].num + tree[t + t + 1].num;  //up
}
int main()
{
    scanf("%d", &t); for(int cas = 1; cas <= t; cas ++){
        scanf("%d%d", &n, &q);
       build(1, 1, n); 
        while(q --){
            int x, y, z; scanf("%d%d%d", &x, &y, &z);
            update(x, y, z, 1);
        }   printf("Case %d: The total value of the hook is %d.\n", cas, tree[1].num);
    }
    return 0;
}
另外值得一提的是看到这道题有人打了这样的暴力:

#include <iostream>
#include <cstdio>
using namespace std;
 
int data[100005][3];
 
int main()
{
     int t,q,n,i,j,sum,k,v;
     scanf ( "%d" ,&t);
     for (i=1;i<=t;i++)
     {
         scanf ( "%d%d" ,&n,&q);
         for (j=1;j<=q;j++)
             scanf ( "%d%d%d" ,&data[j][0],&data[j][1],&data[j][2]);
         sum=0;
         for (k=1;k<=n;k++)
         {
             v=1;
             for (j=q;j>=1;j--)
                 if (data[j][0]<=k && k<=data[j][1]) //寻找k所在的更新区间,若存在则更新,不存在v=1不变
                 {
                     v=data[j][2];                 //若找的最后面的更新区间,则停止,因为前面的会被覆盖
                     break ;
                 }
             sum+=v;
         }
         printf ( "Case %d: The total value of the hook is %d.\n" ,i,sum);
     }
     return 0;
}
然后它的速度竟然比线段树快T T , 果然是它的数据出的太弱了, 但一般这种线段树的题都会有其它的解法的, 贪心二分什么的。


poj 3468

还是最裸最裸的线段树, 不过我最开始还是调了好久。。。。。果然弱得不能忍。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#define MAXN 100005
using namespace std;
int a[MAXN], n, q;
struct Tree{
    int l, r; long long delta, sum;     
}tree[MAXN * 4];
void build(int t, int l, int r){
    tree[t].l = l; tree[t].r = r; tree[t].delta = 0;
    if(l == r){tree[t].sum = (long long)a[l]; return;}
    int mid = (l + r)>>1;
    build(t + t, l, mid); build(t + t + 1, mid + 1, r);
    tree[t].sum = tree[t + t].sum + tree[t + t + 1].sum;    
}
inline void pushdown(int t){
    if(tree[t].delta){  long long dd = tree[t].delta; tree[t].delta = 0;
        tree[t + t].delta += dd; tree[t + t + 1].delta += dd;
        tree[t + t].sum += dd * (tree[t + t].r - tree[t + t].l + 1);
        tree[t + t + 1].sum += dd * (tree[t + t + 1].r - tree[t + t + 1].l + 1);}    
}
void update(int t, int l, int r, int z){
    if(tree[t].l >= l && tree[t].r <= r){
        tree[t].delta += z;  
        tree[t].sum += (tree[t].r - tree[t].l + 1) * (long long)z; return;    
    }       pushdown(t);
    int mid = (tree[t].l + tree[t].r)>>1;
    if(mid >= l)update(t + t, l, r, z);
    if(mid + 1 <= r)update(t + t + 1, l, r, z);
    tree[t].sum = tree[t + t].sum + tree[t + t + 1].sum;
}
long long ask(int t, int l, int r){
    if(tree[t].l >= l && tree[t].r <= r)return tree[t].sum;   
    pushdown(t);
    int mid = (tree[t].l + tree[t].r)>>1;
    long long ret = 0;
    if(mid >= l) ret += ask(t + t, l, r);
    if(mid + 1 <= r) ret += ask(t + t + 1, l, r);   return ret;
}
int main()
{
    scanf("%d%d", &n, &q);
    for(int i = 1; i <= n; i ++)scanf("%d", &a[i]);
    build(1, 1, n);
    for(int i = 1; i <= q; i ++){   getchar();
        char c; int x, y; scanf("%c%d%d", &c, &x, &y);
        if(c == 'Q'){printf("%I64d\n", ask(1, x, y));}
        else {int z; scanf("%d", &z); update(1, x, y, z);}
    }
   // system("pause");
    return 0;
}
还有一点就是只看自己的代码的时候不觉得有什么, 但在同一道题下, 看一下别人的代码就会感慨自己写得有多丑 了!!

#include <cstdio>
#include <algorithm>
using namespace std;
 
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
#define LL long long
const int maxn = 111111;
LL add[maxn<<2];
LL sum[maxn<<2];
void PushUp(int rt) {
    sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
void PushDown(int rt,int m) {
    if (add[rt]) {
        add[rt<<1] += add[rt];
        add[rt<<1|1] += add[rt];
        sum[rt<<1] += add[rt] * (m - (m >> 1));
        sum[rt<<1|1] += add[rt] * (m >> 1);
        add[rt] = 0;
    }
}
void build(int l,int r,int rt) {
    add[rt] = 0;
    if (l == r) {
        scanf("%lld",&sum[rt]);
        return ;
    }
    int m = (l + r) >> 1;
    build(lson);
    build(rson);
    PushUp(rt);
}
void update(int L,int R,int c,int l,int r,int rt) {
    if (L <= l && r <= R) {
        add[rt] += c;
        sum[rt] += (LL)c * (r - l + 1);
        return ;
    }
    PushDown(rt , r - l + 1);
    int m = (l + r) >> 1;
    if (L <= m) update(L , R , c , lson);
    if (m < R) update(L , R , c , rson);
    PushUp(rt);
}
LL query(int L,int R,int l,int r,int rt) {
    if (L <= l && r <= R) {
        return sum[rt];
    }
    PushDown(rt , r - l + 1);
    int m = (l + r) >> 1;
    LL ret = 0;
    if (L <= m) ret += query(L , R , lson);
    if (m < R) ret += query(L , R , rson);
    return ret;
}
int main() {
    int N , Q;
    scanf("%d%d",&N,&Q);
    build(1 , N , 1);
    while (Q --) {
        char op[2];
        int a , b , c;
        scanf("%s",op);
        if (op[0] == 'Q') {
            scanf("%d%d",&a,&b);
            printf("%lld\n",query(a , b , 1 , N , 1));
        } else {
            scanf("%d%d%d",&a,&b,&c);
            update(a , b , c , 1 , N , 1);
        }
    }system("pause");
    return 0;
}
这个代码也就比我的那个多了20行, 但是真的漂亮到不知道哪里去了。。。不过他用的是那种不开struct的线段树, 所以说变量名就都会显得比较短, 其实我这种线段树应该也可以define一下然后看起来就会漂亮多了!

改了一会改不下去了。。但大概是这个效果:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#define MAXN 100005
#define ll long long
#define S(x) tree[x].sum
#define R(x) tree[x].r
#define L(x) tree[x].l
#define D(x) tree[x].delta
#define ls(x) x<<1
#define rs(x) (x<<1)+1
using namespace std;
int a[MAXN], n, q;
struct Tree{
    int l, r;
    long long delta, sum;     
}tree[MAXN * 4];
void build(int t, int l, int r){
    L(t) = l;
    R(t) = r;
    D(t) = 0;
    if(l == r){
        S(t) = (ll)a[l];
        return;
    }
    int mid = (l + r)>>1;
    build(ls(x), l, mid);
    build(rs(x), mid + 1, r);
    S(t) = S(ls(x)) + S(rs(x));    
}
inline void pushdown(int t){
    if(D(t)){  
        ll dd = D(t);
        D(t) = 0;
        D(ls(t)) += dd;
        D(rs(t)) += dd;
        S(ls(t)) += dd * (R(ls(t)) - L(ls(t)) + 1);
        S(rs(t)) += dd * (R(rs(t)) - L(rs(t)) + 1);
    }    
}
void update(int t, int l, int r, int z){
    if(L(t) >= l && R(t) <= r){
        D(t) += z;  
        S(t) += (R(t) - L(t) + 1) * (ll)z;
        return;    
    }       
    pushdown(t);
    int mid = (L(t) + R(t))>>1;
    if(mid >= l)update(ls(t), l, r, z);
    if(mid + 1 <= r)update(rs(t), l, r, z);
    S(t) = S(ls(t)) + S(rs(t));
}

风格很怪异啊。。。



还有这道题, 我还没写呢, 但是感觉还是有价值看一看的, 一下是一个人的题解

o    poj3225 Help with Intervals
题意:区间操作,,,补等
思路:
我们一个一个操作来分析:(01表示是否包含区间,-1表示该区间内既有包含又有不包含)
U:
把区间[l,r]覆盖成1
I:
[-∞,l)(r,∞]覆盖成0
D:
把区间[l,r]覆盖成0
C:
[-∞,l)(r,∞]覆盖成0 ,[l,r]区间0/1互换
S:[l,r]
区间0/1互换

成段覆盖的操作很简单,比较特殊的就是区间0/1互换这个操作,我们可以称之为异或操作
很明显我们可以知道这个性质:当一个区间被覆盖后,不管之前有没有异或标记都没有意义了
所以当一个节点得到覆盖标记时把异或标记清空
而当一个节点得到异或标记的时候,先判断覆盖标记,如果是01,直接改变一下覆盖标记,不然的话改变异或标记

开区间闭区间只要数字乘以2就可以处理(偶数表示端点,奇数表示两端点间的区间)
线段树功能:update:成段替换,区间异或 query:简单hash

?View Code CPP

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

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

#include <cstdio>

#include <cstring>

#include <cctype>

#include <algorithm>

using namespace std;

#define lson l , m , rt << 1

#define rson m + 1 , r , rt << 1 | 1

 

const int maxn=131072;

bool hash[maxn];

int cover[maxn<<2];

int XOR[maxn<<2];

void FXOR(int rt){

         if (cover[rt]!=-1) cover[rt]^=1;

         else XOR[rt]^=1;

}

void PushDown(int rt){

         if (cover[rt]!=-1){

                 cover[rt<<1]= cover[rt<<1|1]= cover[rt];

                 XOR[rt<<1]= XOR[rt<<1|1]=0;

                 cover[rt]=-1;

         }

         if (XOR[rt]){

                 FXOR(rt<<1);

                 FXOR(rt<<1|1);

                 XOR[rt]=0;

         }

}

void update(char op,int L,int R,int l,int r,int rt) {

         if (L <= l && r<= R){

                 if (op == 'U'){

                          cover[rt]=1;

                          XOR[rt]=0;

                 } else if (op=='D'){

                          cover[rt]=0;

                          XOR[rt]=0;

                 } else if (op=='C' || op == 'S'){

                          FXOR(rt);

                 }

                 return ;

         }

         PushDown(rt);

         int m = (l + r)>>1;

         if (L <= m) update(op , L , R , lson);

         else if (op =='I'|| op == 'C') {

                 XOR[rt<<1]= cover[rt<<1]=0;

         }

         if (m < R) update(op , L , R , rson);

         else if (op =='I'|| op == 'C') {

                 XOR[rt<<1|1]= cover[rt<<1|1]=0;

         }

}

void query(int l,int r,int rt){

         if (cover[rt]==1){

                 for (int it = l; it<= r ; it ++){

                          hash[it]=true;

                 }

                 return ;

         } else if (cover[rt]==0)return;

         if (l == r) return ;

         PushDown(rt);

         int m = (l + r)>>1;

         query(lson);

         query(rson);

}

int main(){

         cover[1]= XOR[1]=0;

         char op , l , r;

         int a , b;

         while ( ~scanf("%c %c%d,%d%c\n",&op ,&l , &a , &b ,&r)){

                 a <<= 1 , b <<= 1;

                 if (l == '(') a++;

                 if (r == ')') b--;

                 if (a > b) {

                          if (op == 'C' || op == 'I'){

                                   cover[1]= XOR[1]=0;

                          }

                 } else update(op , a , b , 0 , maxn , 1);

         }

         query(0 , maxn ,1);

         bool flag = false;

         int s = -1 , e;

         for (int i = 0 ; i <= maxn; i++){

                 if (hash[i]){

                          if (s == -1) s= i;

                          e = i;

                 } else {

                          if (s != -1) {

                                   if(flag)printf(" ");

                                   flag = true;

                                   printf("%c%d,%d%c",s&1?'(':'[' , s>>1 , (e+1)>>1 , e&1?')':']');

                                   s =-1;

                          }

                 }

         }

         if (!flag)printf("empty set");

         puts("");

         return 0;

}


然后就是区间合并的啦!

·        区间合并
这类题目会询问区间中满足条件的连续最长区间,所以PushUp的时候需要对左右儿子的区间进行合并

就是像小白逛公园那样的题了, 话说小白逛公园是我A的第一道线段树的题。。。深感被cy欺骗了。。。她应该先让我做单点修改的题啊,还记得当时我做那题做得很困难。

 

poj3667

今天poj上不去是什么情况。。T T, 一会再交

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <cstdlib>
#include <time.h>
#include <queue>
#define MAXN 50005
using namespace std;
struct Tree{
	int lmax, rmax, mmax, l, r, c;
}tree[MAXN * 4];
inline void pushdown(int x){
	if(tree[x].c != -1){
		tree[x<<1].c = tree[x<<1|1].c = tree[x].c;
		tree[x<<1].lmax = tree[x<<1].rmax = tree[x<<1].mmax = tree[x].c * (tree[x<<1].r - tree[x<<1].l + 1);
		tree[x<<1|1].lmax = tree[x<<1|1].rmax = tree[x<<1|1].mmax = tree[x].c * (tree[x<<1|1].r - tree[x<<1|1].l + 1);
		tree[x].c = -1;
	}
}
inline void pushup(int t){
	tree[t].lmax = tree[t<<1].lmax;
	tree[t].rmax = tree[t<<1|1].rmax;
	if(tree[t<<1].lmax == tree[t<<1].r - tree[t<<1].l + 1) tree[t].lmax += tree[t<<1|1].lmax;
	if(tree[t<<1|1].rmax == tree[t<<1|1].r - tree[t<<1|1].l + 1) tree[t].rmax += tree[t<<1].rmax;
	tree[t].mmax = max(max(tree[t<<1].mmax, tree[t<<1|1].mmax), tree[t<<1].rmax + tree[t<<1|1].lmax);
}
void build(int t, int l, int r){
	tree[t].lmax = tree[t].rmax = tree[t].mmax = r - l + 1;
	tree[t].l = l; tree[t].r = r; tree[t].c = -1;
	if(l == r)return;
	int mid = l + r>>1;
	build(t<<1, l, mid); build(t<<1|1, mid + 1, r);
}
int ask(int t, int w){
	int l = tree[t].l, r = tree[t].r;
	if(l == r)return l;
	pushdown(t);
	int mid = l + r >>1;
	if(tree[t<<1].mmax >= w)return ask(t<<1, w);
	if(tree[t<<1].rmax + tree[t<<1|1].lmax >= w) return mid - tree[t<<1].rmax + 1;
	return ask(t<<1|1, w);
}
void update(int l, int r, int t, int c){
	if(tree[t].l >= l && tree[t].r <= r){
		tree[t].lmax = tree[t].rmax = tree[t].mmax = c * (tree[t].r - tree[t].l + 1);
		tree[t].c = c; return;
	}
	pushdown(t);
	int mid = (tree[t].l + tree[t].r)>>1;
	if(l <= mid)update(l, r, t<<1, c);
	if(r >= mid + 1)update(l, r, t<<1|1, c);
	pushup(t);
}
int main()
{
	int n, m; scanf("%d%d", &n, &m);
	build(1, 1, n);
	while(m --){
		int z, a, b; scanf("%d%d", &z, &a);
		if(z == 1){
			if(tree[1].mmax < a)puts("0");
			else{
				int p = ask(1, a);
				printf("%d\n", p);
				update(p, p + a - 1, 1, 0);
			}
		}
		else{
			scanf("%d", &b);
			update(a, a + b - 1, 1, 1);
		}
	}//system("pause");
	return 0;
}



hdu3308

同区间合并裸题,,但是调了好久,,这两天一直在调代码有点疲惫了呜呜呜~~~~(>_<)~~~~

很快打完的代码总是调不出来,,还是做的题太少了,,加油吧一直敲代码我的代码能力一定会上去的! >_<


扫描线

这算是线段树的一个经典应用吧,,前几天做题还遇到了,,当时好像现场没调出来~~~~(>_<)~~~~


poj 1177

所有线段树的总结中都有这个!

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define MAXN 50010
using namespace std;
int n; 
int x[2 * MAXN], end;
struct node{
    int l, r;
    int len, lenall;
    int num, seg;
    bool lcover, rcover;   
}tree[MAXN * 8];
struct line{
    int s, e;
    int y;
    bool down;    
}xline[2 * MAXN];
void build(int l, int r, int t){
    tree[t].l = l;
    tree[t].r = r;
    tree[t].len = x[r] - x[l];
    tree[t].lenall = tree[t].num = tree[t].seg = 0;
    tree[t].lcover = tree[t].rcover = 0;
    if(r - l > 1){
        int mid = (l + r)>>1;
        build(l, mid, t + t), 
        build(mid, r, t + t + 1);    
    }    
}

void update(int r){
    if(tree[r].num > 0){
        tree[r].lenall = tree[r].len;
        tree[r].seg = 1;
        tree[r].lcover = tree[r].rcover = 1;    
    }    
    else if(tree[r].r - tree[r].l > 1){
            tree[r].lenall = tree[2 * r].lenall + tree[2 * r + 1].lenall;
            tree[r].lcover = tree[2 * r].lcover;
            tree[r].rcover = tree[2 * r + 1].rcover;
            tree[r].seg = tree[2 * r].seg + tree[2 * r + 1].seg
                            - tree[2 * r].rcover * tree[2 * r + 1].lcover; 
    } 
    else{
        tree[r].lenall = tree[r].seg = 0;
        tree[r].lcover = tree[r].rcover = 0;    
    }
}

void insert(int l, int r, int t){
    if(l == tree[t].l && r == tree[t].r)
        tree[t].num ++;
    else {
        int mid = (tree[t].l + tree[t].r) >> 1;
        if(r <= mid) insert(l, r, 2 * t);
        else if(l >= mid) insert(l, r, 2 * t + 1);
        else insert(l, mid, 2 * t), insert(mid, r, 2 * t + 1); 
    }    
    update(t);
}

void deletee(int l, int r, int t){
    if(l == tree[t].l && r == tree[t].r)
        tree[t].num --;
    else {
        int mid = (tree[t].l + tree[t].r)>>1;
        if(r <= mid)    deletee(l, r, 2 * t);
        else if(l >= mid)   deletee(l, r, 2 * t + 1);
        else deletee(l, mid, 2 * t), deletee(mid, r, 2 * t + 1);    
    }    
    update(t);
}

int find(int key){
    return lower_bound(x + 1, x + end + 1, key) - x;    
}

bool cmp(const line &l1, const line &l2){
    return l1.y < l2.y;    
}
int main()
{
    scanf("%d", &n);
    int x1, x2, y1, y2;
    end = 1;
    for(int i = 0; i < n; i ++){
        scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
        x[end ++] = x1;
        x[end ++] = x2;
        xline[2 * i].s = xline[2 * i + 1].s = x1;
        xline[2 * i].e = xline[2 * i + 1].e = x2;
        xline[2 * i].y = y1; xline[2 * i + 1].y = y2;
        xline[2 * i].down = 1; xline[2 * i + 1].down = 0;
    }
    sort(x + 1, x + end) ;
    end = unique(x + 1, x + end) - (x + 1);
    build (1, end, 1);
    int ans = 0, pre = 0;
    sort(xline, xline + 2 * n, cmp);
    for(int i = 0; i < 2 * n - 1; i ++){
        if(xline[i].down){
            insert(find(xline[i].s), find(xline[i].e), 1);    
        }    
        else
            deletee(find(xline[i].s), find(xline[i].e), 1);
            
        ans += tree[1].seg * (xline[i + 1].y - xline[i].y) * 2;
        ans += abs(tree[1].lenall - pre);
        pre = tree[1].lenall;
    }
    deletee(find(xline[2 * n - 1].s), find(xline[2 * n - 1].e), 1);
    ans += abs(tree[1].lenall - pre);
    printf("%d\n",ans);
  //  system("pause");
    return 0;    
}



资源下载链接为: https://pan.quark.cn/s/67c535f75d4c 在机器人技术中,轨迹规划是实现机器人从一个位置平稳高效移动到另一个位置的核心环节。本资源提供了一套基于 MATLAB 的机器人轨迹规划程序,涵盖了关节空间和笛卡尔空间两种规划方式。MATLAB 是一种强大的数值计算与可视化工具,凭借其灵活易用的特点,常被用于机器人控制算法的开发与仿真。 关节空间轨迹规划主要关注机器人各关节角度的变化,生成从初始配置到目标配置的连续路径。其关键知识点包括: 关节变量:指机器人各关节的旋转角度或伸缩长度。 运动学逆解:通过数学方法从末端执行器的目标位置反推关节变量。 路径平滑:确保关节变量轨迹连续且无抖动,常用方法有 S 型曲线拟合、多项式插值等。 速度和加速度限制:考虑关节的实际物理限制,确保轨迹在允许的动态范围内。 碰撞避免:在规划过程中避免关节与其他物体发生碰撞。 笛卡尔空间轨迹规划直接处理机器人末端执行器在工作空间中的位置和姿态变化,涉及以下内容: 工作空间:机器人可到达的所有三维空间点的集合。 路径规划:在工作空间中找到一条从起点到终点的无碰撞路径。 障碍物表示:采用二维或三维网格、Voronoi 图、Octree 等数据结构表示工作空间中的障碍物。 轨迹生成:通过样条曲线、直线插值等方法生成平滑路径。 实时更新:在规划过程中实时检测并避开新出现的障碍物。 在 MATLAB 中实现上述规划方法,可以借助其内置函数和工具箱: 优化工具箱:用于解决运动学逆解和路径规划中的优化问题。 Simulink:可视化建模环境,适合构建和仿真复杂的控制系统。 ODE 求解器:如 ode45,用于求解机器人动力学方程和轨迹执行过程中的运动学问题。 在实际应用中,通常会结合关节空间和笛卡尔空间的规划方法。先在关节空间生成平滑轨迹,再通过运动学正解将关节轨迹转换为笛卡
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值