Scripting: Having fun with C# and UDP

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Scripting: Having fun with C# and UDP

Jeff Kelley
That's a thing I was dreaming for years : Linking a physical, real-world
object to an opensim object. You move the object in opensim, the real
object moves. You move the real object, the object in opensim moves. All in
real-time.

Here is a short demo video, in mov and mp4 (H.264) format. If your web
browser can't handle either, download the .mp4 version and open it with
VLC. I don't Youtube, sorry.

http://www.pescadoo.net/tmp/fun_with_udp.mov        (1Mb)
http://www.pescadoo.net/tmp/fun_with_udp.mp4        (1.9Mb)

Right is the familiar Imprudence window. The object with eight yellow bars
is a multi-slider, similar to a mixing desk. Each bar can be clicked and
dragged to the desired value.

Left is a less-familiar window with another application running. The app is
Cycling74' Max/MSP, although that could any app that can animate objects
(graphical or physical) and read/write network sockets.

In this video, i first move the slider in opensim and you see the sliders
in the external app moving. Then I move the sliders in the external app,
and the sliders in opensim move. No delay. Real-time.

But there is more fun. The external app is linked to a physical "control
surface", with motorized sliders. Unfortunately I can't show it in the
video, missing a camcorder. I use a Behringer BCF2000. See it here:

http://www.behringer.com/EN/images/lightboxphotos/BCF2000_P0246_Left_XL.jpg

It is attached to my desktop machine (not the simulator host) via USB/MIDI.
You could as well control lights with DMX, motors with Arduino, a robotic
device, or conversely move an opensim object with a dataglove, or anything
you may imagine.

How does it work?

The opensim object contains two C# script, one for sending and one for
receiving UDP messages using System.Net.Sockets (two scripts are needed
because the receiver runs a forever loop and events can't interrupt). The
simulator host and my desktop machine (both on same LAN) communicate
through UDP messages.

I omit the prim handling script for brevity. It is pure LSL and there is
nothing new here. It reads and writes couples of (track_number, value) via
link messages to the C# sender and receiver. Since i am a beginner in C#,
there is much room for improvement. I was not able to declare a 'use'
clause, so I had to fully qualify each instance and method, making the code
quite ugly.



UDP Sender script
-----------------

//c#

public static void SendUDPPacket (string hostNameOrAddress,
                                  int destinationPort, string data) {

    // Resolve the host name to an IP Address
    System.Net.IPAddress[] ipAddresses
        = System.Net.Dns.GetHostAddresses(hostNameOrAddress);

    // Use the first IP Address in the list
    System.Net.IPAddress destination = ipAddresses[0];
    System.Net.IPEndPoint endPoint
        = new System.Net.IPEndPoint(destination, destinationPort);

    byte[] buffer = System.Text.Encoding.ASCII.GetBytes(data);

    // Send the packet
    System.Net.Sockets.Socket socket = new System.Net.Sockets.Socket
        (System.Net.Sockets.AddressFamily.InterNetwork,
         System.Net.Sockets.SocketType.Dgram,
         System.Net.Sockets.ProtocolType.Udp);

    socket.SendTo(buffer, endPoint);
    socket.Close();
}

int SLIDER_IN  = 101;       // Link Messages input
int SLIDER_OUT = 102;       // Link Messages output

string  remoteAddr = "192.168.0.21";
int     remotePort = 51000;

// Receiving a link message from the sliders

public void default_event_link_message (
    LSL_Types.LSLInteger sender_num,
    LSL_Types.LSLInteger num,
    LSL_Types.LSLString str,    // Channel number
    LSL_Types.LSLString id) {   // Channel value

    // Send the message over UDP

    if (num == SLIDER_OUT)
        SendUDPPacket (remoteAddr, remotePort, str+" "+id);
}



UDP Receiver script
-------------------

//c#

public static System.Net.Sockets.Socket BindUDPSocket (int listenPort) {

    // Local endpoint
    System.Net.IPEndPoint endPoint
        = new System.Net.IPEndPoint(System.Net.IPAddress.Any, listenPort);

    // Create socket
    System.Net.Sockets.Socket socket = new System.Net.Sockets.Socket
        (System.Net.Sockets.AddressFamily.InterNetwork,
         System.Net.Sockets.SocketType.Dgram,
         System.Net.Sockets.ProtocolType.Udp);

    // Bind socket
    socket.Bind(endPoint);
    return socket;
}


int listenPort = 50000;

int SLIDER_IN  = 101;       // Link Messages input
int SLIDER_OUT = 102;       // Link Messages output

public void default_event_state_entry() {
    System.Net.Sockets.Socket socket = BindUDPSocket (listenPort);
    byte[] buffer = new byte[1024];

    // Receiving a message from UDP (loop forever)

    while (true) {
        socket.Receive(buffer);
        string msg = System.Text.ASCIIEncoding.ASCII.GetString(buffer);

        // 1st word is Channel number
        // 2nd word is Channel value

        string[] parse = msg.Split(' ');

        // Send the message using LinkMessage

        llMessageLinked (LINK_THIS, SLIDER_IN, parse[0], parse[1]);

        System.Array.Clear (buffer, 0, 1024);
    }
}


Thanks to Nick Olsen for C# code
http://nickstips.wordpress.com/2010/09/03/c-creating-and-sending-udp-packets/
_______________________________________________
Opensim-users mailing list
[hidden email]
https://lists.berlios.de/mailman/listinfo/opensim-users
Reply | Threaded
Open this post in threaded view
|

Re: Scripting: Having fun with C# and UDP

ssm2017
wao, great idea to share things like that
thank you a lot Jeff for sharing :)

2011/5/3 Jeff Kelley <[hidden email]>:

> That's a thing I was dreaming for years : Linking a physical, real-world
> object to an opensim object. You move the object in opensim, the real
> object moves. You move the real object, the object in opensim moves. All in
> real-time.
>
> Here is a short demo video, in mov and mp4 (H.264) format. If your web
> browser can't handle either, download the .mp4 version and open it with
> VLC. I don't Youtube, sorry.
>
> http://www.pescadoo.net/tmp/fun_with_udp.mov    (1Mb)
> http://www.pescadoo.net/tmp/fun_with_udp.mp4    (1.9Mb)
>
> Right is the familiar Imprudence window. The object with eight yellow bars
> is a multi-slider, similar to a mixing desk. Each bar can be clicked and
> dragged to the desired value.
>
> Left is a less-familiar window with another application running. The app is
> Cycling74' Max/MSP, although that could any app that can animate objects
> (graphical or physical) and read/write network sockets.
>
> In this video, i first move the slider in opensim and you see the sliders
> in the external app moving. Then I move the sliders in the external app,
> and the sliders in opensim move. No delay. Real-time.
>
> But there is more fun. The external app is linked to a physical "control
> surface", with motorized sliders. Unfortunately I can't show it in the
> video, missing a camcorder. I use a Behringer BCF2000. See it here:
>
> http://www.behringer.com/EN/images/lightboxphotos/BCF2000_P0246_Left_XL.jpg
>
> It is attached to my desktop machine (not the simulator host) via USB/MIDI.
> You could as well control lights with DMX, motors with Arduino, a robotic
> device, or conversely move an opensim object with a dataglove, or anything
> you may imagine.
>
> How does it work?
>
> The opensim object contains two C# script, one for sending and one for
> receiving UDP messages using System.Net.Sockets (two scripts are needed
> because the receiver runs a forever loop and events can't interrupt). The
> simulator host and my desktop machine (both on same LAN) communicate
> through UDP messages.
>
> I omit the prim handling script for brevity. It is pure LSL and there is
> nothing new here. It reads and writes couples of (track_number, value) via
> link messages to the C# sender and receiver. Since i am a beginner in C#,
> there is much room for improvement. I was not able to declare a 'use'
> clause, so I had to fully qualify each instance and method, making the code
> quite ugly.
>
>
>
> UDP Sender script
> -----------------
>
> //c#
>
> public static void SendUDPPacket (string hostNameOrAddress,
>                                  int destinationPort, string data) {
>
>    // Resolve the host name to an IP Address
>    System.Net.IPAddress[] ipAddresses
>        = System.Net.Dns.GetHostAddresses(hostNameOrAddress);
>
>    // Use the first IP Address in the list
>    System.Net.IPAddress destination = ipAddresses[0];
>    System.Net.IPEndPoint endPoint
>        = new System.Net.IPEndPoint(destination, destinationPort);
>
>    byte[] buffer = System.Text.Encoding.ASCII.GetBytes(data);
>
>    // Send the packet
>    System.Net.Sockets.Socket socket = new System.Net.Sockets.Socket
>        (System.Net.Sockets.AddressFamily.InterNetwork,
>         System.Net.Sockets.SocketType.Dgram,
>         System.Net.Sockets.ProtocolType.Udp);
>
>    socket.SendTo(buffer, endPoint);
>    socket.Close();
> }
>
> int SLIDER_IN  = 101;       // Link Messages input
> int SLIDER_OUT = 102;       // Link Messages output
>
> string  remoteAddr = "192.168.0.21";
> int     remotePort = 51000;
>
> // Receiving a link message from the sliders
>
> public void default_event_link_message (
>    LSL_Types.LSLInteger sender_num,
>    LSL_Types.LSLInteger num,
>    LSL_Types.LSLString str,    // Channel number
>    LSL_Types.LSLString id) {   // Channel value
>
>    // Send the message over UDP
>
>    if (num == SLIDER_OUT)
>        SendUDPPacket (remoteAddr, remotePort, str+" "+id);
> }
>
>
>
> UDP Receiver script
> -------------------
>
> //c#
>
> public static System.Net.Sockets.Socket BindUDPSocket (int listenPort) {
>
>    // Local endpoint
>    System.Net.IPEndPoint endPoint
>        = new System.Net.IPEndPoint(System.Net.IPAddress.Any, listenPort);
>
>    // Create socket
>    System.Net.Sockets.Socket socket = new System.Net.Sockets.Socket
>        (System.Net.Sockets.AddressFamily.InterNetwork,
>         System.Net.Sockets.SocketType.Dgram,
>         System.Net.Sockets.ProtocolType.Udp);
>
>    // Bind socket
>    socket.Bind(endPoint);
>    return socket;
> }
>
>
> int listenPort = 50000;
>
> int SLIDER_IN  = 101;       // Link Messages input
> int SLIDER_OUT = 102;       // Link Messages output
>
> public void default_event_state_entry() {
>    System.Net.Sockets.Socket socket = BindUDPSocket (listenPort);
>    byte[] buffer = new byte[1024];
>
>    // Receiving a message from UDP (loop forever)
>
>    while (true) {
>        socket.Receive(buffer);
>        string msg = System.Text.ASCIIEncoding.ASCII.GetString(buffer);
>
>        // 1st word is Channel number
>        // 2nd word is Channel value
>
>        string[] parse = msg.Split(' ');
>
>        // Send the message using LinkMessage
>
>        llMessageLinked (LINK_THIS, SLIDER_IN, parse[0], parse[1]);
>
>        System.Array.Clear (buffer, 0, 1024);
>    }
> }
>
>
> Thanks to Nick Olsen for C# code
> http://nickstips.wordpress.com/2010/09/03/c-creating-and-sending-udp-packets/
> _______________________________________________
> Opensim-users mailing list
> [hidden email]
> https://lists.berlios.de/mailman/listinfo/opensim-users
>
_______________________________________________
Opensim-users mailing list
[hidden email]
https://lists.berlios.de/mailman/listinfo/opensim-users
Reply | Threaded
Open this post in threaded view
|

Re: Scripting: Having fun with C# and UDP

paul emery
In reply to this post by Jeff Kelley
too cool
Reply | Threaded
Open this post in threaded view
|

Re: Scripting: Having fun with C# and UDP

justincc
In reply to this post by Jeff Kelley
Very cool, Jeff.

The issue with using in C# scripts is that, like translated LSL -> C# scripts, they are embedded within some C# preamble
in order to compile the script, which one can see at
OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs:CreateCSCompilerScript().

I should think that one could work around this by moving using statements in a C# script into that preamble.

On 03/05/11 00:49, Jeff Kelley wrote:

> That's a thing I was dreaming for years : Linking a physical, real-world
> object to an opensim object. You move the object in opensim, the real
> object moves. You move the real object, the object in opensim moves. All in
> real-time.
>
> Here is a short demo video, in mov and mp4 (H.264) format. If your web
> browser can't handle either, download the .mp4 version and open it with
> VLC. I don't Youtube, sorry.
>
> http://www.pescadoo.net/tmp/fun_with_udp.mov        (1Mb)
> http://www.pescadoo.net/tmp/fun_with_udp.mp4        (1.9Mb)
>
> Right is the familiar Imprudence window. The object with eight yellow bars
> is a multi-slider, similar to a mixing desk. Each bar can be clicked and
> dragged to the desired value.
>
> Left is a less-familiar window with another application running. The app is
> Cycling74' Max/MSP, although that could any app that can animate objects
> (graphical or physical) and read/write network sockets.
>
> In this video, i first move the slider in opensim and you see the sliders
> in the external app moving. Then I move the sliders in the external app,
> and the sliders in opensim move. No delay. Real-time.
>
> But there is more fun. The external app is linked to a physical "control
> surface", with motorized sliders. Unfortunately I can't show it in the
> video, missing a camcorder. I use a Behringer BCF2000. See it here:
>
> http://www.behringer.com/EN/images/lightboxphotos/BCF2000_P0246_Left_XL.jpg
>
> It is attached to my desktop machine (not the simulator host) via USB/MIDI.
> You could as well control lights with DMX, motors with Arduino, a robotic
> device, or conversely move an opensim object with a dataglove, or anything
> you may imagine.
>
> How does it work?
>
> The opensim object contains two C# script, one for sending and one for
> receiving UDP messages using System.Net.Sockets (two scripts are needed
> because the receiver runs a forever loop and events can't interrupt). The
> simulator host and my desktop machine (both on same LAN) communicate
> through UDP messages.
>
> I omit the prim handling script for brevity. It is pure LSL and there is
> nothing new here. It reads and writes couples of (track_number, value) via
> link messages to the C# sender and receiver. Since i am a beginner in C#,
> there is much room for improvement. I was not able to declare a 'use'
> clause, so I had to fully qualify each instance and method, making the code
> quite ugly.
>
>
>
> UDP Sender script
> -----------------
>
> //c#
>
> public static void SendUDPPacket (string hostNameOrAddress,
>                                    int destinationPort, string data) {
>
>      // Resolve the host name to an IP Address
>      System.Net.IPAddress[] ipAddresses
>          = System.Net.Dns.GetHostAddresses(hostNameOrAddress);
>
>      // Use the first IP Address in the list
>      System.Net.IPAddress destination = ipAddresses[0];
>      System.Net.IPEndPoint endPoint
>          = new System.Net.IPEndPoint(destination, destinationPort);
>
>      byte[] buffer = System.Text.Encoding.ASCII.GetBytes(data);
>
>      // Send the packet
>      System.Net.Sockets.Socket socket = new System.Net.Sockets.Socket
>          (System.Net.Sockets.AddressFamily.InterNetwork,
>           System.Net.Sockets.SocketType.Dgram,
>           System.Net.Sockets.ProtocolType.Udp);
>
>      socket.SendTo(buffer, endPoint);
>      socket.Close();
> }
>
> int SLIDER_IN  = 101;       // Link Messages input
> int SLIDER_OUT = 102;       // Link Messages output
>
> string  remoteAddr = "192.168.0.21";
> int     remotePort = 51000;
>
> // Receiving a link message from the sliders
>
> public void default_event_link_message (
>      LSL_Types.LSLInteger sender_num,
>      LSL_Types.LSLInteger num,
>      LSL_Types.LSLString str,    // Channel number
>      LSL_Types.LSLString id) {   // Channel value
>
>      // Send the message over UDP
>
>      if (num == SLIDER_OUT)
>          SendUDPPacket (remoteAddr, remotePort, str+" "+id);
> }
>
>
>
> UDP Receiver script
> -------------------
>
> //c#
>
> public static System.Net.Sockets.Socket BindUDPSocket (int listenPort) {
>
>      // Local endpoint
>      System.Net.IPEndPoint endPoint
>          = new System.Net.IPEndPoint(System.Net.IPAddress.Any, listenPort);
>
>      // Create socket
>      System.Net.Sockets.Socket socket = new System.Net.Sockets.Socket
>          (System.Net.Sockets.AddressFamily.InterNetwork,
>           System.Net.Sockets.SocketType.Dgram,
>           System.Net.Sockets.ProtocolType.Udp);
>
>      // Bind socket
>      socket.Bind(endPoint);
>      return socket;
> }
>
>
> int listenPort = 50000;
>
> int SLIDER_IN  = 101;       // Link Messages input
> int SLIDER_OUT = 102;       // Link Messages output
>
> public void default_event_state_entry() {
>      System.Net.Sockets.Socket socket = BindUDPSocket (listenPort);
>      byte[] buffer = new byte[1024];
>
>      // Receiving a message from UDP (loop forever)
>
>      while (true) {
>          socket.Receive(buffer);
>          string msg = System.Text.ASCIIEncoding.ASCII.GetString(buffer);
>
>          // 1st word is Channel number
>          // 2nd word is Channel value
>
>          string[] parse = msg.Split(' ');
>
>          // Send the message using LinkMessage
>
>          llMessageLinked (LINK_THIS, SLIDER_IN, parse[0], parse[1]);
>
>          System.Array.Clear (buffer, 0, 1024);
>      }
> }
>
>
> Thanks to Nick Olsen for C# code
> http://nickstips.wordpress.com/2010/09/03/c-creating-and-sending-udp-packets/
> _______________________________________________
> Opensim-users mailing list
> [hidden email]
> https://lists.berlios.de/mailman/listinfo/opensim-users
>


--
Justin Clark-Casey (justincc)
http://justincc.org/blog
http://twitter.com/justincc
_______________________________________________
Opensim-users mailing list
[hidden email]
https://lists.berlios.de/mailman/listinfo/opensim-users
Reply | Threaded
Open this post in threaded view
|

Re: Scripting: Having fun with C# and UDP

ffoliveira
In reply to this post by Jeff Kelley
Hello,

I just tried to use that script, but I got the "The given key was not present in the dictionary" error message.

I use Windows 7 x64 with OpenSim 0.7.2 (OSgrid Version)

At console id dont give any error.
Reply | Threaded
Open this post in threaded view
|

Re: Scripting: Having fun with C# and UDP

Sarrah12
This post has NOT been accepted by the mailing list yet.
This post was updated on .
In reply to this post by Jeff Kelley
Hello,

I'm currently doing a research work and i need to connect opensim to Max/msp.  Is there any tutorials on how to do it?

Thanks,
Sarrah