I want to get finger positions in Leap motion using c#.I'm new to leap motion controller. So i Couldn't find any example code for detecting finger positions, but i tried to come up with some code. I think it has lot of errors.
So, how to get finger positions in Leap Motion using C#?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Leap;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form, ILeapEventDelegate
{
private Controller controller;
private LeapEventListener listener;
public Form1()
{
InitializeComponent();
this.controller = new Controller();
this.listener = new LeapEventListener(this);
controller.AddListener(listener);
}
delegate void LeapEventDelegate(string EventName);
public void LeapEventNotification(string EventName)
{
if (!this.InvokeRequired)
{
switch (EventName)
{
case "onInit":
MessageBox.Show("onInit");
break;
case "onConnect":
MessageBox.Show("onConnect");
break;
case "onFrame":
MessageBox.Show("onFrame");
break;
}
}
else
{
BeginInvoke(new LeapEventDelegate(LeapEventNotification), new object[] {
EventName });
}
}
private void Form1_Load(object sender, EventArgs e)
{
}
}
public interface ILeapEventDelegate
{
void LeapEventNotification(string EventName);
}
public class LeapEventListener : Listener
{
ILeapEventDelegate eventDelegate;
public LeapEventListener(ILeapEventDelegate delegateObject)
{
this.eventDelegate = delegateObject;
}
public override void OnInit(Controller controller)
{
this.eventDelegate.LeapEventNotification("onInit");
}
public override void OnConnect(Controller controller)
{
this.eventDelegate.LeapEventNotification("onConnect");
}
public override void OnFrame(Controller controller)
{
this.eventDelegate.LeapEventNotification("onFrame");
}
public override void OnExit(Controller controller)
{
this.eventDelegate.LeapEventNotification("onExit");
}
public override void OnDisconnect(Controller controller)
{
this.eventDelegate.LeapEventNotification("onDisconnect");
}
}
}
Your code looks like it is derived from the documentation example. However, you have left out the actual event handlers so nothing will ever happen.
You will see in the linked example that there is a newFrameHandler function. You can change that to access the finger positions in the frame object, which is a snapshot of the tracked hands at a moment in time.
void newFrameHandler(Frame frame)
{
foreach(Finger in frame.Fingers){
Vector fingerPosition = finger.TipPosition;
//Do something with this information...
}
}
You can similarly get the hands and then access each hand's fingers, which often is the more natural approach:
foreach(Hand hand in frame.Hands){
foreach(Finger in hand.Fingers){
Vector fingerPosition = finger.TipPosition;
//Do something with this information...
}
}
Related
I am very new to C# and try to use Microsoft.MixedReality.QR for reading some QRCodes with the Hololense 2 and have problems accessing the events of the QRCodeWatcher. According to the API, the QRCodeWatcher class has 4 events but it seems that these are never triggered. (QR_Added, QR_Updated,... are never called). Am I setting up something wrong?
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Microsoft.MixedReality.QR;
using QRTracking;
namespace QRTracking {
public class Detector: MonoBehaviour {
public TextMesh debugScreen;
public bool IsSupported {get; private set; }
private QRCodeWatcher qrTracker;
private bool QRstarted=false;
private QRCodeWatcherAccessStatus accessStatus;
// Start is called before the first frame update
async protected virtual void Start() {
debugScreen.text="Hello";
if (QRCodeWatcher.IsSupported()) {
try {
accessStatus=await QRCodeWatcher.RequestAccessAsync();
debugScreen.text=accessStatus.ToString();
}
catch {
debugScreen.text="No World";
}
}
}
// Update is called once per frame
void Update() {
if (accessStatus.ToString()=="Allowed") {
if (QRstarted==false) {
debugScreen.text="Setup Tracking";
SetupQRTracking();
QRstarted=true;
}
}
}
private void SetupQRTracking() {
qrTracker=new QRCodeWatcher();
qrTracker.Added+=QR_Added;
qrTracker.Updated+=QR_Updated;
qrTracker.Removed+=QR_Removed;
qrTracker.EnumerationCompleted+=QR_Enum;
qrTracker.Start();
debugScreen.text="Tracking started";
}
private void QR_Added(object sender, QRCodeAddedEventArgs args) {
debugScreen.text="Added";
}
private void QR_Updated(object sender, QRCodeUpdatedEventArgs args) {
debugScreen.text="Updated";
}
private void QR_Removed(object sender, QRCodeRemovedEventArgs args) {
debugScreen.text="Removed";
}
private void QR_Enum(object sender, object e) {
debugScreen.text="Enum";
}
}
}
(While the script is running the HoloLense is able to read the content of a QRCode. The debugScreen is a TextMesh so that I can see the text while wearing the HoloLense.)
Workaround to get only the recently seen QR codes to mimic the update event:
private IReadOnlyList<QRCode> detectedQR;
private DateTimeOffset timestamp;
private int timetolerance = 1; // seconds
detectedQR = qrTracker.GetList();
timestamp = DateTimeOffset.Now;
foreach (var QR in detectedQR)
{if ((timestamp - QR.LastDetectedTime ).Duration() < TimeSpan.FromSeconds(timetolerance))
{
//Do stuff with QR Codes seen in the last second
}
}
However, with too many QR codes, performance could suffer.
Hi I’m Wayne Wang from the Microsoft for Founders Hub team!
We do have an example from my colleague on your current context.
Seems the implementation you may need is here:
https://github.com/chgatla-microsoft/QRTracking/blob/master/SampleQRCodes/Assets/Scripts/QRCodesManager.cs
it was little bit of old but I believe the Interfaces and pipelines still the same
I new in Xamarin forms and C#.
I am trying to scan BLE device using the native Xamarin forms API, the code attached. I am using the Xiomi note 5 running android 9.
using Android.Bluetooth;
using Android.Bluetooth.LE;
using Android.Runtime;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using Xamarin.Forms;
namespace bletest
{
// Learn more about making custom code visible in the Xamarin.Forms previewer
// by visiting https://aka.ms/xamarinforms-previewer
[DesignTimeVisible(false)]
public class MyScanCallback : ScanCallback
{
public override void OnBatchScanResults(IList<ScanResult> results)
{
base.OnBatchScanResults(results);
}
public override void OnScanResult([GeneratedEnum] ScanCallbackType callbackType, ScanResult result)
{
base.OnScanResult(callbackType, result);
}
public override void OnScanFailed([GeneratedEnumAttribute] ScanFailure errorCode)
{
base.OnScanFailed(errorCode);
}
}
public class newbtle
{
private readonly BluetoothAdapter _ba;
private readonly BluetoothLeScanner _sc;
private readonly MyScanCallback _scCb;
public newbtle()
{
_ba = BluetoothAdapter.DefaultAdapter;
_sc = _ba.BluetoothLeScanner;
_scCb = new MyScanCallback();
}
public void BleScan()
{
if (_ba.Enable() == true)
{
_sc.StartScan(_scCb);
}
}
public void BleScanStop()
{
_sc.StopScan(_scCb);
_sc.FlushPendingScanResults(_scCb);
_ba.Disable();
}
public string GetScanMode()
{
return _ba.ScanMode.ToString();
}
public string GetStateMode()
{
return _ba.State.ToString();
}
}
public partial class MainPage : ContentPage
{
newbtle bt = new newbtle();
public MainPage()
{
InitializeComponent();
}
private void Button_Clicked(object sender, EventArgs e)
{
bt.BleScan();
}
private void Button_Clicked_1(object sender, EventArgs e)
{
bt.BleScanStop();
}
}
}
When a call is made to bt.BleScan no call back is called, when the bt.BleScan called in the second time without turning the scanner off the OnScanFailed is called with 'already active error'.
When I run the BLE explorer utility on the same mobile in the same environment it scan few BLE devices.
Any suggestion what can be the problem?
Thanks
A quick brief of the program that i have already done.
Golfer: A Golfer can be equipped with a Golf Club using the PickUp method; the golf club is
then stored in the Golfer’s club field. The Golfer’s holding property is true when its golf club
field is not null. When the Golfer is told to Swing, the following occurs:
If the Golfer is holding a golf club:
“Breathe and focus” is printed to the console. (b) The Golfer tells its club to swing.
Else…
“Where is my caddy?” is printed to the console.
GolfClub: Any golf club that can be swung; a GolfClub can also be held by a Golfer. GolfClub
is an abstract base class.
Putter: A Putter is a GolfClub that, when swung, prints “putt putt putt”.
SandWedge: A SandWedge is a GolfClub that can be swung 5 times before it is thrown in
frustration. (The constructor sets the swing counter to 5 and calling the Throw method resets
the play counter to 5.) When a SandWedge is swung, it does one of two things: if the remaining swing count is larger than zero, it prints “I am in my happy place” and the swing count is
decremented by one; otherwise it prints “hand me my hockey stick”.
My problem:
Code that uses a Golfer object may, therefore, ask for a specific golf club to be operated by referring
to that GolfClub by name. I'm not expected to get input from the user, just embedding it directly in Program.cs is totally fine. So basically a golfer wants to play, either select putter or sandwedge.
My code:
Program.cs
namespace Test
{
public class Program
{
private enum GolfKind
{
Putter, SandWedge
}
public static void Main(string[] args)
{
Golfer golfer = new Golfer();
Putter putt = new Putter();
SandWedge sandwedge = new SandWedge();
golfer.PickUp(putt);
golfer.PickUp(sandwedge);
if (golfer.Holding == true)
{
Console.WriteLine("Breate and Focus");
golfer.Swing(putt);
golfer.Swing(sandwedge);
}
else
{
Console.WriteLine("Where is my Caddy?");
}
Console.ReadLine();
}
}
}
GolfClub.cs
using System;
using System.Collections.Generic;
using System.Text;
namespace Test
{
public abstract class GolfClub
{
public GolfClub() { }
public abstract void Swing();
}
}
Golfer.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Test
{
public class Golfer
{
private List<GolfClub> _clubs;
public Golfer()
{
_clubs = new List<GolfClub>();
}
public bool Holding
{
get
{
if(_clubs.Count() != 0)
{
return true;
}
else
{
return false;
}
}
}
public void PickUp(GolfClub club)
{
_clubs.Add(club);
}
public void Swing(GolfClub club)
{
foreach (GolfClub gc in _clubs)
{
if (gc == club)
{
gc.Swing();
}
}
}
}
}
SandWedge.cs
using System;
using System.Collections.Generic;
using System.Text;
namespace Test
{
public class SandWedge : GolfClub
{
private int _count;
public SandWedge()
{
_count = 5;
}
public override void Swing()
{
while(_count > 0)
{
Console.WriteLine("I am in my happy place");
_count--;
}
if (_count == 0)
{
Console.WriteLine("hand me my hockey stick");
}
}
public void Throw()
{
_count = 5;
}
}
}
Putter.cs
using System;
using System.Collections.Generic;
using System.Text;
namespace Test
{
public class Putter : GolfClub
{
public Putter () {}
public override void Swing()
{
Console.WriteLine("putt putt putt");
}
}
}
You can use a IDictionary<string, GolfClub> to associate a name with a golf club. Provide the name as a new argument for the PickUp() method. Then use a string argument in the Swing() method to find the right club.
public class Golfer
{
private readonly IDictionary<string, GolfClub> _clubs = new Dictionary<string, GolfClub>();
// [...]
public void PickUp(GolfClub club, string name) {
_clubs.Add(name, club);
}
public void Swing(string name) {
_clubs[name].Swing();
}
}
This problem has been addressed in SOF in general. However, I am unable (not competent enough) to apply the suggestions to this example. I am getting the "Cannot access a non-static member of outer type 'FixClientTest.Form1' via nested type ... " error. In this case, the nested type is an instantiation of a 3rd party provided class (in this case, the open-source QuickFix/n library). I understand that the source is not really relevant but I am trying to avoid any suggestion that might have me modifying that code and don't have the knowledge to get around the problem. My goal is simply to update form controls based on information that I get in the callbacks from this library. (The code below is just a simple form with 2 buttons, one to set up the event callbacks and the other to stop them.) I would greatly appreciate any suggestions that the community might have.
Thank You.
using System;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using QuickFix;
namespace FixClientTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public class MyQuickFixApp : QuickFix.IApplication
{
public void FromApp(QuickFix.Message msg, SessionID sessionID) { }
public void OnCreate(SessionID sessionID) { }
public void OnLogout(SessionID sessionID)
{
Console.WriteLine("Logged out.");
}
public void OnLogon(SessionID sessionID)
{
Console.WriteLine("Logged In.");
}
public void FromAdmin(QuickFix.Message msg, SessionID sessionID)
{
//logListView.Items.Add(msg.ToString()); <<GENERATES ERROR!
}
public void ToAdmin(QuickFix.Message msg, SessionID sessionID) { }
public void ToApp(QuickFix.Message msg, SessionID sessionID) { }
}
public QuickFix.Transport.SocketInitiator _Initiator = null;
private void connectButton_Click(object sender, EventArgs e)
{
string file = "c:/FIX/tradeclientIB.cfg";
try
{
QuickFix.SessionSettings settings = new QuickFix.SessionSettings(file);
QuickFix.IApplication myApp = new MyQuickFixApp();
QuickFix.IMessageStoreFactory storeFactory = new QuickFix.FileStoreFactory(settings);
QuickFix.ILogFactory logFactory = new QuickFix.ScreenLogFactory(settings);
_Initiator = new QuickFix.Transport.SocketInitiator(myApp, storeFactory, settings, logFactory);
_Initiator.Start();
}
catch (System.Exception err)
{
MessageBox.Show(err.ToString());
}
}
private void stopButton_Click(object sender, EventArgs e)
{
_Initiator.Stop();
}
}
}
Your MyQuickFixApp class doesn't know anything about the Form1 object.
First, I'd suggest moving it out of the Form1 class.
Then, I'd look at how and when the MyQuickFixApp object is created. I'm not familiar with the QuickFix library, but a quick glance at the docs suggests that creating it in a button message handler isn't the right way to do this. (In a winforms app I'd imagine you'd create it in your Program.Main method).
As for the actual error, you need to give the MyQuickFixApp object a reference to the Form1 object (probably pass it in the constructor).
public class MyQuickFixApp : QuickFix.IApplication
{
private readonly Form1 _form1;
public MyQuickFixApp(Form1 form)
{
_form1 = form;
}
public void FromAdmin(QuickFix.Message msg, SessionID sessionID)
{
_form1.logListView.Items.Add(msg.ToString());
}
}
While I was waiting for answers, I took another look at an answer provided in this link:
Property is inaccessible due to its protection level When I read it again more carefully this time, I realized that Steve had posted the answer I need so it is really his answer. I needed to restructure this using events to capture the change in the form and to preserve encapsulation. It also allowed me to move my class that updated the form out of the Form class, however, it created the much-feared "cross-thread" problem. I already had an answer for this from someone else (sorry, don't have that link). I added lines to the event that updates the form to spin it off as a new thread. I've done this before and it works nicely. If anyone thinks this might be a problem, please let me know. Apologies if I've wasted anyone's time in looking at my problem but I thought I would share the mix of answers because it solves two of the biggest problems I've had since learning c#/forms.
One thing, don't get confused about this declaration: private delegate void AddLogItemDelegate(string msg); It is related to creating the thread containing the AddLogItem function and not to the creation of the event.
Thanks
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using QuickFix;
namespace FixClientTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public QuickFix.Transport.SocketInitiator _Initiator = null;
private void connectButton_Click(object sender, EventArgs e)
{
string file = "c:/FIX/tradeclientIB.cfg";
try
{
QuickFix.SessionSettings settings = new QuickFix.SessionSettings(file);
QuickFix.IApplication myApp = new MyQuickFixApp();
QuickFix.IMessageStoreFactory storeFactory = new QuickFix.FileStoreFactory(settings);
QuickFix.ILogFactory logFactory = new QuickFix.ScreenLogFactory(settings);
//QuickFix.Transport.SocketInitiator initiator = new QuickFix.Transport.SocketInitiator(myApp, storeFactory, settings, logFactory);
_Initiator = new QuickFix.Transport.SocketInitiator(myApp, storeFactory, settings, logFactory);
MyQuickFixApp.UpdateEvent += new MyQuickFixApp.OnUpdateEvent(AddLogItem);
_Initiator.Start();
}
catch (System.Exception err)
{
Console.WriteLine(err.Message);
Console.WriteLine(err.StackTrace);
MessageBox.Show(err.ToString());
}
}
private void stopButton_Click(object sender, EventArgs e)
{
_Initiator.Stop();
}
public string stuff;
private delegate void AddLogItemDelegate(string msg);
public void AddLogItem(string msg)
{
if(this.InvokeRequired)
{
this.Invoke(new AddLogItemDelegate(AddLogItem), new object[] { msg });
return;
}
try
{
logListView.Items.Add(msg);
}
catch(Exception err)
{
MessageBox.Show(err.ToString());
}
}
}
public class MyQuickFixApp : QuickFix.IApplication
{
public delegate void OnUpdateEvent(string msg);
public static event OnUpdateEvent UpdateEvent;
public void FromApp(QuickFix.Message msg, SessionID sessionID) { }
public void OnCreate(SessionID sessionID) { }
public void OnLogout(SessionID sessionID)
{
Console.WriteLine("Logged out.");
}
public void OnLogon(SessionID sessionID)
{
UpdateEvent("STUFF!!");
Console.WriteLine("Logged In.");
}
public void FromAdmin(QuickFix.Message msg, SessionID sessionID)
{
}
public void ToAdmin(QuickFix.Message msg, SessionID sessionID) { }
public void ToApp(QuickFix.Message msg, SessionID sessionID) { }
}
}
How do I get a button click on a form to send the return of a called method to another class? Here is the pseudo code of what I have and any help would be greatly appreciated...
[Class Library]
using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Collections.Generic;
using System.Linq;
namespace Auto
{
GUID Info
public interface IAuto
{
string SendToOtherApp();
}
COM Info
public class Auto : IAuto
{
public string tbox1;
NAVForm frm1 = new NAVForm();
public Auto()
{
}
public string SendToOtherApp()
{
frm1.ShowDialog();
tbox1 = NAVForm.UseThis();
return tbox1;
}
}
}
[Form]
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Auto
{
public partial class NAVForm : Form
{
public NAVForm()
{
InitializeComponent();
}
private void NAVForm_Load(object sender, EventArgs e)
{
}
private void button2_Click(object sender, EventArgs e)
{
UseThis(textBox1.Text);
}
public string UseThis(string txt)
{
if (txt.Trim().Length != 0)
{
return txt;
}
else
{
return "didn't work";
}
}
}
}
I want to get the return value from public string UseThis(string txt) into public string SendToOtherApp() which is visible to the other system that is calling this.
I am obviously new to C# so I am also very open to an overall critique of the project and best practices.
This is what I have done and it works great. In our ERP I run the codeunit, which calls the automation variable which is tied to the "OpenThis()" method. My form opens, I enter text in the textbox, click OK, it closes the from and the ERP pops a messagebox displaying the text from the message box. What do you C# experts think about this build? I am very interested in your thoughts on this solution so please let me know.
Class Library.....
using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Collections.Generic;
using System.Linq;
namespace NavAutomation
{
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
[Guid("5D83B4FE-45E6-410E-A075-AD635F5F0354")]
[ComVisible(true)]
public interface INavAutomation
{
string HelloWorld();
object OpenThis();
}
[ComVisible(true)]
[Guid("B7806CE5-862A-4407-9A3E-14CE8A9FB83A")]
[ClassInterface(ClassInterfaceType.None)]
public class NavAutomation : INavAutomation
{
public NavAutomation()
{
}
public object OpenThis()
{
using (var form = new NAVForm())
{
var result = form.ShowDialog();
return form.RetVal1;
}
}
}
}
Form.....
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace NavAutomation
{
public partial class NAVForm : Form
{
public NAVForm()
{
InitializeComponent();
}
private void NAVForm_Load(object sender, EventArgs e)
{
}
public string RetVal1 { get; set; }
private void button2_Click(object sender, EventArgs e)
{
if (textBox1.Text.Trim().Length != 0)
{
this.RetVal1 = textBox1.Text;
}
else
{
this.RetVal1 = "didn't work";
}
this.Close();
}
}
}
I am not sure if i got your goals right but here is the code that when called from a from, shows another modal form with a textbox, you enter a value into that textbox and close this modal form to find that value in that textbox returned to the first form that called for the show of the modal form.
CLASS LIBRARY
using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Collections.Generic;
using System.Linq;
namespace Auto
{
public interface IAuto
{
string SendToOtherApp();
}
public class Auto : IAuto
{
public string tbox1;
NAVForm frm1 = new NAVForm();
public Auto()
{
}
public string SendToOtherApp()
{
frm1.ShowDialog();
tbox1 = frm1.UseThis(frm1.textBox1.Text);
return tbox1;
}
}
}
A FROM THAT CALLS TO SHOW A MODAL FORM
namespace Auto
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Auto auto = new Auto();
string returnedString = auto.SendToOtherApp(); // the string filled at the modal form text boxed will be returned to this variable
}
}
THE FORM THAT WILL BE SHOWED AS MODAL FORM
namespace Auto
{
public partial class NAVForm : Form
{
public NAVForm()
{
InitializeComponent();
}
public string UseThis(string txt)
{
if (txt.Trim().Length != 0)
{
return txt;
}
else
{
return "didn't work";
}
}
private void button1_Click(object sender, EventArgs e)
{
UseThis(textBox1.Text);
}
}
}
Please note that the access modifier of textBox1 at NAVForm should be set to public in order for it to be visible to class Auto
Let me know if i misunderstood something to correct it.