问:
How to: implementation problem with Position control on a 3 Wheels robot (2 motorized) with velocity profile of trapezoid
I'm trying to apply position control in a wheeled robot, controlled by an arduino mega.
The robot has two wheels powered by two dc motors (1 motor for each wheel) and one castor wheel.
In order to implement the position control, I'm using classic PID control applied to each wheel seperately.
My goal is to achieve some accuracy of moving and of course that the robot is moving in straight lines when told so (this means the wheels
shall spin with the same speed, for the same distance and at the same time - otherwise the robot, would of course, turn).
Following, I have gathered how I try to do this, some issues I face and some questions that I would like to ask.

The way I'm trying to achieve these robot functionalities is the following:

the error feeded as input to the control unit is estimated by the position generated from a trajectory profile that i wish the robot to follow,
minus the actual position the robot has actually travelled.

afterwards, the output of the control is fed, in the form of pwm value, from the arduino to the motor controller,
which i guess is (something similar to) an h-bridge.

about the desired position: as mentioned i have made a trajectory generator function.
This trajectory is actually the integral of a trapezoid velocity profile.
The desired position (des_pos) is actually a function of the pwm value, that i send from the arduino to the motor controller board.
For example, for the accelerating phase, the position is calculated from the formula: 0.5(vmax/tacc)t^2 , where tacc is the time of acceleration.
and vmax is the pwm value.

about the actual position: the encoder provides feedback of the position of the motor. This information is translated into actual (centi)meters
that the robot has travelled (using the diameter of the wheel and the total number of ticks per revolution generated by the encoder)

Issues:

the des_pos as said is a function of pwm. That means that its units are not meters. Which in principle is wrong.
To make things worst, the error is computed between dissimilar quantities..
My idea was that I could either try and make some tests and map different values of pwm to the corresponding velocity of the robot.
Then, by interpolation I could transform pwm values to velocity.
Another option is to "absorb" this error inside the values of the gains. In other words, that during gain tuning I would be able to make this issue
"hide".

the robot in order to move in the ground, where is placed, requires a threshold pwm value. Otherwise, if less pwm value than the threshold is
provided then the robot can not start moving. This is perfectly normal, since friction, dynamics of the motor etc are opposing the movement.
When applying PID though, the output of the control has to be mapped to produce values of "pwm adjustment" with respect to this minimum pwm value.

Questions:

What is the proper way to implement position control here?
What is the "proper" approach in this kind of robots?
My approach has many issues (see above) and it seems like gain tuning is tough.

How can I handle the issues I mentioned or what is the best practise?

The response I get from testing the aforementioned setup is that the motors are doing an interrupted movement.
In other words, it seems like the robot alternates between 0 and minimum pwm value, instead of progressively increasing speed.
Theoritically, is this a result of bad pid tuning? Or is it because of the minimum pwm value required to ignite movement in the robot?

Something different, but more general let's say, regarding control theory.
My understanding is that velocity and position control are actually different sides of the same coin.
If I am not mistaken, the main difference has to do with the feature (velocity or position) which we pay attention in
[for example in position control, you can manage the same result with velocity control - meaning you reach the same distance -
but you have overshooting and all aspects of control focused on position whereas in velocity control you have focused on velocity], as mentioned also
here.
Also, what is the case when you need to take into account the dynamics of the motor? Or in other words, when is it necessary to insert the dynamics of
the motor inside the control scheme?

Thanks in advance and sorry for the long post.
I m looking forward to any help!

答:
This is a long post that's a bit all over the place, but as concisely as I can:

You say,

Issues: the des_pos as said is a function of pwm. That means that its units are not meters

but you also say,

about the desired position: as mentioned i have made a trajectory generator function. This trajectory is actually the integral of a trapezoid velocity profile.

This doesn't make sense to me - if you have a desired position, then that should determine the velocity trapezoid. If you have a velocity trapezoid driving the desired position, then you don't really have a desired position, you have a desired velocity and whatever position you get from that is incidental.

Regardless, you go on to state:

the position is calculated from the formula: 0.5(vmax/tacc)t^2 , where tacc is the time of acceleration. and vmax is the pwm value

If you want engineering units, you should have vmax as a real speed, which means you need to calculate motor top speed, gearbox ratio, wheel diameter, etc.

The rest of your questions all seem to revolve around issues with PWM control, so I'll put it like this: Your vehicle controller (as described) should generate a trapezoidal speed profile, in some kind of engineering unity like meters per second.

You can use a PID controller at each wheel that accepts the trapezoidal speed control as an input. You can calculate wheel speed with wheel radius, gearbox ratio, and motor speed. The wheel speed error is reference (input) minus feedback (calculated). The wheel speed error is what you pass to the PID controller; P term acts directly on that error, take the integral of the error for the I term, take the derivative of the error for the D term. Take those outputs, (kPerror) + (kIerror_integral) + (kD*error_derivative), and send that out as the PWM signal. Any scaling that needs to happen for PWM will be taken into account when you do your tuning.

I would also highly recommend using a feed-forward term in your controller. This will take a bit of study on your part, but pay attention while you're doing your tuning and you should be able to plot PWM signal against steady-state wheel speed. The feed-forward "controller" will use this curve to send the estimated PWM signal to the motor directly, and the PID controller then only has to act to make up for dynamics and disturbances. I guarantee you'll get significantly better performance with feed-forward control than with pure PID, because PID can only ever act on an error - PID controllers won't send anything until you're failing to match the reference input.


问:
Batteries lose functionality
In Webots: I want my little robot drive to a fully charged charger (green pointlight and cylinder) and drain its energy. While the battery loses energy it should change its color.

It works as long as I stay in the Webots Tour setup of the battery device. I can make changes of the bot and the arena. Everything works. But as soon as I introduce a second robot or just close Webots and open it again the light and shape stays green when my robot comes into contact. This happened every time over multiple different worlds. Every time I introduce the battery to a new robot Webots crashes and afterwards the charger is not working anymore. Or I close the program in the battery setup and after reopening it does not change the colors. So I don't know what my mistake is.

I use R2023a because I use Python. My Robot has 50/100/30 and the Charger nodes have 100/100/3. When I introduce a new robot or battery and change the second number it crashes. I even deinstalled and reinstalled Webots. All the same.

I safe in the red initial state and when I run than It changes to the green initial state. And not because it charged fully. Because the initial values in the nodes changes that when I reset the simulation the initial values are green again.

My output

The Charger loses its energy but does not change the color.

World file

Controller.py

答:
The "gradual" appearance change of the Charger node that is used in the default "battery.wbt" world and in your world uses the initial color value of the Charger first child node to determine the color change when loosing energy.

Here is the documentation of the "gradual" field from the Charger node documentation:

gradual: defines the behavior of the indicator. If set to TRUE, the indicator displays a progressive transition between its original color and the emissiveColor specified in the Charger node, corresponding to the present level of charge.

In the default "battery.wbt" world file, the emissiveColor of the Charger.Trasform.Shape.appearance and the color of the Charger.Trasform.PointLight are set to red (1 0 0). This is the important settings that makes the Charger color change when charging a battery and loosing energy.

It seems that you modified and saved the default "battery.wbt" after running the simulation, so these initial settings were lost.

Here is the Charger structure you should use:

```<code>Charger {
  translation -0.43 0.43 0
  rotation 0 0 1 -1.570795
  children [
    Transform {
      translation 0 0 0.15
      children [
        Shape {
          appearance PBRAppearance {
            baseColor 0 1 0
            transparency 0.7
            roughness 0.2189099510000001
            metalness 0
            emissiveColor 1 0 0   # this field should be set to a different color than Charger.emissiveColor
          }
          geometry DEF CHARGER_GEOM Cylinder {
            height 0.3
            radius 0.2
            subdivision 24
          }
        }
        PointLight {
          attenuation 0 0 12
          color 1 0 0  # this field should be set to a different color than Charger.emissiveColor
          intensity 0.53
        }
      ]
    }
  ]
  name "charger0"
  battery [
    100, 100, 4
  ]
  radius 0.2
}
</code>```

I could also reproduce the crash when adding battery values while running the simulation. I'm now inspecting and fixing it.

Disclaimer: I am a Webots developer working at Cyberbotics.

ContentLicense: CC BY-SA 4.0

Title: Batteries lose functionality

Body:
The "gradual" appearance change of the Charger node that is used in the default "battery.wbt" world and in your world uses the initial color value of the Charger first child node to determine the color change when loosing energy.

Here is the documentation of the "gradual" field from the Charger node documentation:

gradual: defines the behavior of the indicator. If set to TRUE, the indicator displays a progressive transition between its original color and the emissiveColor specified in the Charger node, corresponding to the present level of charge.

In the default "battery.wbt" world file, the emissiveColor of the Charger.Trasform.Shape.appearance and the color of the Charger.Trasform.PointLight are set to red (1 0 0). This is the important settings that makes the Charger color change when charging a battery and loosing energy.

It seems that you modified and saved the default "battery.wbt" after running the simulation, so these initial settings were lost.

Here is the Charger structure you should use:

Charger {
  translation -0.43 0.43 0
  rotation 0 0 1 -1.570795
  children [
    Transform {
      translation 0 0 0.15
      children [
        Shape {
          appearance PBRAppearance {
            baseColor 0 1 0
            transparency 0.7
            roughness 0.2189099510000001
            metalness 0
            emissiveColor 1 0 0   # this field should be set to a different color than Charger.emissiveColor
          }
          geometry DEF CHARGER_GEOM Cylinder {
            height 0.3
            radius 0.2
            subdivision 24
          }
        }
        PointLight {
          attenuation 0 0 12
          color 1 0 0  # this field should be set to a different color than Charger.emissiveColor
          intensity 0.53
        }
      ]
    }
  ]
  name "charger0"
  battery [
    100, 100, 4
  ]
  radius 0.2
}

I could also reproduce the crash when adding battery values while running the simulation. I'm now inspecting and fixing it.

Disclaimer: I am a Webots developer working at Cyberbotics.


问:
Robotic part to dispense candy
I'm a complete newbie trying to build a simple robot that dispenses candy (M&M, skittles, etc).  However, since I'm not familiar with the field, I'm having a hard time googling because I don't know the correct terms to search for.  I'm looking for a piece to build a robotic 'trap door' of sorts that will open for a specified amount of time to release candy.  What parts can I use and what is are called?  I've tried robotic lever, robotic door, etc with no luck.</p>

答:
There are two good search terms that come to mind.  The first one is a "candy machine mechansim", or "dispenser mechanism" (e.g. http://www.woodworkingformeremortals.com/2012/10/make-candy-dispenser.html).  There are several models of off-the-shelf pet food dispensers and cereal dispensers that use this method.

The second term would be a screw conveyor (a.k.a. "auger dispenser"/"food auger"/"grain auger"), which describes a more continuous-flow version of what you are describing.

This type of dispenser controls the volume that is delivered by rotating the auger by a fixed amount, not by dumping a fixed-size container.

Beyond those, there are some homemade concepts that use some variation on the idea, like this one:

ContentLicense: CC BY-SA 3.0

Title: Robotic part to dispense candy


问:
How could you have controllers communicate with each other?
I have been attempting to have two controllers be able to access information from each other in a way that is similar to object-oriented programming in UNITY, however, I have constantly had problems getting it to work. I always get a similar error of:

```<code>Exo_controller.cpp: In function 'int main(int, char**)':
Exo_controller.cpp:22:5: error: expected primary-expression before 'public'
   22 |     public static double dist;
      |     ^~~~~~
Exo_controller.cpp:23:5: error: 'dist' was not declared in this scope
   23 |     dist = distance[1] -> getValue();
      |     ^~~~
Error 1
</code>```

Could someone explain if it is even possible to have something like object-oriented programming and if not is there anyther way I could simulate this is Webots?

答:
In Webots it is not possible to access device values from another robot controller and each controller is running in its own process.
See also this question: read-device-value-from-another-robot-controller-in-webots.

So if in your controller program you are trying to get the devices of another robot that it is not the one associated with the current controller instance it won't work.

However, you have some other options to make two Webots controllers communicate with each other:

use the Emitter/Receiver mechanism to send data from one robot/controller the other one

for single values you could also use the Robot.data field to store the data to share and read it in the other controller program using the Supervisor API

Not specific to Webots, you can also use any standard inter-process communication mechanism (files, sockets, shared memory, etc.).

Disclaimer: I am a Webots developer working at Cyberbotics.


问:
Render H.264 Video of Robot
How do I render h264 video data in Foxglove Studio?. My data is recorded as a separate file alongside an MCAP file. Ideally I'd like to be able to open my MCAP file and then attach my video and have them time synced so they're both controlled by the scrubber.</p>

答:
To answer my own comment above integrated h264 in foxglove is an open issue https://github.com/foxglove/mcap/issues/427 (and more discussion https://github.com/foxglove/community/issues/87) - so it looks to be on their road map but not yet supported.

I'm not familiar with foxglove but you could possibly write an external application (or your own plugin?) that receives a clock/timestamp output from foxglove when you move the scrubber or play (do they support that?) and then indexes into your video, which you could have pre-processed for the location of frames (especially index frames)- and you'd need to have timestamps that can match up with what foxglove is using embedded in your video or in another file alongside it.  It would publish out decoded images in a format foxglove can show live.

PyAV (https://github.com/PyAV-Org/PyAV and python3-av in Ubuntu) could be an easy way to get a basic external version working (but it doesn't support nvidia gpu decoding- though I'm not clear on that).

Title: Render H.264 Video of Robot


问:
Rocker bogie suspension stability
From the designs usually shown of rocker bogie systems, the whole weight of platform seems to be supported by only one rod, be it differential bar or gear. Isn't this a bit unstable system because if we have arms of rover at one end we will have a high torque about that rod?

Is my understanding such rocker bogie systems correct? If so, are there any solutions to this problem which don't sacrificing the functionality of rover?

To clarify, I want to know how rovers like curiosity are designed so as to balance such a heavy platform with a differential bar mechanism. I am trying to make a small rocker bogie myself and I want to avoid this anticipated problem.

答:
This should only be a problem if you anticipate that the weight would be shifting within the robot.

You're correct that the weight of the rover will be borne by the single contact points on each side, so any imbalance about that rod will become stress on the differential mechanism.  However, in the initial design of the vehicle you should be placing the contact points of the suspension system in line with the vehicle body's center of mass.  You could also add weight to certain parts of the vehicle to achieve this balance.

In cases where you really do want to change the weight distribution in the vehicle (e.g. picking up an object with a gripper arm), you have 2 choices: either make the suspension strong enough to handle the torque you'll be putting on it, or introduce a system that can adjust the balancing point -- a movable ballast.

Title: Rocker bogie suspension stability


问:
Questions about sensor fusion with Lidar - Extended Kalman Filter
I am attempting to teach myself sensor fusion as I suspect I'll need to do this down the road with lidar and some other sensors. In all my research so far it sounds like a version of the extended kalman-filter is the best way to do this.

I believe I have a good intuition for how the EKF works but I am stuck on a few things. First let me describe my understanding of the process in general.

Starting at time $k_1$, use a motion model to predict the pose of the vehicle at time $k$

Use a measurement model to describe where we can expect the measurement to occur

Once a measurement is observed we use step 3 to decide how much of the measurement should be used to update the predicted state

Update the predicted state with information from step 3.

Repeat forever

What I am really stuck on is how do we measure the pose of the robot with a sensor like lidar or radar? Several examples I have found show the raw lidar data as if it were the measured pose of the robot, instead of the distance from a object. They use this raw data in step 4 above but this doesn't make sense to me. How can we get a better prediction of the state using the raw lidar data if we can't actually measure the state of the robot using the lidar?

答: One common way of using LiDAR to estimate the pose of a robot is by scan-matching against a previously-created occupancy grid (map), then using the match scores in a pose estimation system like AMCL. Then, that pose estimate is often fed into an EKF, along with other state measurements (wheel odometry, IMU), to "fuse" them all together to form a filtered pose estimate. If you Google terms like "AMCL" and "scan-matcher", you'll find a wealth of literature and tutorials about using LiDAR for this purpose.</p>


问:
ros-gz integration
I am trying to connect ros and gazebo garden using a bridge.
I am working on ubuntu 22.04. I have ros2 humble and gazebo garden installed. I am following the readme of this repo https://github.com/gazebosim/ros_gz/tree/39cdcf88e762589595222d74e41f22b1d876aef1/ros_gz_bridge

I wrote a YAML file as suggested and it looks like this:

```<code> ros_topic_name: "/lidar2"
 gz_topic_name: "/lidar2"
 ros_type_name: "sensor_msgs/msg/LaserScan"
 gz_type_name: "gz.msgs.LaserScan"
 direction: GZ_TO_ROS
</code>```

then I ran used this line as suggested

```<code>ros2 run ros_gz_bridge parameter_bridge --ros-args -p config_file:=$WORKSPACE/ros_gz/ros_gz_bridge/test/config/full.yaml
</code>```

However, I keep getting this error

```<code>[WARN] [1671207408.574261249] [ros_gz_bridge]: Failed to create a bridge for topic [/lidar2] with ROS2 type [/lidar2] to topic [sensor_msgs/msg/LaserScan] with Gazebo Transport type [gz.msgs.LaserScan]
</code>```

Any idea what's the problem and how to solve it?

答:
To use roz_gz with Humble & Garden you will need to build the package from source. https://github.com/gazebosim/ros_gz

The Humble binaries (ros-humble-ros-gz) look for Fortress message types.

Title: ros-gz integration


问:
How to handle motor stall zones in differential drive point-forward go to goal algorithm?
I am implementing the Go To Goal algorithm for a differential drive robot as described here and in this video.  The issue I have is that there is a large dead zone in pwm values where the motors are stalled.  I have calibration data for each motor that measures the stall pwm and the minimum speed that the motor can turn just above stall.  I also have calibration data for the maximum speed.  I'm using optical encoders to measure the rotational speed of the wheels.  So my issue is that the point-forward algorithm controls both linear velocity and angular velocity and it is calculating wheel speeds that cannot be achieved by the robot; they are in the stall zone.  How does one handle that issue?  It seems like just upping velocities by the minimum velocity does not work because then the turning angle is too shallow to reach the goal.</p>

答:
I know it is an old post, but you never know.
Anyway, did you find any solution to overcome this issue?

My idea is that maybe a mapping can be done between the values i get and values that overcome the threshold value of PWM that moves the robot.
Something like a linear interpolation, maybe.
Otherwise, my guess is that pid gains of the control maybe could be adjusted in such way that they produce pwm correction which again is translated to PWM values that make the robot move.

Hope it helps.

In any case, please share if (and how) you managed to overcome this problem in a better way.

Thanks in advance


问:
Where does Gazebo set the GAZEBO_MODEL_PATH environment variable?
I'm starting out with Gazebo (1.5) at the moment and am following a tutorial off the internet. In order to get Gazebo to find the model, the author advocates manually exporting the GAZEBO_MODEL_PATH environment variable via

```<code>export GAZEBO_MODEL_PATH=[...]/models:$GAZEBO_MODEL_PATH
</code>```

But that will only work for the current terminal. So I wanted to change the environment variable permanently.

The Gazebo User Guide claims that GAZEBO_MODEL_PATH, along with all the other environment variables, is set by /usr/share/gazebo-1.5/setup.sh but my (virgin) Gazebo install doesn't list it:

```<code>export GAZEBO_MASTER_URI=http://localhost:11345
export GAZEBO_MODEL_DATABASE_URI=http://gazebosim.org/models
export GAZEBO_RESOURCE_PATH=/usr/share/gazebo-1.5:/usr/share/gazebo_models
export GAZEBO_PLUGIN_PATH=/usr/lib/gazebo-1.5/plugins
export LD_LIBRARY_PATH=/usr/lib/gazebo-1.5/plugins:${LD_LIBRARY_PATH}
export OGRE_RESOURCE_PATH=/usr/lib/i386-linux-gnu/OGRE-1.7.4

# This line is needed while we're relying on ROS's urdfdom library
export LD_LIBRARY_PATH=/opt/ros/fuerte/lib:${LD_LIBRARY_PATH}
</code>```

But when I start Gazebo, GAZEBO_MODEL_PATH is already set to $HOME/.gazebo/models, so it must be set somewhere. I guess I could probably simply add GAZEBO_MODEL_PATH to the setup.sh script, but since it is set somewhere, I'd still like to know where and whether it is better practice to set it in there.

答: In my case, just setting Gazebo path did not solved the issue. Running roscore, in  a separate terminal, solved my problem.


问:
Rotate sensor frame to body frame
I'm working with a lsm303agr from ST. Here is the frame attached to the chip

Here is the body frame

So I have some doubts about the rotations, before to fuse data coming from my lsm I'd like to rotate lsm axis to body frame. So if I understand well if my sensor is flat on the body (sensor z axis points up) and pin 1 of sensor towards the front of the body.
I have to rotate axis like this

rotate x and y axis sensor to -90° or 270°

rotate z sensor to 180°

Is it right ?

答:
Yes and no.
If you look carefully the coordinate system in the first picture does not match with the coordinate system in the aircraft picture. Why?
Because the X axis in the first picture is positioned were the Y axis should be!!! And not because of the rotation!!! In a conventional coordinate system, X and Y are swapped in the first picture. So you should rename them in your code. So the picture with the aircraft is the "right" one.
Furthermore, the order of rotation matters.

Given that you swap now X and Y in the first picture, then:

Rotate the coordinate system about +180° around the Y axis (X in the picture).

Rotate the coordinate system about +180° around the Z axis

Now they should match.
Use your right hand to visualize the rotations.

Title: Rotate sensor frame to body frame


问:
Why the robot is not at the zero configuration
As part of my testing, I was using Kuka's arm to test some kinematic controllers. In the picture below, when the arm is spawned in Gazebo, the positions of the joints are zero (i.e. obtained from /joint_states topic). However, this is not the zero configuration (i.e. all joint angles are zero) as per the Norwegian University Robotics course. The arm should be stretched upward.

A posture at zero configuration is expected to be as follows:

If this is a wise thing to do, how can I fix this issue with the URDF? I'm turning off gravity so the robot shouldn't collapse.

Gazebo 9, Melodic ROS, Ubuntu 18.04. The launch file yields the following

```<code>SUMMARY
========

PARAMETERS
 * /arm_1/gripper_controller/gains/gripper_finger_joint_l/d: 1.0
 * /arm_1/gripper_controller/gains/gripper_finger_joint_l/p: 1000.0
 * /arm_1/gripper_controller/gains/gripper_finger_joint_r/d: 1.0
 * /arm_1/gripper_controller/gains/gripper_finger_joint_r/p: 1000.0
 * /arm_1/gripper_controller/joints: ['gripper_finger_...
 * /arm_1/gripper_controller/type: effort_controller...
 * /arm_1/joint_1_velocity/joint: arm_joint_1
 * /arm_1/joint_1_velocity/pid/antiwindup: True
 * /arm_1/joint_1_velocity/pid/d: 0.0
 * /arm_1/joint_1_velocity/pid/i: 100.0
 * /arm_1/joint_1_velocity/pid/i_clamp_max: 100.0
 * /arm_1/joint_1_velocity/pid/i_clamp_min: -100.0
 * /arm_1/joint_1_velocity/pid/p: 200.0
 * /arm_1/joint_1_velocity/type: effort_controller...
 * /arm_1/joint_2_velocity/joint: arm_joint_2
 * /arm_1/joint_2_velocity/pid/antiwindup: True
 * /arm_1/joint_2_velocity/pid/d: 0.0
 * /arm_1/joint_2_velocity/pid/i: 100.0
 * /arm_1/joint_2_velocity/pid/i_clamp_max: 100.0
 * /arm_1/joint_2_velocity/pid/i_clamp_min: -100.0
 * /arm_1/joint_2_velocity/pid/p: 100.0
 * /arm_1/joint_2_velocity/type: effort_controller...
 * /arm_1/joint_3_velocity/joint: arm_joint_3
 * /arm_1/joint_3_velocity/pid/antiwindup: True
 * /arm_1/joint_3_velocity/pid/d: 0.0
 * /arm_1/joint_3_velocity/pid/i: 100.0
 * /arm_1/joint_3_velocity/pid/i_clamp_max: 1000.0
 * /arm_1/joint_3_velocity/pid/i_clamp_min: -1000.0
 * /arm_1/joint_3_velocity/pid/p: 100.0
 * /arm_1/joint_3_velocity/type: effort_controller...
 * /arm_1/joint_4_velocity/joint: arm_joint_4
 * /arm_1/joint_4_velocity/pid/antiwindup: True
 * /arm_1/joint_4_velocity/pid/d: 0.0
 * /arm_1/joint_4_velocity/pid/i: 100.0
 * /arm_1/joint_4_velocity/pid/i_clamp_max: 1000.0
 * /arm_1/joint_4_velocity/pid/i_clamp_min: -1000.0
 * /arm_1/joint_4_velocity/pid/p: 100.0
 * /arm_1/joint_4_velocity/type: effort_controller...
 * /arm_1/joint_5_velocity/joint: arm_joint_5
 * /arm_1/joint_5_velocity/pid/antiwindup: True
 * /arm_1/joint_5_velocity/pid/d: 0.0
 * /arm_1/joint_5_velocity/pid/i: 100.0
 * /arm_1/joint_5_velocity/pid/i_clamp_max: 100.0
 * /arm_1/joint_5_velocity/pid/i_clamp_min: -100.0
 * /arm_1/joint_5_velocity/pid/p: 500.0
 * /arm_1/joint_5_velocity/type: effort_controller...
 * /gazebo/enable_ros_network: True
 * /joint_state_controller/publish_rate: 100
 * /joint_state_controller/type: joint_state_contr...
 * /robot_description: <?xml version="1....
 * /robot_state_publisher/publish_frequency: 30.0
 * /rosdistro: melodic
 * /rosversion: 1.14.13
 * /use_sim_time: True

NODES
  /
    arm_1_gripper_controller_spawner (controller_manager/spawner)
    arm_1_joint_controller_spawner (controller_manager/spawner)
    arm_1_joint_joint_vel_convertor (youbot_gazebo_control/arm_joint_vel_convertor)
    gazebo (gazebo_ros/gzserver)
    gazebo_gui (gazebo_ros/gzclient)
    joint_state_controller_spawner (controller_manager/spawner)
    robot_state_publisher (robot_state_publisher/robot_state_publisher)
    spawn_robot (gazebo_ros/spawn_model)

auto-starting new master
process[master]: started with pid [10608]
ROS_MASTER_URI=http://localhost:11311

setting /run_id to a7050ac0-8753-11ed-b539-782b4602bfac
process[rosout-1]: started with pid [10620]
started core service [/rosout]
process[gazebo-2]: started with pid [10627]
process[gazebo_gui-3]: started with pid [10632]
process[spawn_robot-4]: started with pid [10637]
process[joint_state_controller_spawner-5]: started with pid [10638]
process[arm_1_joint_controller_spawner-6]: started with pid [10639]
process[arm_1_joint_joint_vel_convertor-7]: started with pid [10640]
process[arm_1_gripper_controller_spawner-8]: started with pid [10641]
process[robot_state_publisher-9]: started with pid [10646]
[INFO] [1672302888.537418, 0.000000]: Controller Spawner: Waiting for service controller_manager/load_controller
[ INFO] [1672302888.562724669]: Finished loading Gazebo ROS API Plugin.
[ INFO] [1672302888.563895131]: waitForService: Service [/gazebo/set_physics_properties] has not been advertised, waiting...
[INFO] [1672302888.591070, 0.000000]: Controller Spawner: Waiting for service controller_manager/load_controller
[INFO] [1672302888.594987, 0.000000]: Controller Spawner: Waiting for service controller_manager/load_controller
[ INFO] [1672302888.605154844]: Finished loading Gazebo ROS API Plugin.
[ INFO] [1672302888.606237426]: waitForService: Service [/gazebo_gui/set_physics_properties] has not been advertised, waiting...
[ INFO] [1672302888.871914467]: waitForService: Service [/gazebo/set_physics_properties] is now available.
[ INFO] [1672302888.886935459]: Physics dynamic reconfigure ready.
[INFO] [1672302888.926367, 0.000000]: Loading model XML from ros parameter robot_description
[INFO] [1672302888.933339, 0.000000]: Waiting for service /gazebo/spawn_urdf_model
[INFO] [1672302888.936714, 0.000000]: Calling service /gazebo/spawn_urdf_model
[INFO] [1672302889.096456, 0.000000]: Spawn status: SpawnModel: Successfully spawned entity
[ INFO] [1672302889.172336448]: Loading gazebo_ros_control plugin
[ INFO] [1672302889.172445700]: Starting gazebo_ros_control plugin in namespace: /
[ INFO] [1672302889.173204807]: gazebo_ros_control plugin is waiting for model URDF in parameter [robot_description] on the ROS param server.
[spawn_robot-4] process has finished cleanly
log file: /home/bandar/.ros/log/a7050ac0-8753-11ed-b539-782b4602bfac/spawn_robot-4*.log
[ INFO] [1672302889.290428615]: Loaded gazebo_ros_control.
[INFO] [1672302889.442121, 0.000000]: Controller Spawner: Waiting for service controller_manager/switch_controller
[INFO] [1672302889.444259, 0.000000]: Controller Spawner: Waiting for service controller_manager/unload_controller
[INFO] [1672302889.446195, 0.000000]: Loading controller: arm_1/joint_1_velocity
[INFO] [1672302889.471425, 0.000000]: Loading controller: arm_1/joint_2_velocity
[INFO] [1672302889.493585, 0.000000]: Loading controller: arm_1/joint_3_velocity
[INFO] [1672302889.496364, 0.000000]: Controller Spawner: Waiting for service controller_manager/switch_controller
[INFO] [1672302889.498697, 0.000000]: Controller Spawner: Waiting for service controller_manager/unload_controller
[INFO] [1672302889.499587, 0.000000]: Controller Spawner: Waiting for service controller_manager/switch_controller
[INFO] [1672302889.502455, 0.000000]: Loading controller: joint_state_controller
[INFO] [1672302889.503163, 0.000000]: Controller Spawner: Waiting for service controller_manager/unload_controller
[INFO] [1672302889.506900, 0.000000]: Loading controller: arm_1/gripper_controller
[INFO] [1672302889.517154, 0.000000]: Loading controller: arm_1/joint_4_velocity
[INFO] [1672302889.520421, 0.000000]: Controller Spawner: Loaded controllers: joint_state_controller
[INFO] [1672302889.571038, 0.000000]: Controller Spawner: Loaded controllers: arm_1/gripper_controller
[INFO] [1672302889.586059, 0.000000]: Loading controller: arm_1/joint_5_velocity
</code>```

答:
Can you share your the Gazebo trace. You can use --verbose to visualize all the errors, warnings and debug traces. If you are using ROS probably you can add to the launch file verbose:=true.

My guess is that the Gazebo ROS controller is not running. Can you also specify the Gazebo and ROS versions.

Thank you


问:
What is the definition of the contents of PointCloud2?
What does the contents of PointCloud2 means in ROS?

fields.offset?

fields.datatype?

fields.count?

point_step?

row_step?

Its documentation is poor

Here is a published PointCloud2 message by Velodyne LiDAR:

```<code>header:
  seq: 1071
  stamp:
    secs: 1521699326
    nsecs: 676390000
  frame_id: "velodyne"
height: 1
width: 66811
fields:
  -
    name: "x"
    offset: 0
    datatype: 7
    count: 1
  -
    name: "y"
    offset: 4
    datatype: 7
    count: 1
  -
    name: "z"
    offset: 8
    datatype: 7
    count: 1
  -
    name: "intensity"
    offset: 16
    datatype: 7
    count: 1
  -
    name: "ring"
    offset: 20
    datatype: 4
    count: 1
is_bigendian: False
point_step: 32
row_step: 2137952
data: [235, 171, 54, 190, 53, 107, 250, ...
</code>```

Why height in Velodyne-HDL64e LiDAR is equal to one? I expected it to be 64.

Finally, for example, what is 171 value in data? is Y or is a range (for which one of the beams)?

答:
The height for the Velodyne-HDL64e LiDAR is one because it is an unorganized datasets. This is because pointclouds won't have the same amount of points in dynamic scenarios (if nothing is "seen" by the LiDAR the entry is just left out) while a pointcloud from a camera might have a fixed size (height x width) which helps to speedup some algorithms.

In your Pointcloud2 data example you have an unorganized datasets (indicated by height of 1) with a total of 66811 points (indicated by the width). The following message might have more or less points depending on the objects in the scene.


问:
SetuptoolsDeprecationWarning in ros2 Humble
I was trying to follow this tutorial in the official documentation of ros2 Humble for Integrating launch files into ROS 2 packages and ran in to the below given error after doing trying to perform a build on the package using

colcon build --packages-select py_launch_example
```
<p>The package build compilation given me the following error.</p>
```Starting >>> py_launch_example
[3.759s] WARNING:colcon.colcon_ros.task.ament_python.build:Package 'py_launch_example' doesn't explicitly install a marker in the package index (colcon-ros currently does it implicitly but that fallback will be removed in the future)
[3.793s] WARNING:colcon.colcon_ros.task.ament_python.build:Package 'py_launch_example' doesn't explicitly install the 'package.xml' file (colcon-ros currently does it implicitly but that fallback will be removed in the future)
--- stderr: py_launch_example
/usr/lib/python3/dist-packages/setuptools/command/install.py:34: SetuptoolsDeprecationWarning: setup.py install is deprecated. Use build and pip and other standards-based tools.
  warnings.warn(
---
Finished <<< py_launch_example [1.23s]

Summary: 1 package finished [4.38s]
  1 package had stderr output: py_launch_example
```

I have found a similar issue in this thread in ROS Answers. Please help! Thank you

Additional Informations

operating system : Ubuntu 22.04 LTS

ROS Distro : Humble

Python version : 3.10.6

Solutions I have tried :

Downgrading the setuptools to older version 58.2.0, this actually worked for me and the warning was no longer shown.

removing the line install_requires=['setuptools'] from the setup.py file and use --allow-overriding tag while rebuilding. This solution didn't work for me.

答:
It is a warning message, which affects Humble. The problem is the newest version of setuptools.
Look here for a possible solution. Basically you should downgrade setuptools to 58.2.0.
Personally I leave setuptools to the last version. Since this is a warning and not an error, it is annoying but not a problem. Probably it is going to disappear after the next update of setuptools. Downgrade is never a good option (to me)</p>


问:
creating a ros2 workspace
I am new to ros2 and have very little experience with it. Looking in to the documentation I have seen how to create a workspace in ros by cloning a github repository of your respective distro from their branch. Is there any other way to create a ros2 workspace with a single line terminal command similar to the one we use for creating a package in ros2. According to my knowledge I hope creating a workspace is necessary in order to create a package and run it. Thank you!</p>

答:
Basically a workspace in ROS is just a folder, which can be identified by ROS when sourcing the

install/setup.bash

file. So.. you do not need to download a pkg for creating a workspace, but just create a normal folder as you normally would do and most important create a subdirectory src in it, where you store your packages. Clear? Inside the src folder you can then create package with ros2 pkg create --build-type ament_cmake <package_name>

Title: creating a ros2 workspace


问:
odom frame keeps moving in ROS GPS robot_localization
I am using two instances of ROS robot_localization package to get the local and global odometry. In the local one, I am fusing IMU and twist messages. It is working fine. But when I use the second instance where map and odom frame both should be fixed points, one of them is moving. I set map as the fixed frame, then odom is moving. Why is that? Odom should remain fixed at the initial starting point. base_link with respect to odom is working fine but since odom is moving, base_link with respect to map is not working.

In the image, you can see the map frame is the big axes. odom frame was there too. But as I move the robot, the odom frame starts moving. The red lines are local odometry and green ones are global odometry.

1st instance:

```<code>ekf_se_odom: # Used only for broadcasting odom to base_link transforms
  frequency: 30
  sensor_timeout: 0.1
  two_d_mode: true
  transform_time_offset: 0.0
  transform_timeout: 0.0
  print_diagnostics: true
  debug: false

  map_frame: map
  odom_frame: odom
  base_link_frame: base_link
  world_frame: odom
</code>```

2nd instance:

```<code>ekf_se_map:
  frequency: 30
  sensor_timeout: 0.1
  two_d_mode: true
  transform_time_offset: 0.0
  transform_timeout: 0.0
  print_diagnostics: true
  debug: false

  map_frame: map
  odom_frame: odom
  base_link_frame: base_link
  world_frame: map

  publish_tf: true
</code>```

navsat_node:

```<code>navsat_transform:
  frequency: 30
  delay: 3.0
  magnetic_declination_radians: 0.0842
  yaw_offset: -1.57080
  zero_altitude: true
  broadcast_utm_transform: true
  publish_filtered_gps: true
  use_odometry_yaw: false
  wait_for_datum: false
  broadcast_utm_transform_as_parent_frame: false
</code>```

I am using gazebo husky simulation.

答:
Odom should remain fixed at the initial starting point.

This assumption is not correct, as map->odom is allowed to change. You have configured your 2nd instance to publish this update.

An update to the map->odom TF is typically done to correct for drift in odom->base_link since it comes from an odometry source.

The purpose of this to make the overall transform map->base_link a globally accurate source for localisation and mapping purpose which may have discontinuous jumps (e.g. Due to loop closure from SLAM), while maintaining odom->base_link as an approximately accurate but more importantly continuously varying TF for control and state estimation purposes.

The purpose of this structure is formalised and documented in REP-105


问:
Is Luenberger observer applicable in practical systems?
I have tried to find out about this from quite a few sources but it still remains unclear to me. I know that the Luenberger observer is applicable for a deterministic system with known control inputs while the Kalman filter is used for a stochastic linear dynamic system. There are versions of Kalman filters that are implementable for nonlinear systems with process and measurement noise, which is what we have in practice. Although there is an extended version of the Luenberger observer as well which could theoretically be applied to nonlinear systems, I have not found much about its practical applicability in the real world. So my question is - Is Luenberger observer used in practice? If yes, please provide a few examples to support your answer.</p>

答:
I don't understand the question here. It seems like the question boils down to "Kalman filters can be adapted to nonlinear systems, so why use Luenberger observers?" There are plenty of linear systems, and plenty of nonlinear systems that can be linearized.

Anywhere that you could use a standard Kalman filter you could also use a Luenberger observer. Personally I think the Luenberger observer is easier to understand and (importantly) easier to tune. The thumbrule I was taught was to have observer poles 5 to 10 times faster than the controller poles, to ensure your controller is acting on plant dynamics and not observer dynamics.

I don't know of any equivalent guidance for Kalman filters. Kalman filters require some values for process and measurement noise. The measurement noise is generally straightforward, but I have yet to read anything compelling on how to characterize process noise. Usually what winds up happening is the creation of a "tuning knob" that creates some ratio of process-to-measurement noise, and then you adjust that until you get some output that looks okay.

My issue with random adjustments is that I don't get a good feel for filter dynamics with that approach, which means then that it's hard to ensure that my controller is controlling the system and not just getting excited by filter dynamics.

In short, if you know you've got a good system model, I think you can get better control with the Luenberger observers. If you don't have a great system model, or the entirety of your model is essentially noise effects, then you can go with some basic motion model and use a Kalman filter. I've used Kalman filters to estimate wind effects, for example.

This is just my personal experience doing controls development.


问:
How to find the optimal path for a line following maze robot?
First let me explain the problem.

This is a maze made only out of black lines on a white surface. The robot has only a few IR sensors which can sense the position of the line. No other sensory input is available.

This is a maze with many self-loops and so a simple LSRB or equivalent algorithm wont work.
The robot is supposed to learn the maze and then solve it as optimally as possible .

The above figure represent the possible intersections as all the paths are at 90deg to each other.

As far as my understanding goes, the robot will first scan how many nodes there are, and what their connections to each other is, thus effectively constructing the graph. Next, implement any shortest path algorithm and make your robot follow it.

However, the main problem that i cant get my head around is this:

How will this blind robot know it isnt viewing the same node multiple
   times if it keeps coming back to the same point after getting caught in
   a loop?

Also, please suggest good approaches to solving this problems along with any experience anybody has. How does one shot searching methods like DFS , Iterative deepeing DFS , hill climbing work in such scenarios ?

The arrow indicates the direction of the robot and the black lines represent the track, which the robot has to follow .

答:
How will this blind robot know it isn't viewing the same node multiple
times if it keeps coming back to the same point after getting caught
in a loop?

If you can assume the robot moves at constant velocity, you can measure the elapsed-time between intersections, and use this travel-time as a stand-in for segment length. A grid-representation should allow you to determine whether the robot has arrived at a node that is already present on the map.

Once you have the complete map of node connections, you can easily find a path to minimize travel distance.


问:
How to import a 3D model in Webots_R2022b?
I have a 3D model which is made by SolidWorks. I remember that in older versions there was a function to import 3D models but I can't find it in R2022b. Can you tell me how to import it? Thanks so much!</p>

答:
The functionality to import CAD models was removed from the latest versions of Webots because there is now a better way to handle this. Instead of importing a CAD model, you should now refer to it using a CadShape node. Simply insert a CadShape node in your scene tree at the desired location. It may be at root level or inside some other node. Set the url field to the point to your CAD file (prefer a relative path to an absolute path) and you are done:

CadShape {
  url "model/my_model.dae"
}
```

The CadShape node supports the following 3D formats: DAE (Collada) and OBJ (Wavefront).

Alternatively, you may also consider using the Mesh node which imports only the geometry of a CAD file, excluding the appearance and material information. In should inserted in the geometry field of a Shape node. In addition to DAE and OBJ formats, the Mesh node also supports the STL format.

Disclaimer: I am a Webots developer working at Cyberbotics.

Body:
The functionality to import CAD models was removed from the latest versions of Webots because there is now a better way to handle this. Instead of importing a CAD model, you should now refer to it using a CadShape node. Simply insert a CadShape node in your scene tree at the desired location. It may be at root level or inside some other node. Set the url field to the point to your CAD file (prefer a relative path to an absolute path) and you are done:

CadShape {
  url "model/my_model.dae"
}

The CadShape node supports the following 3D formats: DAE (Collada) and OBJ (Wavefront).

Alternatively, you may also consider using the Mesh node which imports only the geometry of a CAD file, excluding the appearance and material information. In should inserted in the geometry field of a Shape node. In addition to DAE and OBJ formats, the Mesh node also supports the STL format.

Disclaimer: I am a Webots developer working at Cyberbotics.


答:
You have already suggested that a simple LSRB or equivalent won't work but could you please refer to this article, Coding a Line Follower Robot for Maze using LSRB Algorithm and finding its Shortest Path, which suggest a method for reducing the LSRB path with final optimisation. I am quoting the suggested shortest path finding step here,</p>
```<code>LBR = B

LBS = R

RBL = B

SBL = R

SBS = B

LBL = S
</code>```

Title: How to find the optimal path for a line following maze robot?

Body:
First let me explain the problem.

This is a maze made only out of black lines on a white surface. The robot has only a few IR sensors which can sense the position of the line. No other sensory input is available.

This is a maze with many self-loops and so a simple LSRB or equivalent algorithm wont work.
The robot is supposed to learn the maze and then solve it as optimally as possible .

The above figure represent the possible intersections as all the paths are at 90deg to each other.

As far as my understanding goes, the robot will first scan how many nodes there are, and what their connections to each other is, thus effectively constructing the graph. Next, implement any shortest path algorithm and make your robot follow it.

However, the main problem that i cant get my head around is this:

How will this blind robot know it isnt viewing the same node multiple
   times if it keeps coming back to the same point after getting caught in
   a loop?

Also, please suggest good approaches to solving this problems along with any experience anybody has. How does one shot searching methods like DFS , Iterative deepeing DFS , hill climbing work in such scenarios ?

The arrow indicates the direction of the robot and the black lines represent the track, which the robot has to follow .

Body:
You have already suggested that a simple LSRB or equivalent won't work but could you please refer to this article, Coding a Line Follower Robot for Maze using LSRB Algorithm and finding its Shortest Path, which suggest a method for reducing the LSRB path with final optimisation. I am quoting the suggested shortest path finding step here,

LBR = B

LBS = R

RBL = B

SBL = R

SBS = B

LBL = S


问:
Getting A Head Start With iRobot Create3 (ROS2)
With the announcement of the iRobot Create3 "with ROS2 support", and to get a head start playing with it, iRobot has some create3 GitHub repos:

https://github.com/iRobotEducation/create3_sim

https://github.com/iRobotEducation/create3_examples
and apparently a dependency on:

https://github.com/iRobotEducation/irobot_create_msgs

I have started a "Create3 ROS2 Controller" with a RaspberryPi3B running ROS2 Galactic over 64-bit Ubuntu 20.04 Server.

Since this is a headless, no desktop install, I have not installed the create3_sim repo.

Where should I put irobot_create_msgs and how do I build it?

My tree:

```<code>$ tree -L 2
├── create3ros
│   ├── create3_examples_ws
│   ├── create3_ws
</code>```

This is the error:

```<code>ubuntu@CREATE3:~/create3ros/create3_examples_ws$ colcon build
Starting >>> create3_examples_msgs
Starting >>> create3_examples_py
Finished <<< create3_examples_py [5.42s]
[Processing: create3_examples_msgs]
Finished <<< create3_examples_msgs [49.4s]
Starting >>> create3_coverage
--- stderr: create3_coverage
CMake Error at CMakeLists.txt:22 (find_package):
  By not providing "Findirobot_create_msgs.cmake" in CMAKE_MODULE_PATH this
  project has asked CMake to find a package configuration file provided by
  "irobot_create_msgs", but CMake did not find one.

  Could not find a package configuration file provided by
  "irobot_create_msgs" with any of the following names:

    irobot_create_msgsConfig.cmake
    irobot_create_msgs-config.cmake

  Add the installation prefix of "irobot_create_msgs" to CMAKE_PREFIX_PATH or
  set "irobot_create_msgs_DIR" to a directory containing one of the above
  files.  If "irobot_create_msgs" provides a separate development package or
  SDK, be sure it has been installed.

---
Failed   <<< create3_coverage [7.51s, exited with code 1]

Summary: 2 packages finished [58.1s]
  1 package failed: create3_coverage
  1 package had stderr output: create3_coverage
<span class="math-container">```
```

答:
For anyone looking for the answer for ROS2 Humble, there is an easy package

sudo apt install -y ros-humble-irobot-create-msgs


问:
3R Planar robot arm singularity
To find the situation where singularity occurs, the determinant of the Jacobian is used.

For the RRR planar robot with angles $q_1$, $q_2$, and $q_3$ and the length $L_1$, $L_2$, and $L_3$ as shown in the picture, the determinant of the Jacobian is as follows:

$$det(J) = L_1*L_2*sin(q_2)$$

$$L_1*L_2*sin(q_2) = 0$$

Therefore, singularity occurs when $q_2 = 0°$ or $q_2 = 180°$

I understand that singularity happens when the link is fully stretched or retracted. However, from the calculation of determinant of the Jacobian, it shows that the singularity will only occur when $q_2$ is 0 or 180 degrees.

My question is that when $q_3 = 0°$ or $180°$, why does the singularity not occur?

I just need to understand the physical meaning regarding the mathematical calculation.

答:
Sometimes I seem to equate planar and planar positioning, this would be one of those times. The workspace of the robot you are analyzing is the planar position and orientation workspace - i.e. $x$ and $y$ location of the end-effector and additionally some $\theta$ angle of the end-effector. In this case, the determinant of the Jacobian exists, and I'll take the papers word for the given formula being correct. It looks like what you're saying about the fully-extended and retracted states of the arm comes from the paper, so let's dig into that.

The fully-extended state of the arm refers to the first two links being parallel to each other, where their total length is the sum of each link's length, and the retracted state is the configuration where the two links are parallel but their length is the difference of their individual link length's. So, what about this robot guarantees that these configurations will always be singular?

Intuitively, I'm not quite sure. However, it appears that in these cases, we get something like $j_{1,1} = j_{1,2} + j_{1,3}$ and likewise $j_{2,1} = j_{2,2} + j_{2,3}$, where $j_{i,k}$ represents the $i^{\text{th}}$ row and the $k^{\text{th}}$ column of the Jacobian. Thus, we lose the ability to move the arm independently in some direction as the Jacobian has linearly dependent columns.

I can write out more of the math if you would like, but its really just a couple steps of work from the paper you listed.

As an aside, when the workspace of a robot has more than 2 DoFs (especially for orienting robots), the physical intuition of singularities is harder to visualize. As CroCo mentioned, it won't do much good to look into the matter more than the Jacobian loses rank, or likewise has linearly dependent columns.

Title: 3R Planar robot arm singularity


问:
Center of gravity offset for accelerometer and gyroscope readings
I am working on a 6DOF IMU that contains a 3 Axis Accelerometer and a 3 Axis Gyroscope.

I am building a project to plot the position and orientation of the turret/cabin in a crane in 3D space.

The IMU will be placed in the rear end of the cabin which is away from the centre of gravity of the vehicle.

The turret can move independently from the hull/body of the crane.
The crane performs extreme manoeuvres I am trying to plot those on a 3d graph both position and orientation.

I have some questions regarding this

Will the gyroscope have errors or uncertainty in its reading as it is placed away from COG? If yes, how do I compensate that.

I referred this article, Accelerometer Placement – Where and Why, stating effect on accelerometer if the IMU is placed away from COG. From this article I came to the conclusion that I have to compensate the accelerometer readings if Accelerometer is not placed at centre of gravity of the body, is my conclusion correct?
Can someone help me understanding.

If the turret is facing backword and crane is moving forward will this change my calculations.

答:
As mentioned in the comment above, I did work like this professionally for a long time. I'll start by saying that I've tried putting IMUs on cranes in the past, and you're really just better off pulling position information from the crane control system, which should be getting position information directly from the position encoders on the crane. This is the best, most reliable data you can get.

Any IMU will have biases and noise, and you will accumulate those errors over time.

Regarding your questions specifically:

Will the gyroscope have errors or uncertainty in its reading as it is placed away from COG? If yes, how do I compensate that.

Rotation of a rigid body is the same at all positions on the rigid body, so gyroscope readings are unaffected by placement, unless accelerations affect the readings. If this is the case then it should be noted in the datasheet.

I referred the bellow article stating effect on accelerometer if IMU is placed away from COG. From this article I came to the conclusion that I have to compensate the accelerometer readings if Accelerometer is not placed at centre of gravity of the body, is my conclusion correct? Can someone help me understanding.

Yes you will need to compensate, and I don't think I can explain any better than the article you linked explains it. An object that is rotating some distance $r$ from the center of rotation is also translating through space. But, since it's rotating, it's not translating in a straight line.

If it's not moving in a straight line then it must be accelerating, because acceleration is the only way to change the direction of the speed vector.

If the turret is facing backwards and crane is moving forward will this change my calculations.

The is a classic point that is drilled into engineering students - you need to create a free-body diagram that captures all of the relevant motions and forces when you create your equations of motion. As long as your equations are all based in the same frame then you shouldn't need to change anything based on orientation because they'll work themselves out with sign changes.

Rail-mounted gantry cranes can conceivably gantry and trolley, translating x- and y-directions, in addition to your slew/yaw motion. Rubber-tire gantry cranes, or any other cranes that aren't fixed to a rail (tracked cranes, etc.) could rotate the gantry frame in addition to rotating the cab/jib, and so you could possibly have two kinds of rotation in addition to two kinds of translation.

But really, I can't stress enough that an IMU will always have position drift, and there is nothing you will ever be able to do that will eliminate that position drift. The Madgwick filter uses gravity/down to fix roll and pitch rotations, but those shouldn't be an issue on a crane. You'd be more concerned with yaw/slew motion, which should be fixed by magnetic North, but any environment where a crane is operating will have a lot of magnetic interference that will prevent you from getting reliable compass readings.

If you "just" pull encoder readings off the crane then you could know the 3D position and orientation (pose) of the cab by forward kinematics. I put "just" in quotes because I know even this can be challenging, but I sincerely believe accessing that data is going to be easier and more effective long-term than trying to build a positioning system built around an IMU.


问:
ROS2 Humble packages for Ubuntu 22.04 - what is the perception package?
I've tried searches for documentation on the package but whilst I can sudo apt install -y ros-humble-perception or load it via docker as "ros-humble-perception" I didn't find any documentation to explain what it is apart from a mention on the humble release, ROS 2 Humble Hawksbill Released!

It appears to have added packages over base but not include simulation or full desktop.

答:
Looking around online, I found this page, which says (in part):

Installing ROS perception
We are going to install a single package called perception, which is a meta package of ROS containing all the perception related packages such as OpenCV, PCL, and so on.

In ROS Jade

$ sudo apt-get install ros-jade-perception

In ROS Indigo

$ sudo apt-get install ros-indigo-perception

This looks like the same command you've posted; sudo apt install -y ros-humble-perception, just for a different ROS release.

Looking around some more, I found this Github repo, which seems to be as described in the article.


问:
Importing 3D models into webots 2023a and splitting parts into shapes for a robot
I am quite new with Webots. I am wondering if there is a possibility to import 3D models into Webots 2023a as it was possible within Webots 2021b. I have managed to import it within 2021b, but when I specify the bounding object and I apply physics, the robot falls through the arena and bounces around underneath. The same thing occurs when I just create a solid with a box shape and apply bounding object and physics to it.

I know that you can import it using a CADshape within the 2023a version, would I have to import all parts of my model assembly separately and then assemble it within Webots under a robot node?

答:
I would recommend you to merge together in your 3D modeling software all the parts of your robots that don't move with respect to each other and save them into a single Collada/DAE or a wavefront/OBJ CAD file. At the end you will have several CAD files corresponding to each moving part of your robot that you will assemble together in Webots within a Robot node using the CADShape node. For example in case of a simple differential wheels robots, you will have typically 3 CAD files: one for the base of the robot and one for each of the two wheels. For a legged robot, you will end up with many more CAD files.

As for the bounding objects, I would recommend against using CAD files for them as it will impact the performance and quality of collision detection. Instead, you should use primitives, such as Sphere, Capsule, Box, Cylinder and/or combination of them as explained in this tutorial.

Disclaimer: I am a Webots developer working at Cyberbotics.


问:
How is the Homography formula derived?
In the Wikipedia article about Homography, the projective transformation between picture A to picture B is defined as:

$H_{ab} = R - \frac{t n^T}{d}$

However, the formula lacks the derivation. How is it derived?

答:
Given a point on a plane $p$, $n^T p$ for the directed unit normal vector for the plane gives you the projection of the given point onto the line of the normal vector, which gives you the distance $-d$ away from the origin on that plane (negative because the normal vector is in the opposite direction to the point vector). i.e.

$$
n^T p = -d
$$

For a homography from $a$ to $b$, we want

$$
p_b = H_{ab}p_a = (R_{ab}p_a+t_{ab})
$$

for some rotation and translation. The translation term is annoying because it doesn't have $p_a$ on the right even though H should be a single multiplicative term for p. We have to split up $H$ into a single multiplicative factor for $p$ with two terms, one for the $R$ which doesn't have to change, and one for $t$ for which we need to split out so that multiplying by $p$ results in the $t$ translation.

We do this by looking back at our $n^T p = -d$ equation, dividing by $-d$ on both sides so LHS = 1. The t can now be multiplied by the LHS, which doesn't change the value but introduces the $p$ to be factored out
$$
p_b = H_{ab}p_a = (R_{ab}+\frac{t_{ab}n^T}{-d})p \\
= R_{ab}p+ t_{ab}\frac{n^T p}{-d} \\
= R_{ab}P + t_{ab}
$$
This recovers our expected relationship

Title: How is the Homography formula derived?


问:
accelerometer and gyroscope fusion using extended kalman filter
I'm working on my graduation project which is characterizing human body posture. I'm using IMU so I get measurements from the accelerometer and gyroscope and I'm wealing to fuse these two filters so I can get Roll and pitch using extended Kalman filter, I'm confused if I should use Euler angle or Quaternions with the EKF, IF so what are the steps to get roll ant pitch. using EKF</p>

答:
You should be using quaternions for fusion for good behaviour. Addition and multiplication for quaternions will be swapped out by rotation composition operations for quaternions and your orientation dynamics will need to be linearised.

But you really shouldn't implement this from scratch if you can avoid it, you should be able to find plenty of EKF implementations that work with quaternions or other $SO(3)$ representations and reuse them.


问:
GPS to Cartesian
I'm interested in turning GPS position into Cartesian, I want to then transform it so the starting point is the origin.

Anyone have experience with this?

答:
This is a geopy https://geopy.readthedocs.io/en/stable/#module-geopy.distance method for going back and forth from a coordinate and a reference coordinate to relative meters in north and east:

#!/usr/bin/env python
# convert latitude-longitude-altitude to meters relative to reference point

import geopy
# geopy.distance doesn't work unless this is also done
from geopy import distance

# x is north and y is east
def coords_to_relative_meters(lat0, lng0, lat1, lng1, ellipsoid="WGS-84", north_then_east=False):
    xa = distance.geodesic((lat0, lng0), (lat1, lng0), ellipsoid=ellipsoid).m
    ya = distance.geodesic((lat1, lng0), (lat1, lng1), ellipsoid=ellipsoid).m
    print(f"north-then-east relative x north {xa}m, y east {ya}m")

    yb = distance.geodesic((lat0, lng0), (lat0, lng1), ellipsoid=ellipsoid).m
    xb = distance.geodesic((lat0, lng1), (lat1, lng1), ellipsoid=ellipsoid).m
    print(f"east-then-north relative x north {xb}m, y east {yb}m")

    print(f"north-then-east vs. east-then-north error {(xb - xa):0.6f}m {(yb - ya):0.6f}m")
    if north_then_east:
        return xa, ya
    else:
        return xb, yb

def relative_meters_to_coords(lat0, lng0, rel_x, rel_y, ellipsoid="WGS-84", north_then_east=False):
    # 0 is north (rel_x), 90 is east (rel_y)
    ll_na = distance.geodesic(meters=rel_x, ellipsoid=ellipsoid).destination((lat0, lng0), bearing=0.0)
    ll_ea = distance.geodesic(meters=rel_y, ellipsoid=ellipsoid).destination(ll_na, bearing=90.0)
    print(f"north-then-east relative x north {ll_ea.latitude}° {ll_ea.longitude}°")

    ll_eb = distance.geodesic(meters=rel_y, ellipsoid=ellipsoid).destination((lat0, lng0), bearing=90.0)
    ll_nb = distance.geodesic(meters=rel_x, ellipsoid=ellipsoid).destination(ll_eb, bearing=0.0)
    print(f"east-then-north relative x north {ll_nb.latitude}° {ll_ea.longitude}°")

    text = "north-then-east vs. east-then-north error"
    text += f" lat {(ll_ea.latitude - ll_nb.latitude):0.6f}°"
    text += f", long {(ll_ea.longitude - ll_nb.longitude):0.6f}°"
    print(text)

    if north_then_east:
        rv = ll_ea
    else:
        rv = ll_nb

    return rv.latitude, rv.longitude

if __name__ == "__main__":
    print(geopy.__version__)

    lat0 = 46.8454439
    lng0 = -121.7649698
    print(f"reference {lat0}° {lng0}°")

    lat1 = lat0 + 0.01
    lng1 = lng0 + 0.01
    print(f"target    {lat1}° {lng1}°")

    # if this is set false then round trip error much lower because of the way the conversion
    # back to lat to long works
    north_then_east = True
    print(f"relative coordinates {lat1 - lat0}° {lng1 - lng0}°")
    for ellipsoid in distance.ELLIPSOIDS.keys():
        print(f"\n{ellipsoid}")
        rel_x, rel_y = coords_to_relative_meters(lat0, lng0, lat1, lng1,
                                                 ellipsoid=ellipsoid, north_then_east=north_then_east)
        lat1b, lng1b = relative_meters_to_coords(lat0, lng0, rel_x, rel_y,
                                                 ellipsoid=ellipsoid, north_then_east=north_then_east)
        print(f"round trip conversion error lat {(lat1b - lat1)}°, lng {(lng1b - lng1)}°")
```
<p>and the output for WGS-84:</p>
```reference 46.8454439° -121.7649698°
target    46.8554439° -121.7549698°
relative coordinates 0.00999999999999801° 0.010000000000005116°

WGS-84
north-then-east relative x north 1111.6792380437344m, y east 762.6088552752285m
east-then-north relative x north 1111.6792380437344m, y east 762.7504100234593m
north-then-east vs. east-then-north error 0.000000m 0.141555m

north-then-east relative x north 46.85544346321024° -121.7549698000608°
east-then-north relative x north 46.85544346336275° -121.7549698000608°
north-then-east vs. east-then-north error lat -0.000000°, long 0.000002°
round trip conversion error lat -4.367897545876076e-07°, lng -6.080824732634937e-11°
```

The bigger the change in latitude the more error the relative y/east meters has- 0.15 meters when for example about a kilometer is traversed moving north from the reference point to the target point using the above output.  As long as everything has good lat/long coordinates to start and they share the reference point and use consistent coordinate conversion functions it may not matter much (it's a little useless if a gnss sensor sdk has the option to output relative meters but doesn't expose a call to convert any coordinate using the same function, or document what they did to do the conversion, you wouldn't want to commingle two different sensors with two conversion methods).

If you had really good relative distance measurements and wanted to convert in the other direction, get latitude longitude given distance traveled from a reference point it would be better to break the path up into segments than take the endpoints and ignore the path between them if the amount of error is a concern.

Title: GPS to Cartesian

Body:
This is a geopy https://geopy.readthedocs.io/en/stable/#module-geopy.distance method for going back and forth from a coordinate and a reference coordinate to relative meters in north and east:

#!/usr/bin/env python
# convert latitude-longitude-altitude to meters relative to reference point

import geopy
# geopy.distance doesn't work unless this is also done
from geopy import distance

# x is north and y is east
def coords_to_relative_meters(lat0, lng0, lat1, lng1, ellipsoid="WGS-84", north_then_east=False):
    xa = distance.geodesic((lat0, lng0), (lat1, lng0), ellipsoid=ellipsoid).m
    ya = distance.geodesic((lat1, lng0), (lat1, lng1), ellipsoid=ellipsoid).m
    print(f"north-then-east relative x north {xa}m, y east {ya}m")

    yb = distance.geodesic((lat0, lng0), (lat0, lng1), ellipsoid=ellipsoid).m
    xb = distance.geodesic((lat0, lng1), (lat1, lng1), ellipsoid=ellipsoid).m
    print(f"east-then-north relative x north {xb}m, y east {yb}m")

    print(f"north-then-east vs. east-then-north error {(xb - xa):0.6f}m {(yb - ya):0.6f}m")
    if north_then_east:
        return xa, ya
    else:
        return xb, yb

def relative_meters_to_coords(lat0, lng0, rel_x, rel_y, ellipsoid="WGS-84", north_then_east=False):
    # 0 is north (rel_x), 90 is east (rel_y)
    ll_na = distance.geodesic(meters=rel_x, ellipsoid=ellipsoid).destination((lat0, lng0), bearing=0.0)
    ll_ea = distance.geodesic(meters=rel_y, ellipsoid=ellipsoid).destination(ll_na, bearing=90.0)
    print(f"north-then-east relative x north {ll_ea.latitude}° {ll_ea.longitude}°")

    ll_eb = distance.geodesic(meters=rel_y, ellipsoid=ellipsoid).destination((lat0, lng0), bearing=90.0)
    ll_nb = distance.geodesic(meters=rel_x, ellipsoid=ellipsoid).destination(ll_eb, bearing=0.0)
    print(f"east-then-north relative x north {ll_nb.latitude}° {ll_ea.longitude}°")

    text = "north-then-east vs. east-then-north error"
    text += f" lat {(ll_ea.latitude - ll_nb.latitude):0.6f}°"
    text += f", long {(ll_ea.longitude - ll_nb.longitude):0.6f}°"
    print(text)

    if north_then_east:
        rv = ll_ea
    else:
        rv = ll_nb

    return rv.latitude, rv.longitude

if __name__ == "__main__":
    print(geopy.__version__)

    lat0 = 46.8454439
    lng0 = -121.7649698
    print(f"reference {lat0}° {lng0}°")

    lat1 = lat0 + 0.01
    lng1 = lng0 + 0.01
    print(f"target    {lat1}° {lng1}°")

    # if this is set false then round trip error much lower because of the way the conversion
    # back to lat to long works
    north_then_east = True
    print(f"relative coordinates {lat1 - lat0}° {lng1 - lng0}°")
    for ellipsoid in distance.ELLIPSOIDS.keys():
        print(f"\n{ellipsoid}")
        rel_x, rel_y = coords_to_relative_meters(lat0, lng0, lat1, lng1,
                                                 ellipsoid=ellipsoid, north_then_east=north_then_east)
        lat1b, lng1b = relative_meters_to_coords(lat0, lng0, rel_x, rel_y,
                                                 ellipsoid=ellipsoid, north_then_east=north_then_east)
        print(f"round trip conversion error lat {(lat1b - lat1)}°, lng {(lng1b - lng1)}°")

and the output for WGS-84:

reference 46.8454439° -121.7649698°
target    46.8554439° -121.7549698°
relative coordinates 0.00999999999999801° 0.010000000000005116°

WGS-84
north-then-east relative x north 1111.6792380437344m, y east 762.6088552752285m
east-then-north relative x north 1111.6792380437344m, y east 762.7504100234593m
north-then-east vs. east-then-north error 0.000000m 0.141555m

north-then-east relative x north 46.85544346321024° -121.7549698000608°
east-then-north relative x north 46.85544346336275° -121.7549698000608°
north-then-east vs. east-then-north error lat -0.000000°, long 0.000002°
round trip conversion error lat -4.367897545876076e-07°, lng -6.080824732634937e-11°

The bigger the change in latitude the more error the relative y/east meters has- 0.15 meters when for example about a kilometer is traversed moving north from the reference point to the target point using the above output.  As long as everything has good lat/long coordinates to start and they share the reference point and use consistent coordinate conversion functions it may not matter much (it's a little useless if a gnss sensor sdk has the option to output relative meters but doesn't expose a call to convert any coordinate using the same function, or document what they did to do the conversion, you wouldn't want to commingle two different sensors with two conversion methods).

If you had really good relative distance measurements and wanted to convert in the other direction, get latitude longitude given distance traveled from a reference point it would be better to break the path up into segments than take the endpoints and ignore the path between them if the amount of error is a concern.


答:
The proper reference is the ROS Enhancement Proposals (REPs) which provide a concise technical specification for various things related to ROS.
There you can find a document describing the different ROS 2 variants. It says

The perception variant includes packages commonly used for perception capabilities.

and as you can see it is only available from Humble Hawksbill.
Thus the ros-humble-perception variant contains following packages:

```<code>- perception:
    extends:  [ros_base]
    packages: [image_common, image_pipeline, image_transport_plugins,
               laser_filters, laser_geometry, perception_pcl,
               vision_opencv]
</code>```

including ros_base that is defined as

```<code>- ros_base:
    extends:  [ros_core]
    packages: [geometry2, kdl_parser, robot_state_publisher,
               rosbag2, urdf]
</code>```

and ros_core with

```<code>- ros_core:
    packages: [ament_cmake, ament_cmake_auto, ament_cmake_gmock,
               ament_cmake_gtest, ament_cmake_pytest,
               ament_cmake_ros, ament_index_cpp,
               ament_index_python, ament_lint_auto,
               ament_lint_common, class_loader, common_interfaces,
               launch, launch_ros, launch_testing,
               launch_testing_ament_cmake, launch_testing_ros,
               launch_xml, launch_yaml, pluginlib, rcl_lifecycle,
               rclcpp, rclcpp_action, rclcpp_lifecycle, rclpy,
               ros2cli_common_extensions, ros2launch,
               ros_environment, rosidl_default_generators,
               rosidl_default_runtime, sros2, sros2_cmake]
    And at least one of the following rmw_implementation:
    - Fast-RTPS: [Fast-CDR, Fast-RTPS, rmw_fastrtps]
    - CycloneDDS: [cyclonedds, rmw_cyclonedds]
    - Connext: [rmw_connextdds]
</code>```

As you can see it doesn't contain any packages needed for a "desktop experience" like rviz2.

Therefore you need to install the largest package via sudo apt install -y ros-humble-desktop-full which contains everything that is officially supplied for ROS 2. (Gazebo must be installed separately, see their instructions)

```<code>- desktop_full:
    extends:  [desktop]
    packages: [perception, simulation, ros_ign_gazebo_demos]
</code>```

Title: ROS2 Humble packages for Ubuntu 22.04 - what is the perception package?

Body:
I've tried searches for documentation on the package but whilst I can sudo apt install -y ros-humble-perception or load it via docker as "ros-humble-perception" I didn't find any documentation to explain what it is apart from a mention on the humble release, ROS 2 Humble Hawksbill Released!

It appears to have added packages over base but not include simulation or full desktop.

Body:
The proper reference is the ROS Enhancement Proposals (REPs) which provide a concise technical specification for various things related to ROS.
There you can find a document describing the different ROS 2 variants. It says

The perception variant includes packages commonly used for perception capabilities.

and as you can see it is only available from Humble Hawksbill.
Thus the ros-humble-perception variant contains following packages:

- perception:
    extends:  [ros_base]
    packages: [image_common, image_pipeline, image_transport_plugins,
               laser_filters, laser_geometry, perception_pcl,
               vision_opencv]

including ros_base that is defined as

- ros_base:
    extends:  [ros_core]
    packages: [geometry2, kdl_parser, robot_state_publisher,
               rosbag2, urdf]

and ros_core with

- ros_core:
    packages: [ament_cmake, ament_cmake_auto, ament_cmake_gmock,
               ament_cmake_gtest, ament_cmake_pytest,
               ament_cmake_ros, ament_index_cpp,
               ament_index_python, ament_lint_auto,
               ament_lint_common, class_loader, common_interfaces,
               launch, launch_ros, launch_testing,
               launch_testing_ament_cmake, launch_testing_ros,
               launch_xml, launch_yaml, pluginlib, rcl_lifecycle,
               rclcpp, rclcpp_action, rclcpp_lifecycle, rclpy,
               ros2cli_common_extensions, ros2launch,
               ros_environment, rosidl_default_generators,
               rosidl_default_runtime, sros2, sros2_cmake]
    And at least one of the following rmw_implementation:
    - Fast-RTPS: [Fast-CDR, Fast-RTPS, rmw_fastrtps]
    - CycloneDDS: [cyclonedds, rmw_cyclonedds]
    - Connext: [rmw_connextdds]

As you can see it doesn't contain any packages needed for a "desktop experience" like rviz2.

Therefore you need to install the largest package via sudo apt install -y ros-humble-desktop-full which contains everything that is officially supplied for ROS 2. (Gazebo must be installed separately, see their instructions)

- desktop_full:
    extends:  [desktop]
    packages: [perception, simulation, ros_ign_gazebo_demos]


问:
Recording controller output
I am a new to the field of control systems.

In real life systems, such as process industry or continuous manufacturing, where large number of feedback control loops are present - is controller output always recorded and preserved in a dataset? If one has to do an offline analysis using the setpoint, controller output, and process variable - using historic data collected at batch level, is this data generally recorded and available? I would assume that process variable and setpoint data would be available, but would like to know if Controller output is also recorded and stored?

答:
Really comes down to the system and how you want to implement it. Sometimes it never records, other times it always records, other times it comes with a debug mode that records for you to analyse when developing and turn off in production systems.

Control data for high frequency processes does blow up quite quickly in size though, so most people aren't constantly recording their 500 Hz+ PID loop.

Title: Recording controller output


问:
How to programatically calibrate Turningy esc?
I have a Turnigy ESC and I am controlling it from AVR. Now I need to calibrate it to set the range of the input.
With a servo tester I managed to calibrate it without any problems, more or less by following the user guide, but when I try to do the same procedure from code, the ESC starts beeping in some confused pattern and then enters programming mode.

My code looks like this:

```<code>void calibrate_turningy_esc()
{
    servo_set16(SERVO_RANGE_TICKS);
    for (uint16_t i = 0; i < 10000; ++i)
        _delay_ms(1);
    servo_set16(-SERVO_RANGE_TICKS);
    for (uint16_t i = 0; i < 10000; ++i)
        _delay_ms(1);
    servo_set16(0);
    for (uint16_t i = 0; i < 10000; ++i)
        _delay_ms(1);
}
</code>```

where +SERVO_RANGE_TICKS is 2.2ms pulse length, -SERVO_RANGE_TICKS is 0.8ms pulse length and 0 is 1.5ms. The timeouts of 10s were measured during the manual calibration with a stopwatch.

I have checked with an oscilloscope that the output servo signal looks the way I would expect it -- 10 seconds of 2.2ms pulses, 10 seconds of 0.8ms pulses and then 1.5ms pulses.
Edit: I made a mistake here, see my answer.

Do you have any idea what to change to calibrate the ESC?

答:
So, the calibration code was essentially correct. The problem was in my Makefile dependency code.

For previous tests i used a range from 0.5 to 2.5ms and that was clearly too much for this ESC. I tried to decrease the range to 0.8ms - 2.2ms, but my makefile didn't notice the change and kept uploading the old version ... After a clean rebuild the ESC is calibrated without any problems.

As for the oscilloscope check... I mixed them up :-)


问:
4 wheeled differential wheeled (skid-steer) robot steering problem
My question is about a square shaped differential wheeled robot, I built, that has a hub-motor (BLDC motor) attached to each corner, i.e., the wheels on the same side, either left or right, have the same velocity and direction (skid-steer). Currently, I’m able to move it back and forth but I’m not able to steer it by using different wheel speeds, i.e., left side spinning faster than the right side and vice versa, or let alone to turn it in place, i.e., left side spinning at the same speed as the right side but with opposite direction. In the case of using different wheel speeds, it keeps going forward. When trying to make it turn in place, it just doesn’t move at all. I’ve tested the wheels spinning off the ground, and they did spin according to the differential drive system. The tests were performed on asphalt. The wheels are hub-motors for e-bikes (bike tires).

What could be the problem? Not enough power (torque) in the hub-motors? the geometry of the robot? What calculations I can do to calculate the power necessary of each motor to steer it with different wheel speeds or turn it in place?

Best,

答:
The most likely cause is that your motor torque is too small. Another way to look at this is that the friction between wheel and ground is too large.

You can reduce this friction by using smoother tires, or by covering the tire treads with something like duct tape. Be aware this may have side effects e.g. your wheel-encoder odometry can become less accurate.


问:
How to solve action client not connected?
Does anyone know how to solve error action client not connected?

The error text is:

```<code>[ WARN] [1559064181.400017201, 235.919000000]: Waiting for arm_controller_moveit/joint_trajectory_action to come up
[ WARN] [1559064188.755204272, 241.920000000]: Waiting for arm_controller_moveit/joint_trajectory_action to come up
[ERROR] [1559064196.377289892, 247.920000000]: Action client not connected: arm_controller_moveit/joint_trajectory_action
</code>```

When I try to see all action servers with the command:

```<code>rostopic list | grep -i goal
</code>```

This is output:

```<code> /execute_trajectory/goal
 /joint_trajectory_action/goal
 /move_base_simple/goal
 /move_group/goal
 /pickup/goal
 /place/goal
</code>```

I am using joint_trajectory_action action server, but I tried with other and it is not working.

Any help would be appreciated. Thanks in advance!

答:
You have a namespace mismatch. Your ros node is looking for the action server at:

```<code>/arm_controller_moveit/joint_trajectory_action
</code>```

but your setup is actually running it at:

```<code>/joint_trajectory_action
</code>```

This bug report https://github.com/ros-planning/moveit/issues/1263 fixed it by changing their controllers.yaml file to:

```<code>name: joint_trajectory_action
action_ns: ''
</code>```

Body:
You have a namespace mismatch. Your ros node is looking for the action server at:

/arm_controller_moveit/joint_trajectory_action

but your setup is actually running it at:

/joint_trajectory_action

This bug report https://github.com/ros-planning/moveit/issues/1263 fixed it by changing their controllers.yaml file to:

name: joint_trajectory_action
action_ns: ''


问:
Bevel Gear Compatibility
ServoCity sells a great little 2:1 bevel gear ratio set: 2:1 Bevel Gear Set (1/4" Bore Pinion, 1/4" Bore Spur)

I have it currently set up in my project and was thinking a 1:1 gear ratio might be better suited for my purposes.  All over the site it says the 13t gear must be paired with the 26t gear. Is there any reason why pairing two 13t gears together wouldn't work?  I can't see why not, but, I want to confirm with people smarter than me.

答:
Bevel gears are not generally interchangeable. For a bevel gear set to work, the virtual cones generated by the pitch (or root) angles of each gear have to meet at the pitch apex. The image below shows the pitch apex.

To help see the issue, I made the graphic below. I made a copy of the larger gear and tried to mate it to the smaller. Immediately, you can see that there are problems. The cones do not meet (blue arrow). We can also see that the gear teeth do not mesh correctly (orange arrow).

(The images above are not mine. I pulled them from the nice discussion on this site and modified:
The Theory of Meccano Gears: Part 3 — Bevel Gears )

Title: Bevel Gear Compatibility


问:
Difference between various ros distro?
I have a doubt on why there are so many distributions of ros2 or ros and what are the major factors that changes between them?</p>

答:
Have a look at the official documentation about Distributions:

What is a Distribution?

A ROS distribution is a versioned set of ROS packages. These are akin to Linux distributions (e.g. Ubuntu). The purpose of the ROS distributions is to let developers work against a relatively stable codebase until they are ready to roll everything forward. Therefore once a distribution is released, we try to limit changes to bug fixes and non-breaking improvements for the core packages (every thing under ros-desktop-full). That generally applies to the whole community, but for “higher” level packages, the rules are less strict, and so it falls to the maintainers of a given package to avoid breaking changes.

Active development goes into one distribution at a time. Each distro has an EOL (end-of-life) date — some distributions are "LTS" (long-term support) and have longer lifespans.

The "Rolling" distro is a special, continuously-updated distro that always has the very latest packages, but is less stable. If you use Rolling, you must be prepared to handle frequent breakages due to package upgrades.

Significant changes to core ROS features in each distro can be found in the release's page on the wiki, for example Humble: https://docs.ros.org/en/rolling/Releases/Release-Humble-Hawksbill.html#new-features-in-this-ros-2-release

Additionally, each package may have its own release notes. Individual version bumps for each package are called out in Discourse under the Packaging and Release Management category.

Title: Difference between various ros distro?


问:
What do quadcopter propeller specifications mean?
I'm trying to figure out the diameter of tri-blade propellers.

I found a 7x3x4.5 blade, I'm trying to understand the measurements. Is the '7' the length of the blade giving the prop a 10.5" diameter? or is the 7 the total diameter?

答:
7 is diameter of propeller in inches and 4.5 is pitch of propeller in inches. </p>

<p>Unless mentioned, propeller parameters are mentioned in inches. The Pitch of a propeller is distance covered by the propeller in one full rotation hence measured in inches. This is similar to pitch of a screw. </p>

Body:
7 is diameter of propeller in inches and 4.5 is pitch of propeller in inches.

Unless mentioned, propeller parameters are mentioned in inches. The Pitch of a propeller is distance covered by the propeller in one full rotation hence measured in inches. This is similar to pitch of a screw.


问:
Calculation of IMU offset for Placement of Inertial measurement unit away from centre of mass
I am working on a 6DOF IMU that contains a 3-axis accelerometer and a 3-axis gyroscope. I am building a project to plot the position and orientation of a vehicle/dirt bike in a 3d plane. However, the inertial measurement unit is placed away from the centre of mass of the vehicle i.e. in the boot/taillight of the car/bike. The vehicle will be performing extreme manoeuvres in a terrain. I have the below questions regarding this matter.

As far as I have read, I have to offset accelerometer and gyroscope readings due to its placement away from the centre of mass of the vehicle. In some articles I have read that the placement of the gyroscope does not affect gyroscope readings; however, just to be sure, I am asking once again if gyro measurements needed to be offset.

I have found two articles stating how to offset accelerometer readings with regards to its placement inside the body.

Accelerometer Placement – Where and Why

In this article the below formula is used:

$$
\begin{matrix}{}
A_{r’} & = & A + A_r            & + \\
       &   & 2\omega \times V_r & + \\
       &   & \alpha \times r    & + \\
       &   & \omega \times (\omega \times r) & + &\end{matrix}\begin{aligned}
&\leftarrow \text{Inertial Acceleration} \\
&\leftarrow \text{Coriolis Acceleration} \\
&\leftarrow \text{Euler Acceleration} \\
&\leftarrow \text{Centripetal Acceleration}
\end{aligned}$$

However, I am not sure how to proceed with this formula. I have $a_x$, $a_y$, and $a_z$ from IMU from a point X (i.e. where the IMU is placed) and using this formula I want to get $a_x$, $a_y$, and $a_z$ at centre of mass of the vehicle; but I am confused as to how to proceed with this formula.

Calculating acceleration offset by Center of Gravity (C.G.)

Starting from the well-known acceleration transformation formula between an arbitrary point A and the center of mass C with $\vec{c} = \vec{r}_C - \vec{r}_A$.

$$ \vec{a}_C = \vec{a}_A + \dot{\vec{\omega}} \times \vec{c} + \vec{\omega} \times \vec{\omega} \times \vec{c} $$

one can use the 3×3 cross product operator to transform the above into

$$ \vec{a}_C = \vec{a}_A + \begin{vmatrix} 0 & -\dot{\omega}_z & \dot{\omega}_y \\ \dot{\omega}_z & 0 & -\dot{\omega}_x \\ -\dot{\omega}_y & \dot{\omega}_x & 0 \end{vmatrix} \vec{c} + \begin{vmatrix} 0 & -\omega_z & \omega_y \\ \omega_z & 0 & -\omega_x \\ -\omega_y & \omega_x & 0 \end{vmatrix} \begin{vmatrix} 0 & -\omega_z & \omega_y \\ \omega_z & 0 & -\omega_x \\ -\omega_y & \omega_x & 0 \end{vmatrix} \vec{c} $$

or in the form seen the linked post

$$ \vec{a}_C = \vec{a}_A +  \begin{vmatrix}
-\omega_y^2-\omega_z^2 & \omega_x \omega_y - \dot{\omega}_z & \omega_x \omega_z + \dot{\omega}_y \\ \omega_x \omega_y + \dot{\omega}_z & -\omega_x^2-\omega_z^2 & \omega_y \omega_z - \dot{\omega}_x \\ \omega_x \omega_z - \dot{\omega}_y & \omega_y \omega_z + \dot{\omega}_x & -\omega_x^2 - \omega_y^2  \end{vmatrix}  \vec{c} $$

However I am confused about this formula as well, since none of them give me ax, ay, and az from the centre of mass of the vehicle.

Kindly help me since I am new to this field, I am originally from a computer science background, and I am struggling to understand these concepts.

Also, if you can give me reference documents as to how do I interpret values from accelerometer and gyroscope, rotation and why is it necessary, that would be great.

答:
The second post you link there seems to explain it pretty well:

Starting from the well known acceleration transformation formula between an arbitrary point A and the center of mass C with $\vec{c} = \vec{r}_C - \vec{r}_A$.

$$ \vec{a}_C = \vec{a}_A + \dot{\vec{\omega}} \times \vec{c} + \vec{\omega} \times \vec{\omega} \times \vec{c} $$

If you have an accelerometer at arbitrary point A and you're trying to determine acceleration about the center of mass C, then you should rearrange the equation to solve for $\vec{a}_A$, right? The trivial answer is

$$ \vec{a}_A = \vec{a}_C - \dot{\vec{\omega}} \times \vec{c} + \vec{\omega} \times \vec{\omega} \times \vec{c} $$

but you can apply a similar rearranging to the expanded equation you gave in your answer.