Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by qtoompuu · Dec 14, 2017 at 12:36 PM · rotationrotatelagarduinolaggy

transform.rotation = ... reacts slow

I'm trying to integrate Arduino and unity for fun, and my current project involves using a potentiometer(variable resistor) to rotate an object in unity. I do this by measuring the output voltage from the potentiometer and translating it into a rotation(the value comes out as a number between 0 and 1023). I've had no issues getting the bytes into unity with the system.IO.Ports stuff, nor have I had trouble translating it into a Euler angle, but when I try to use that angle to set the objects rotation, it is slow and laggy(jumps to the rotation after several seconds). initially I was using transform.Rotate(...), which worked significantly better, but I want the rotation to be set to a specific spot, not to be continually rotated. I'm not sure if there is a more efficient way of setting the rotation(or for that matter, if I'm coming at this from the complete wrong direction), and any help would be appreciated.

Here is the code I'm working with:

 using UnityEngine;
 using System.Collections;
 using System.IO.Ports;
 public class ArduinoInput : MonoBehaviour {

     public SerialPort p = new SerialPort("COM4", 9600);
     float speed;
     string temp;
     public float speedMod = 10;
     public float turnMod;
     Rigidbody rb;
     float rot;

     public GameObject obj;

     void Start () 
     {
         rb = transform.GetComponent<Rigidbody> ();
         if (!p.IsOpen) 
         {
             p.Open ();
         }
         p.ReadTimeout = 1;
     }
     void Update () {
         if (p.IsOpen)
         {
             try
             {
                 temp = p.ReadLine(); //grabs data
                 string[] data = temp.Split(','); // splits the string to separate 2 vars
                 float rotData = float.Parse(data[1]); // translates 1st var to float
                 float speedData = float.Parse(data[0]); // translates 2nd var to float
                 rot = ((rotData/10.23f) - 50); //changes value from between (0 - 1023) to ((-50) - 50)
                 speed = (speedData)/speedMod; //modifies speed
             }
             catch(System.Exception)
             {
                 throw;
             }
         }
     }
     void FixedUpdate()
     {
         obj.transform.localRotation = Quaternion.Euler(0, rot, 0); //sets local rotation
         rb.velocity = transform.forward * speed; //moves object forward
     }
 }
 
Comment
Add comment · Show 2
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image KittenSnipes · Dec 14, 2017 at 12:47 PM 1
Share

I’m not a hundred percent sure as I am currently researching this a bit as well but I think the fact you change the value of rot in update and then use it later on in FixedUpdate without multiplying it by Time.deltaTime could be a factor if it’s oddness. Because when you don’t multiply it by that it does it every frame rather than every second.

avatar image Bunny83 KittenSnipes · Dec 14, 2017 at 02:24 PM 0
Share

Sorry but this makes no sense. He sets an absolute rotation and an absolute velocity here. There is no continous change applied every frame. The whole movement is driven by the physics system. Time.deltaTime shouldn't be used anywhere in this code.

2 Replies

· Add your reply
  • Sort: 
avatar image
3
Best Answer

Answer by Bunny83 · Dec 14, 2017 at 02:22 PM

I see several issues here. First of all you should never do lowlevel hardware communication on the main thread. ReadLine is a blocking call which waits until data arrives (or the timeout is hit if one is set).


Next thing is you have set your timeout to "1ms". So it will most likely run into the timeout all the time.


Low-level hardware communication should always be done on a seperate thread. Note that i said "thread", not coroutine. A coroutine won't help at all. Of course you have to synchronise your threads in order to transfer information from one thread to another.


You can decide if you want to do the parsing inside the reading-thread or in main thread. In your case it would be the easiest solution to parse it in the main thread as you only need to transfer single string between your threads. Of course the reading happens asynchronously and from your observation most likely much less often than your visual framerate. However you have to keep in mind that in theory if your framerate drops dramatically for some reason the reading thread might read two or more lines per update. Though since the information you're processing are just state information you could simply "drop"older information and just keep the newest one.


Here's an example:


 public float speedMod = 10;
 public GameObject obj;
 
 Thread readingThread;
 bool threadRunning = true;
 
 bool newData = false;
 string threadData;
 
 Rigidbody rb;
 float speed;
 float rot;
 
 void Start()
 {
     rb = transform.GetComponent<Rigidbody>();
 }
 
 void OnEnable()
 {
     readingThread = new Thread(ReadingThreadFunc);
     readingThread.Start();
 }
 
 void OnDisable()
 {
     threadRunning = false; // signal the thread to terminate itself
     if (!readingThread.Join(400)) // wait for the thread to finish
     { // if it doesn't finish in the given time, force terminate the thread
         readingThread.Abort();
     }
     readingThread = null;
 }
 
 void Update ()
 {
     if (newData)
     {
         lock(readingThread)
         {
             newData = false;
             string[] data = threadData.Split(',');
             float rotData = float.Parse(data[1]);
             float speedData = float.Parse(data[0]);
             rot = ((rotData / 10.23f) - 50);
             speed = (speedData) / speedMod;
         }
         obj.transform.localRotation = Quaternion.Euler(0, rot, 0);
         rb.velocity = transform.forward * speed;
     }
 }
 
 void ReadingThreadFunc()
 {
     SerialPort p = new SerialPort("COM4", 9600);
     p.Open();
     p.ReadTimeout = 200; // wait 0.2 sec max
     while (threadRunning)
     {
         try
         {
             string data = p.ReadLine();
             lock (readingThread)
             {
                 threadData = data;
                 newData = true;
             }
         }
         catch (System.TimeoutException)
         {}
     }
     p.Close();
 }


Keep in mind that the rate in which your arduino sends out information might be too slow. By default a serial port uses a baud rate of 9600 bits/sec. It takes about9 to 10 bits to transfer one byte. Since you send out strings they have quite a bit of overhead as your string could be 4 bytes + comma + 4bytes + newline character--> around 10 bytes per line. That's just the limit of the serial port which gives you at max a rate of about 100 updates / lines per sec.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image qtoompuu · Dec 14, 2017 at 03:42 PM 0
Share

Thank you very much, I've been trying to get this to work for like 3 days now and this works perfectly.

avatar image
0

Answer by KittenSnipes · Dec 14, 2017 at 12:54 PM

@qtoompuu This code works for me but tell me how it works for you. Here it is:

 float rotation=rotationspeed*Time.deltaTime;
  if (rot > rotation)
  {
      rot -= rotation;
  }
  else
  {
      rotation = rot;
      rot = 0;
  }
  transform.Rotate(0, 0, rotation);



I put this in my update method as it performs the rotation once per my instructions. Maybe you can fit it to your needs.

Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image qtoompuu · Dec 14, 2017 at 01:23 PM 0
Share

the issue is that I am not rotating by a certain amount each x amount of time, I am rotating to a specific point deter$$anonymous$$ed by a number between -50 and 50(imagine you have a knob that you can turn either way and you want the game object to mimic that knob) the .Rotate() method causes the object to keep rotating past the mark.

avatar image KittenSnipes · Dec 14, 2017 at 01:37 PM 1
Share

Ok I understand a bit more. Can that not be solved by a simple if statement then. If the object goes past that point then set a Boolean like:

 if (rot >= currentRotation) {
     allowedToRotate = false;
 }
 
 if (allowedToRotate == true) {
     Rotate that thing.
 }
 
 else {
     return;
 }
 
avatar image qtoompuu KittenSnipes · Dec 14, 2017 at 02:09 PM 0
Share

I appreciate the help, but after some careful debugging, i've realized that my issue has to due with too many of my "try catches"(lines 28 - 40) failing and thus not running the necessary code. I need to figure out what is causing this error:

TimeoutException: The operation has timed-out, System.IO.Ports.WinSerialStream.Read(System.Byte[] buffer, Int32 offset, Int32count)

avatar image KittenSnipes · Dec 14, 2017 at 01:38 PM 0
Share

Oops that first statement I meant to switch that around because rot is a constant which is the max currentRotation can reach. Sorry about that.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

103 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

How to write : Rotate and Reset 0 Answers

Trouble rotating a prefab while it's moving up,Rotating an object with an animation while it moves up 0 Answers

After rotate with joystick, rotate resetting,joystick rotate correction 0 Answers

Practical solutions for lag reduction? 1 Answer

Smoothly rotating an object to a specific rotation. 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges