using Leap;
Controller controller = new Controller();
MyListen mylisten = new MyListen();
Thread Updatedata;
private void but_connect_leap_Click(object sender, EventArgs e)
{
mylisten.OnServiceConnect(controller);
if(controller.IsConnected)
{
MessageBox.Show("Leap连接成功,刷新手参数线程开启");
Updatedata = new Thread(update);
Updatedata.IsBackground = true;
Update_Robot_T.Enabled = true;
Updatedata.Start();
}
else
{
MessageBox.Show("Leap连接失败");
}
}
private void update()
{
while (controller.IsConnected)
{
Thread.Sleep(1);
mylisten.OnFrame(controller);
if (mylisten.HandList != null)
{
if (mylisten.HandList.Count == 0)
{
lastx = 0;
lasty = 0;
lastz = 0;
continue;
}
Hand handRight = new Hand();
Hand handLeft = new Hand();
handRight = mylisten.HandList.Rightmost;
handLeft = mylisten.HandList.Leftmost;
Thread MoveThread = new Thread(() =>
{
if (handRight != null && handRight.IsRight && !handRight.IsLeft)
{
//if (robot.angle2 < 0)
//{
// robot.change_attitude(200);
//}
if (count == 0)
{
lastx = handRight.PalmPosition.x;
lasty = handRight.PalmPosition.y;
lastz = handRight.PalmPosition.z;
// if (lastx < 50 && lastx>-50 && lastz>-50 && lastz < 50 && lasty>-50 && lasty<50 &&handRight.PalmVelocity.y<10 && handRight.PalmVelocity.x<10 && handRight.PalmVelocity.z<10)
if (handRight.GrabStrength < 0.8f)
{
count = 1;
}
else
count = 0;
}
else if (count == 1)
{
float nowx = handRight.PalmPosition.x;
float nowy = handRight.PalmPosition.y;
float nowz = handRight.PalmPosition.z;
Leap_x = nowx - lastx;
Leap_y = nowy - lasty;
Leap_z = nowz - lastz;
lastx = nowx;
lasty = nowy;
lastz = nowz;
}
speed1 = handRight.PalmVelocity.x;
speed2 = handRight.PalmVelocity.y;
speed3 = handRight.PalmVelocity.z;
speed = (speed1 + speed2 + speed3) / 3;
// if (speed > 800 && speed < 1) continue;
Thread robotThread = new Thread();
//robotThread.Start();
else
if (handLeft != null && !handRight.IsRight && handRight.IsLeft)
{
}
public bool isGrabHand(Hand hand)
{
return hand.GrabStrength > 0.8f&&isStationary(hand);
}
public bool isMoveRight(Hand hand)
{
return hand.PalmVelocity.z > 50 && !isStationary(hand);
}
public bool isMoveLeft(Hand hand)
{
return hand.PalmVelocity.z <- 50 && !isStationary(hand);
}
public bool isMoveUp(Hand hand)
{
return hand.PalmVelocity.y > 50 && !isStationary(hand);
}
public bool isMoveDown(Hand hand)
{
return hand.PalmVelocity.y <- 50 && !isStationary(hand);
}
public bool isMoveForward(Hand hand)
{
return hand.PalmVelocity.x > 50 && !isStationary(hand);
}
public bool isMoveBack(Hand hand)
{
return hand.PalmVelocity.x <- 50 && !isStationary(hand);
}
//固定不动的
public bool isStationary(Hand hand)
{
return hand.PalmVelocity.Magnitude < 10; //Vector3.Magnitude返回向量的长度
}
==
//leapx–x;
//leapy–z;
//leapz–y;
==
## 基础语法
结构体和类的区别 :类是按引用传递 结构体是按值传递.
Sequential,顺序布局,比如
struct S1
{
int a;
int b;
}
那么默认情况下在内存里是先排a,再排b
也就是如果能取到a的地址,和b的地址,则相差一个int类型的长度,4字节
[StructLayout(LayoutKind.Sequential)]
struct S1
{
int a;
int b;
}
这样和上一个是一样的.因为默认的内存排列就是Sequential,也就是按成员的先后顺序排列.
2.Explicit,精确布局
需要用FieldOffset()设置每个成员的位置
这样就可以实现类似c的公用体的功能
[StructLayout(LayoutKind.Explicit)]
struct S1
{
[FieldOffset(0)]
int a;
[FieldOffset(0)]
int b;
}
这样a和b在内存中地址相同
2.[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
//这是C#引用非托管的C/C++的DLL的一种定义定义结构体的方式
structlayout支持三种附加字段:charset,pack,size,
1)charset是结构中的字符串成员在结构被传给DLL时的排列方式,可以是Unicode,ansi或Auto,默认为Auto.
2)pack定义了结构的封装大小:1,2,4,8,16,32,64,128或特殊值0(表示当前操作平台默认的压缩大小).
默认(LayoutKind.Sequential)情况下,CLR对struct的Layout的处理方法与C/C++中默认的处理方式相同,即按照结构中占用空间最大的成员进行对齐(Align);
使用LayoutKind.Explicit的情况下,CLR不对结构体进行任何内存对齐(Align),而且我们要小心就是FieldOffset;
使用LayoutKind.Auto的情况下,CLR会对结构体中的字段顺序进行调整,使实例占有尽可能少的内存,并进行4byte的内存对齐(Align)。
3.Inptr(指针)
用于:
1)Csharp调用win32API时;
2)Csharp调用C/C++写的DLL时;
用法:
[DllImport(“LeapC”, EntryPoint = “LeapCreateClockRebaser”)]
public static extern eLeapRS CreateClockRebaser(out IntPtr phClockRebaser);
3)字符串转Intptr:
Marshal.StringTocoTaskMemAuto(txt);
4. [MarshalAs(UnmanagedType.FunctionPtr)]
public Allocate allocate;
1)UnmanagedType;指定如何将参数或字段封送到非托管代码.
2)托管代码指必须依靠.net框架解释运行的代码.
托管的代码就是把有关内存管理(内存申请,内存释放,垃圾回收之类的)全部都是.net的CLR来管理,就是说使用托管的代码把底层的一些操作都封装起来了,不能直接进行内存的读取之类的和硬件相关的操作,优点就是比较安全,不会出现诸如内存泄露之类的问题,缺点也很明显,不能直接读取内存,性能上会有损失,使用起来有时也不够灵活。
非托管的刚好相反,可以直接进行硬件操作,性能比较高,但是对开发人员的要求也比较高。
最直观的就是c#不推荐使用指针,而c++就可以使用指针来直接读取内存;
c#使用垃圾回收,c++要手动的释放对象……
托管代码:
”托管“的含义就是,这些语言的后台(隐性的)操作都由这个管理系统(.Net)完成了,你把你的编程委托给了开发平台(库)来完成。当你使用这些语言时,一些系统资源的调用、回收、编译……各种工作都由它来完成,你只需要专注于程序功能的实现即可。
非托管代码:
就是指不在你这个集成开发环境里,而是使用其它的开发平台写出的程序(代码)。比如说java语言(不是jscript),basic语言(不是VB),C语言(不是VC/C++/C#)等等……它们也有自己的开发平台和程序,用这些语言写出的程序就属于”非托管“。
当非托管的代码在你的托管平台上运行时,你的托管平台就不能很好地处理一些后台(隐性的)操作,就需要编写额外的代码来使它们变得和谐并且安全。
5.lock关键字可以用来确保代码块完成运行,而不会被其他线程中断。
方法:
lock(expression)statement_block
expression:希望跟踪的对象,通常是对象引用;
statement_block:互斥段的代码;
如果你想保护一个类的实例,一般地,你可以使用this;如果你想保护一个静态变量(如互斥代码段在一个静态方法内部),一般使用类名就可以了。
而statement_block就是互斥段的代码,这段代码在一个时刻内只可能被一个线程执行。
lock 关键字可以用来确保代码块完成运行,而不会被其他线程中断。它可以把一段代码定义为互斥段(critical section),互斥段在一个时刻内只允许一个线程进入执行,而其他线程必须等待。这是通过在代码块运行期间为给定对象获取互斥锁来实现的。