UE3 - UDK Using serial port data in UDK

  • Two Factor Authentication is now available on BeyondUnreal Forums. To configure it, visit your Profile and look for the "Two Step Verification" option on the left side. We can send codes via email (may be slower) or you can set up any TOTP Authenticator app on your phone (Authy, Google Authenticator, etc) to deliver codes. It is highly recommended that you configure this to keep your account safe.

silverwizard

New Member
Mar 13, 2013
8
0
0
Hello and well met!

First of all, apologies for the length of the post.

I started experimenting with UDK recently and I would like to use a motion tracker and a Head Mounted Display for navigating the 3d environment. The HMD part is the easy one, it just works as a second monitor straight out of the box. However, I will also need to set up a motion tracker and attach it to the HMD, so that rotation data can be somehow fed into UDK and used to set the player's rotation. The tracker I have access to is kinda old (but it seems to be working). It used a serial port, which I do not have. However, I am using a USB to serial adapter and I am able to see the raw data through programs such as HyperTerminal and Serial Port Monitor - I get a string of numbers, three for translation and three for rotation. So far so good. But how to have these numbers affect the player's view in my level? I noticed that the tracker does not appear as either a mouse or a game controller in Windows.

Now, I am no programmer, but I have a good grasp of programming concepts - I can mostly understand code I read, and even edit it to make it more useful. I have written a little bit of code as well, mostly JavaScript and ActionScript. I have also started reading Rachel Cordone's book on UnrealScript and so far it looks straightforward (although one level higher in complexity than simple scripting languages such as JS or AS).

So, my question essentially is this:
Is there a moderately straighforward way of having the data from the tracker influence the motion and (most improtantly) rotation of the player? In my nonexpert view of the situation, I have reached to the conclusion that I will have to use something called DLLBind, am I correct? Could you please point me to the right direction? I understand DLLs are created with C# or C++. Any good tutorials on how to access the data that comes through a serial port with these languages?

I may be able to enlist a programmer or two if it gets too technical (but then again, maybe not until a bit later), but I would appreciate if you could make your advice clear and accessible to someone who is currently learning.
 

Angel_Mapper

Goooooooats
Jun 17, 2001
3,532
3
38
Cape Suzette
www.angelmapper.com
You'll definitely want to use DLLBind for that (Chapter 10 of my book). You'd probably want to put it in a custom PlayerInput inside a custom PlayerController. The UnrealScript side of it would be easy. For the C++ side, no clue! :D
 

Nathaniel3W

Member
Nov 11, 2012
48
0
6
I don't know enough about C++ to write a .dll, but I agree with AngelMapper. That's how you'll want to do it. Make a .dll that gets data from the serial port and then bind the .dll in UDK.

If you want to get started right away without writing a .dll, you can try what I did with my first VR experiment here: http://www.youtube.com/watch?v=GWRVGlwkAx4

I have a Teensy microcontroller hooked up to an MPU 6050 gyro/accelerometer. And then I had the Teensy turn the gyro readings into mouse movement. It's a cheap fix and it's not an ideal one, but it worked for me.
 

silverwizard

New Member
Mar 13, 2013
8
0
0
Thank you both. I have actually done something towards implementing the DLL solution. I have adjusted some C++ code I found to access the serial port. It seems to be working ok, at a proof of concept level at least. Obviously it needs optimization, like I said I am not a programmer.

To cut a long story short, I can now take all six numbers (3 for translation and 3 for rotation) in UnrealScript as ints or floats, and I have presently attached the camera's and the pawn's yaw and pitch rotation. I can easily add the roll, but the problem I am now facing is that of lag. It may be that I am not using the best computer for this (will try it soon on a much more powerful computer), but it seems to be working ok for one axis, but when I add the second one, the lag is quite noticeable and I must somehow solve this because it may induce motion sickness - not to mention reduce the overall user experience.

I am currently using two dll-imported functions to get the rotation for the two axes I have implemented (RotateX and RotateY), which return an int each. I am fairly convinced that the problem lies somewhere on the UnrealScript side... I was told it might make things faster if I used only one DLL function call to get all the data at once and then process them in UnrealScript. I tried to test this, but I couldn't because a string comes to UnrealScript as a garbled piece of data (probably having something to do with Unicode), while I no such problem with numbers. I also tried passing a struct from C++ to UnrealScript, but I was also unsuccessful.

Angel_Mapper, I will read through the chapter in your book (hopefully I'll be able to understand some of it, despite the fact that I am only on chapter 6 right now). And Nathaniel, I will try your solution as well. Any suggestions will be greatly appreciated.
 

Nathaniel3W

Member
Nov 11, 2012
48
0
6
Good work getting that dll working. Unreal hasn't given me any trouble with lag while reading from a dll. I couldn't say for sure what's going wrong for you. What code did you modify? Maybe I could set up something similar and see what's happening. I'm sure I'm using different hardware, but if the data all goes through a serial port at the same speed, then one sensor should be much the same as any other.
 

silverwizard

New Member
Mar 13, 2013
8
0
0
Well, the lag issue was due to inept programming on my part. More specifically, I had implemented the rotation function i C++ in such a way that a separate call to the serial port was made for each axis. So, for all rotation data, I had three separate and completely identical serial port access calls. I was getting the same string of numbers, extracting a different bit every time. Pretty stupid of me actually.

I have corrected this function, it now takes the string only once and returns a struct named "rotator" containing three int values ("Pitch", "Yaw", and "Roll"); thus, all I need to do in unrealScript is SetRotation(RotateXYZ()). As a rotator is only a struct whose values have specific names, my data is already a rotator.

Also, as part of the same function, I am updating a struct called "Vector" and containing "X", "Y", and "Z" float values. In this way, what comes into UnrealScript is already a vector (same rationale). So, all it takes(*) is: Pawn.SetLocation(TranslateXYZ()).

(*) Obviously, I needed to convert the angle and position values to Unreal units, but it's no big deal as you can imagine.
 

silverwizard

New Member
Mar 13, 2013
8
0
0
The implementation I stated above had some issues with collision. I am suspecting that by calling Pawn.SetLocation(), I am not actually changing the player's location, but the location of the pawn and the camera.

I did it somewhat differently:

Controller class:
Code:
function PlayerTick(float DeltaTime)
{
    theRot = RotateXYZ(); // rotation info from tracker
    newLoc = TranslateXYZ(); // translation info from tracker

    super.PlayerTick(DeltaTime);
    
    SetRotation(theRot);

    Pawn.FaceRotation(theRot, DeltaTime);
    currentLoc = Location + newLoc;

    ProcessMove(DeltaTime, currentLoc, DCLICK_None, theRot);
}
I am now facing two problems:

1. At certain locations, like a long and narrow tunnel, the camera changes from first to third person, centered on my Pawn. With the pawn stationary, if I slightly twist the tracker, for instance changing the roll, it becomes first person again. If I twist it back, it goes back to the third person view. This also happens when I have the tracker deactivated and the relevant lines in the code commented out, so that the mouse is used.

2. When I try to apply my Game class to levels other than the one I created just for this test, which is nothing more than two rooms and a couple of corridors, the translation doesn't work properly. It seems as though there is some force applied on the player, moving him towards one direction only. The rotation works ok.

Right now I feel a little bit overwhelmed by the multitude of properties and classes (as shown in UnCodeX). It is not clear to me exactly how functions such as ProcessMove and PlayerMove should be properly used; also, logging the Location (`log(Location)) reveals that it remains stationary, although the player is definitely moving. This also happens with no tracker (i.e. WASD).

My base game class extends UTDeathMatch, my controller class extends UTPlayerController, and my pawn class extends GamePawn.
 

silverwizard

New Member
Mar 13, 2013
8
0
0
Problems solved (I think)

OK, I tested a few things and I think I got it working at last. Here's what I did:

It was suggested to me that ut* classes carry a lot of needless stuff with them (needless if you plan to deviate from the game type they were made for, that is). Thus, I changed my controller's superclass from UTPlayerController to SimplePC and I haven't been able to reproduce the camera issue ever since. However, I have not "solved" the issue, in the sense that I don't know what property or parameter caused the problem in the first place - I have merely evaded it. But it's a workaround nevertheless.

I have also implemented a "walking in place" locomotion method: the user takes a step or two in the desired direction and the pawn starts moving (more properly, accelerating). I did that on the C++/DLL side. Basically, for each dimension (XYZ), I subtract a value if the current value it larger than the desired threshold, and add the value if it's smaller than negative threshold. If it's in-between, I set it to 0. It may be possible that there are better ways to achieve the same result; I will try to find out.

Bottom line, I believe that the most fundamental issues have been solved or bypassed - but nevertheless addressed.

Thanks for your help!