Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Difficulty Simulating Servo Behavior with ArticulationBody

Discussion in 'Physics' started by joeyvdkaaij, Jun 14, 2023.

  1. joeyvdkaaij

    joeyvdkaaij

    Joined:
    May 11, 2020
    Posts:
    7
    Hello everyone,

    I am currently working on simulating a servo in Unity using the ArticulationBody component. My goal is to closely replicate the behavior of my real-life servo, which feels very stiff and can move 100 grams attached to a 10cm arm through 132 degrees in just 0.40 seconds. The specs says it can deliver a torque of 2.943 N/m

    Video of servo lifting 100 grams in slow motion (240 fps): https://drive.google.com/file/d/1q1ibT3oHX5GfF_bOwwU81VPMM1dI5TSG/view?usp=sharing

    However, I am facing an issue where no combination of stiffness and damping settings in the ArticulationBody.xDrive (while in Force Mode) seems to come close to my servo's behavior. My simulated drive takes over 2 seconds to perform the same motion, and during this time, there is a significant amount of speeding up and slowing down, which is not characteristic of my real servo.

    Screenshot 2023-06-14 113045.png

    I understand that the ArticulationBody likely employs a Proportional-Derivative (PD) controller internally. Since servos also typically have PD-like behavior, I expected to be able to tune the stiffness and damping parameters to get similar behavior.

    Here’s what I’ve tried so far:
    • I have experimented with various values for stiffness and damping (from small to very high)
    • I have tried different modes
    • I have tried different scales
    And here are my current settings:

    Screenshot 2023-06-14 113747.png


    I have a few questions:
    1. Is there something fundamental about the ArticulationBody's internal workings that could be causing this discrepancy?
    2. Are there other parameters besides stiffness and damping that I should be tuning to replicate the behavior of my servo?
    3. Does anyone have any recommendations for settings or techniques that could help achieve a more realistic simulation?
    Any insights or advice would be greatly appreciated!

    Thank you in advance.
     
  2. tjmaul

    tjmaul

    Joined:
    Aug 29, 2018
    Posts:
    464
    hey there,

    1. No, I don't think there's something strange going on.
    2. Yes, more below
    3. yes..

    I'm not sure what you're feeding into the drive target, but I assume that's the issue. If you change the drive target from 0deg to 60deg in an instant (also called 'jump function'), the response to this will be the curve you observed with an acceleration and a deceleration phase, using the max torque you provided.

    If you compare this to the real system, your 2.9 Nm servo (sorry for nerding about this, but N/m is incorrect :)) with a 0.1kg (roughly 1N of force) static load on a 0.1m arm will barely notice that there's anything to lift.

    Apart from the 2.9 Nm, the servo also has a maximum angular velocity, probably depending on the supply voltage. I think this is the important difference between the simulation and the real experiment.

    So what should you do?

    Create a Behaviour with a public AnimationCurve. Set the animation curve to go from 0 to 60 within 0.4 seconds. Feed this value into the target of the articulation drive and leave the targetVelocity to 0 for now. Now play with stiffness (try 10) and damping (try 1). If it overshoots, increase damping. For better controller behaviour, not only set the target, but also targetVelocity (60deg / 0.4s = 150).

    Let me know if that works better :)
     
  3. joeyvdkaaij

    joeyvdkaaij

    Joined:
    May 11, 2020
    Posts:
    7
    Thanks for your answer and your nerding out, I'm here to learn :)

    There is indeed a maximum angular velocity and at 6v it's 0.15 sec ( 60°).

    First some clarification, I was only talking about a 100-gram weight on a 10cm arm but I also tried 200 grams and 300 grams and measured the time it took for those weights to reach the desired target on the real servo. The 200 grams took only slightly longer (0.4sec) and the 300 grams took longer still (0.52sec). I would like to see that behaviour back in the simulation if possible.

    So I tried what you suggested. I made an animation curve going from 0 to 60 in .15 seconds. It indeed seems to work a lot better to avoid a jump function; but only as long as it can keep up. To get the closest to the real behaviour I had to put the stiffness to 300 and damping to 120 and also set the targetVelocity correctly. That left the force limit. When left on 2.9 Nm it would still take a long time for the servo to hit the target. Only when I increased the force limit by a lot (1e+10) would it start to get close to the desired behaviour. Setting it this high does make it so that there is no real effect of putting a heavier weight at the end of the arm. I could of course code that behaviour into the controller; if the weight is 300gram a different animation curve is used, etc.

    It feels like I'm now forcing the articulation body in one area that makes it lose other aspects of the physics simulation (responding to different weights differently). Am I naive in thinking that copying the values of the real servo's spec sheet to the articulation body will result in similar behaviour by itself?

    I'm trying to get a better feel for the Articulation Body physics engine and how to get close to bridging the Sim-to-Real gap in Unity. If you know of any documentation I would love to hear it.

    If you have any more suggestions you are more than welcome to share them.
     
  4. tjmaul

    tjmaul

    Joined:
    Aug 29, 2018
    Posts:
    464
    I think you’re almost there. I think the problem is that you have to enforce both a torque and angular velocity limit. They generally are independent from each other (in terms of systems dynamics), but in reality, the maximum torque is close to zero when you’re approaching the angular velocity limit.

    To model this, create another animation curve that starts out at 1 and stays 1 until it rapidly falls off to zero, close to the end. With this, you can model the characteristic torque curve. Now take the absolute value of the angular velocity and run that through the torque curve and use the result to set the torque limit of the drive. For easier iterations, I'd keep the animation curve normalized, so you'll obviously have to account for that.

    The animation curve I suggested in the previous post is not necessary any more.

    Concerning the other problem with stiffness and the very high force limit: Check the scale, 1 unity unit is equivalent to 1m. Make a simple test where you attach a 1kg mass 1 unit away from the pivot (horizontally). Set the torque to 9.81 which should exactly counteract gravity. Does that work?
     
  5. tjmaul

    tjmaul

    Joined:
    Aug 29, 2018
    Posts:
    464
    @joeyvdkaaij i noticed you have an editor window showing a plot in your screenshot. Can you graph variables with this? It it an asset on the store?
     
  6. joeyvdkaaij

    joeyvdkaaij

    Joined:
    May 11, 2020
    Posts:
    7
    Thanks for your reply, I'm going to look into what you said today.

    On your other post:

    Yes, it's to graph variables and can also save that graph to a csv file. It makes use of AnimationCurves
    I made it myself: https://drive.google.com/file/d/1iEEYkfZkP9D_RsrslQdRGWJl1xocst0o/view?usp=sharing

    When added to a project:
    It adds a window in Windows>Custom Plot Graph
    It also contains 2 Components, FollowYPlotter.cs and PlotGraph.cs

    When playing you can drag the component PlotGraph.cs into the Editor Window and it will show the values recorded so far.

    The FollowYPlotter can be looked at to make other custom scripts to track different variables; it's a very simple script.
     
    Last edited: Jun 20, 2023
    IAMBATMAN and tjmaul like this.
  7. joeyvdkaaij

    joeyvdkaaij

    Joined:
    May 11, 2020
    Posts:
    7
    I think there was something weird going on with scaling that I don't understand yet. I started a new project - did your suggestion of working against gravity. Worked my way towards my servo and now everything seems to work fine. It probably has to do with that I am using a 3d model for my servo that is imported at a certain scale, as now I'm just using Unity's cubes and it works a lot better.
     
    tjmaul likes this.
  8. tjmaul

    tjmaul

    Joined:
    Aug 29, 2018
    Posts:
    464
    Nice idea using the animation curves! :)

    Concerning the scale problems: I think you can avoid a lot of headaches by just always using scale = (1,1,1) for all physics related game objects. You can then add a child to the articulation bodies that just contain the visual model.

    But good to hear that everything works more like expected!
     
    joeyvdkaaij likes this.
  9. tjmaul

    tjmaul

    Joined:
    Aug 29, 2018
    Posts:
    464
    I tried out the plotter and I really like it! Super simple, great idea!
     
    joeyvdkaaij likes this.
  10. joeyvdkaaij

    joeyvdkaaij

    Joined:
    May 11, 2020
    Posts:
    7
    Glad you like it and thanks for helping me. :)

    There are a couple of things I would like to improve on it, some easier than others.
    It would be nice to just keep the PlotGraph component selected.
    It would be nice to have multiple variables being plotted on the same graph - but that's not possible with the AnimationCurve.

    One project at a time :)
     
    tjmaul likes this.