答: One number is wrong in the EKF config. Odom1 is configured as another odom0! This won't work right! Got it fixed and things are moving forward.</p>

Title: Robot loses proper localization

Body:
Having trouble getting robot to stay localized in map. The lidar maps the correct position of robot but not the odometry or ekf tf. One can see the two positions on graphic below.

The robot base is Linorobot2 with differential drive and I'm using Nav2 and Humble. I'm running Rtabmap on the robot without the rtabmapviz node and it publishes the Velodyne puck ICP odometry. The host runs the complete Nav2 stack and SLAM Toolbox with Rviz2.

The Gazebo sim works well for mapping and navigation but the real robot has this trouble, as shown in graphic.

I tried feeding the ICP odom into the EKF node also but it just made things worse, I had to change it back to just the IMU and wheel odometry going into the EKF node.

What is the correct way to troubleshoot this setup? Should I adjust the encoder ticks per meter? I have never seen the amcl arrows, though it seems to be running, as it sometimes posts warnings.

From launch file:

```<code>    Node(
        package='rtabmap_ros', executable='icp_odometry', output='screen',
        parameters=[{
          'frame_id':'velodyne',
          'odom_frame_id':'odom',
          'wait_for_transform':0.2,
          'expected_update_rate':15.0,
          'deskewing':deskewing,
          'use_sim_time':use_sim_time,
        }],
        remappings=[
          ('scan_cloud', '/velodyne_points'),
          ('odom', 'odom_icp')
        ],
        arguments=[
          'Icp/PointToPlane', 'true',
          'Icp/Iterations', '10',
          'Icp/VoxelSize', '0.1',
          'Icp/Epsilon', '0.001',
          'Icp/PointToPlaneK', '20',
          'Icp/PointToPlaneRadius', '0',
          'Icp/MaxTranslation', '2',
          'Icp/MaxCorrespondenceDistance', '1',
          'Icp/Strategy', '1',
          'Icp/OutlierRatio', '0.7',
          'Icp/CorrespondenceRatio', '0.01',
          'Odom/ScanKeyFrameThr', '0.6',
          'OdomF2M/ScanSubtractRadius', '0.1',
          'OdomF2M/ScanMaxSize', '15000',
          'OdomF2M/BundleAdjustment', 'false',
        ]),
</code>```

ekf_filter_node:
ros__parameters:

```<code>    frequency: 50.0

    two_d_mode: true

    publish_tf: true

    use_control: false

    map_frame: map
    odom_frame: odom
    base_link_frame: base_footprint
    world_frame: odom

    #x     , y     , z,
    #roll  , pitch , yaw,
    #vx    , vy    , vz,
    #vroll , vpitch, vyaw,
    #ax    , ay    , az

    # from Robbie's encoders
    odom0: odom/unfiltered
    odom0_config: [false, false, false,
                   false, false, false,
                   true, true, false,
                   false, false, true,
                   false, false, false]

    # from ICP module of Rtabmap
    odom1: odom_icp
    odom0_config: [true, true, false,
                   false, false, true,
                   false, false, false,
                   false, false, false,
                   false, false, false]

    # from MPU 9250
    imu0: imu/data
    imu0_config: [false, false, false,
                  false, false, false,
                  false, false, false,
                  false, false, true,
                  true, false, false]
</code>```

[component_container_isolated-1] [INFO] [1677951250.137225667] [amcl]: Message Filter dropping message: frame 'velodyne' at time 1677951249.140 for reason 'the timestamp on the message is earlier than all the data in the transform cache'
[component_container_isolated-1] [INFO] [1677951250.208334876] [local_costmap.local_costmap]: Timed out waiting for transform from base_link to odom to become available, tf error: Invalid frame ID "odom" passed to canTransform argument target_frame - frame does not exist
[component_container_isolated-1] [INFO] [1677951250.237334995] [amcl]: Message Filter dropping message: frame 'velodyne' at time 1677951249.240 for reason 'the timestamp on the message is earlier than all the data in the transform cache'
[component_container_isolated-1] [INFO] [1677951250.366020161] [amcl]: Message Filter dropping message: frame 'velodyne' at time 1677951249.340 for reason 'discarding message because the queue is full'
[component_container_isolated-1] [INFO] [1677951250.456398646] [amcl]: Message Filter dropping message: frame 'velodyne' at time 1677951249.441 for reason 'discarding message because the queue is full'
[component_container_isolated-1] [INFO] [1677951250.541983751] [amcl]: Message Filter dropping message: frame 'velodyne' at time 1677951249.540 for reason 'the timestamp on the message is earlier than all the data in the transform cache'
[component_container_isolated-1] [INFO] [1677951250.666734227] [amcl]: Message Filter dropping message: frame 'velodyne' at time 1677951249.643 for reason 'discarding message because the queue is full'
[component_container_isolated-1] [INFO] [1677951250.708331804] [local_costmap.local_costmap]: Timed out waiting for transform from base_link to odom to become available, tf error: Invalid frame ID "odom" passed to canTransform argument target_frame - frame does not exist
[component_container_isolated-1] [INFO] [1677951250.744652632] [amcl]: Message Filter dropping message: frame 'velodyne' at time 1677951249.739 for reason 'discarding message because the queue is full'


问:
To demonstrate motion planning of a Husky robot through dynamic environments using Gazebo, how can I introduce moving characters in Gazebo?
I am working on the ClearPath Husky ROS Navigation stack and am trying to demonstrate the motion of Husky through an environment with dynamic obstacles in Gazebo.

I see that mostly such a demonstration of algorithms is done in MATLAB and Pygame in 2D and using point objects.

How can this be done in Gazebo?

答: Gazebo has its own tools to simulate object dynamics. See https://classic.gazebosim.org/tutorials?tut=animated_box</p>

ContentLicense: CC BY-SA 4.0


问:
Calculate joint torques in 3 joint RRR mechanism
I don't know if I could upload these things here, but I want solve the following exercise:.

I undestand that I should use the following formula:

But, I have to solve every joint torque, so how could I get those values?

Thanks

答:
Here below are the expressions you ought to recruit:

$$
\mathbf{J} \left( \mathbf{\theta} \right) = \left( \begin{matrix} \frac{\partial x_e}{\partial \theta_1} & \frac{\partial x_e}{\partial \theta_2} & \frac{\partial x_e}{\partial \theta_3} \\ \frac{\partial y_e}{\partial \theta_1} & \frac{\partial y_e}{\partial \theta_2} & \frac{\partial y_e}{\partial \theta_3} \\ \frac{\partial \phi_e}{\partial \theta_1} & \frac{\partial \phi_e}{\partial \theta_2} & \frac{\partial \phi_e}{\partial \theta_3} \end{matrix} \right),
$$

being $\left( x_e, y_e, \phi_e \right)^T$ the coordinates of the tip,

$$
\mathbf{f}_{tip} = \left( \begin{matrix} 2 \\ 0 \\ 0 \end{matrix} \right),
$$

$$
x_e = \cos\left(\theta_1\right) + \cos\left(\theta_1+\theta_2\right) + \cos\left(\theta_1+\theta_2+\theta_3\right),
$$

$$
y_e = \sin\left(\theta_1\right) + \sin\left(\theta_1+\theta_2\right) + \sin\left(\theta_1+\theta_2+\theta_3\right),
$$

$$
\phi_e = \theta_1 + \theta_2 + \theta_3,
$$

$$
\theta_1 = \theta_3 = 0; \; \theta_2 = \pi/4,
$$

$$
\mathbf{\tau} = \left( \begin{matrix} \tau_1 \\ \tau_2 \\ \tau_3 \end{matrix} \right) = \mathbf{J}^T \cdot \mathbf{f}_{tip} = \left( \begin{matrix} 2\frac{\partial x_e}{\partial \theta_1} \\ 2\frac{\partial x_e}{\partial \theta_2} \\ 2\frac{\partial x_e}{\partial \theta_3} \end{matrix} \right) = -\left( \begin{matrix} 2\sqrt{2} \\ 2\sqrt{2} \\ \sqrt{2} \end{matrix} \right).
$$


问:
Quadrocopter first build: how to tell if components play well together?
I'm building my first quadrocopter, and I'm trying to come up with a parts list that is suitable for a first build.

I will use this to learn how to fly a quadrocopter manually (lots of crashes!), and to do some experiments with running AI for piloting it.

A couple questions about the below list of parts:

Is this a good choice for a first build? Are we missing any crucial parts?

Do these components work together? Is this battery strong enough to fuel all the components that need power?

Here's the current list of parts:

Frame - 450 mm

Propellers - 10x4.5", two pairs

Motor (4x) - 900kv brushless outrunner motor; max current: 18A; ESC: 25-30A; cell count:3s-4s lipoly

Electronic speed controllers (4x) - 20A constant current, 25A burst current; battery: 2-4S lipoly

Battery - 3300mAh lipoly, 11.1v, 3 cell; constant discharge: 30C, peak discharge: 40C. charge plug: JST-XH. 3300 mAh x 30C = 99 amps?

Charger - lipoly, 50W, 6A, 12v power supply

Power supply - input: AC 100-240v 50/60Hz; output: DC15v 5A

Arduino board

Gyroscope for arduino

Accelerometer for arduino

GPS sensor for arduino?

RC transmitter for arduino

RC controller

答:
I found myself in the same situation some time ago.

Keep your list. If you want to see if everything fits, well I'm going to tell you that they won't. Only if there's a miracle. Start learning and designing in SolidWorks. This software gives you the ability to test and fail until everything works. You can simulate basically everything, from weather in diverse regions to how an alloy reacts to pressure. You can even simulate how your code works on your quadcopter by creating a virtual quadcopter.

As for tutorial, I can tell you that you have all the good documentation on their website. If you have a confusion, google and youtube is your best friend. Oh, and don't forget stackexchange.com.

Since time must not rush you, take your time, and be meticulous. Start with an Arduino, but take it slow. Test your programming skills, and if they're not that good, read some tutorials about it. Implement this "algorithm" into your own life, and you'll find out that you can solve anything.

Keep in touch, mate.

By the way, we are both the same age. Well, I'm 17.

ContentLicense: CC BY-SA 3.0


问:
Are there any tutorials for transitioning from Gazebo Sim to Webots?
Are there any decent/recommended tutorials around for transitioning to webots from gazebo Sim? Or at least setting up existing ROS 2 robots in webots?

I got a bit sick of trying to get the latest version of Gazebo working with Ros 2 Humble properly (ros2_control didn't seem to want to work at all) so I decided to give Webots a try and I'm loving it so far. But I'm still trying to get my head around how it all goes together since it seems very different to how a robot is integrated using Gazebo. Particularly getting velocity controllers working so I can get my cmd_vels into the Webots sim.

I have most of the samples working, but most of them seem to have the robot constructed in Webots and just interfacing with ROS 2 rather than importing everything through the ROS 2 Xacro pathway.

Any recommendations for resources on this area of ROS 2 and Webots?

Many thanks in advance

答:
Yes, there are some resources available that can help you transition from Gazebo to Webots or set up existing ROS 2 robots in Webots.

Firstly, the official ROS 2 documentation has a tutorial on how to set up a basic Webots simulation with ROS 2, which can be found at https://docs.ros.org/en/rolling/Tutorials/Advanced/Simulators/Webots.html. This tutorial provides step-by-step instructions on how to set up a simple Webots simulation and interface it with ROS 2.

Additionally, the webots_ros2 package has several resources available that could be helpful. As you mentioned, there are some examples available that show how to use Webots with other ROS 2 packages like ros2_control, cartographer, etc. webots_ros2_universal_robot shows how to import your robot from a Xacro file and use it in the Webots simulation.

Moreover, the webots_ros2 wiki page contains explanations on the examples and how to use them. There are also more advanced tutorials that cover a range of topics, including how to set up an existing ROS 2 robot in Webots. These pages can be accessed at https://github.com/cyberbotics/webots_ros2/wiki.

We are currently working on moving these wiki pages to the official ROS 2 documentation for more visibility.

Disclaimer: I am a Webots developer working at Cyberbotics.


问:
ROS 2 Humble FastDDS Monitor
I struggle to use the eProsima FastDDS Monitor on Humble. I managed to make it work with Vulcanexus Docker image; however, if I follow the guide from 2022 Roscon presentation, I don't see any network traffic in the Monitor tool.

To summarize my setup:

Humble

Building fastdds from source with
colcon build --cmake-args -DFASTDDS_STATISTICS=on

Sourcing environments:
source /opt/ros/humble/setup.bas
source <path to fastdds_ws>/install/setup.bash

Enabling Statistics Module

export FASTDDS_STATISTICS="HISTORY_LATENCY_TOPIC;NETWORK_LATENCY_TOPIC; PUBLICATION_THROUGHPUT_TOPIC; SUBSCRIPTION_THROUGHPUT_TOPIC;RTPS_SENT_TOPIC;RTPS_LOST_TOPIC;HEARTBEAT_COUNT_TOPIC; ACKNACK_COUNT_TOPIC;NACKFRAG_COUNT_TOPIC;GAP_COUNT_TOPIC;DATA_COUNT_TOPIC;RESENT_DATAS_TOPIC; SAMPLE_DATAS_TOPIC;PDP_PACKETS_TOPIC;EDP_PACKETS_TOPIC;DISCOVERY_TOPIC;PHYSICAL_DATA_TOPIC"

Running ros2 run demo_nodes_cpp talker node and the Fast DDS Monitor in a different tab.

The difference in the Monitor's behavior is while I can list the connected Entities, there's no traffic in the Statistics tab, and I don't see any device under the Physical tab. This, in my opinion, indicated that the talker was not, in fact, launched with the statistics enabled. Did someone succeed to launch Fast DDS Monitor with Humble?

答: So the problem was related to the eProsima/Fast-DDS version. After rolling back to v2.6.2, which is mentioned in the Roscon presentation, I got the expected behavior.</p>

Title: ROS 2 Humble FastDDS Monitor


问:
Where should I write and call GPIO port connection in the hardware interface in ros2_control for control of robot movement on Raspberry Pi 4?
I am using ROS 2 Humble on Raspberry Pi 4(Ubuntu 22.04 OS).

I am trying to build 2-wheeled diff-drive mobile robot and using ros2_control for controlling, but I'm not getting where should I write GPIO port connections part.

I am trying to control movement through Raspberry Pi GPIO pins using ros2_control. I have found many examples but with Raspberry Pi and Arduino serial connection not with only Raspberry Pi GPIO pins and L298N motor driver.

I'm not asking for code but where should it be written and whether it can be velocity controlled or not.

答:
https://github.com/ros-mobile-robots/diffbot

This code has the help you need. The Raspi can directly drive the Grove motor controller. It works very well.


问:
Is the angular velocity vector the derivative of a time-varying quantity?
On page 111 (section 4.6) of Robot Modeling and Control (Second Edition) by Spong, Hutchinson and Viyasagar, the authors define a "body velocity" vector $\xi$ of the end-effector as follows:

$\xi = \begin {bmatrix} v_n^0 \\ \omega_n^0 \end{bmatrix}$

where $\omega_n^0$ and $v_n^0$ both belong to $\mathbb{R^3}$. (This is in the context of a derivation of the Jacobian.)  It is then stated:

"Note that this velocity vector is not the derivative of a position variable, since the angular velocity vector is not the derivative of any particular time-varying quantity."

I don't understand the statement.  Why isn't the angular velocity vector the derivative of a time-varying quantity?  In particular, why isn't $\omega_n^0$ the derivative of the end-effector's orientation with respect to the basis vectors of the base frame?

答:
1: The first question you should ask, is: how do we describe the orientation of a rigid body in 3d space?

Using rotation matrices R

Using angle-axis representation

Using euler angles (with a particular convention, ex. ZYX)

Using quaternions

We do not describe it with "the angle of the end-effector's position with respect to the basis vectors of the base frame". (Also i think you mean the angle of the of the frame (coordinate system) of the end effector with respect to the basis frame, using for example angle-axis representation).

2: $\omega_n^0$ is the instantaneous angular velocity of the body, expresed the base frame. That is to say:

$$ \omega_n^0 = \frac{d \theta}{dt} k^0$$

where $k^0$ is the instantaneous axis of rotation. As you can see $\omega_n^0$
is not the derivative of any of the previous ways of representing orientation.

Extra There are two jacobians, the geometric and the analytic. The analytic jacobian is:

$$ \begin{bmatrix} u_n^0 \\ \dot{\theta}_r \end{bmatrix}  = J_A(q,representation) \dot{q} $$

Here  $\dot{\theta}_r$ is the derivate of the above representations.


问:
Is it possible to set up intra process communications b/w 1 publisher and multiple subscribers?
I was reading this tutorial: https://docs.ros.org/en/humble/Tutorials/Demos/Intra-Process-Communication.html

Is it possible to have multiple subscribers to the published message? How does the unique pointers work then. I assume it isn't because then there would be multiple unique pointers to the same message. If it is possible is there any examples showcasing it?

答:
If you have multiple subscriptions which each require a unique pointer the data will be copied the requisite number of times to give the subscribers each unique pointers.

If you want to have highly optimized transfer of data to multiple subscribers you can use const shared_ptr in your subscription which will allow the same pointer to be accessed by multiple subscribers, but with the caveat that it's read only. There's more on that near the end of the page referenced.


问:
Robotic arm servo motor- Not enough torque
I require your help regarding a problem I’m encountering.

I am a beginner in robot modelling. I am designing a robotic arm for agricultural use and I am having issues with the motors. I am using Maxon motors however the calculated load torque (including arm weight is larger than stall torque of all the motors within the Maxon catalog).

The robot arm is approximately 8 kgs and is lifting a weight of 12 grams (reach=1 m).

Does anyone know why there may be an issue and if there are any possible solutions?

Will adding another motor in the base half the loads that are applied to each joint? Or should I use gears to increase the output torque?

答:
You almost always need some type of transmission between the motor and the joint. This is often a set of gears or a timing belt with 2 different sized toothed wheels. In some case it maybe a planetary gear of cycloidal transmission.

Adding a transmission allows you to use smaller motor and to get more precision on your encoder feedback. The downside is that it makes the joint slower.

Also keep in mind that for agricultural use, the arm will probably need to be sealed so that it can be washed off to keep it clean.


答:
As far as I can tell, the phrase

Note that this velocity vector is not the derivative of a position variable, since the angular velocity vector is not the derivative of any particular time-varying quantity.

is referring to the fact that you do not directly integrate the angular velocity vector back into some variable that represents the current orientation. For example, when you have the position derivative $\dot{x}(t)$, we know the position $x(t)$ can be found simply from using the equation

$$ x(t) = \int_{0}^{t}\dot{x}(\tau) d\tau $$

While a similar concept can be applied to a subset of rotations represented using the axis-angle representation, it does not hold universally. For example, consider a rotation about the x-axis with a magnitude of $2\pi$ radians followed by a rotation about the y-axis with a magnitude of $\pi$ radians. For the first rotation, we can directly integrate the angular velocity to produce its axis-angle representation, $\left[ 2\pi, 0, 0  \right]$. Meanwhile, directly integrating the second rotation would give you the axis-angle value of $\left[ 2\pi, \pi, 0  \right]$. Conceptually, we can see the final result of this example should be a $\pi$ rotation about the y-axis as a $2\pi$ rotation about any axis will return to the original orientation. So, let's consider the rotation matrix derived from the computed axis-angle values as well as the rotation matrix produced from the y-axis rotation alone.

So, the rotation matrix produced from the axis-angle representation is
$$ \mathbf{R}_{\omega} \approx \left[  \begin{array}{ccc} 0.95 & 0.11 & 0.30 \\ 0.11 & 0.79 & -0.60 \\ -0.30 & 0.60 & 0.74 \end{array}  \right] $$

while the y-axis rotation matrix is
$$ \mathbf{R}_{y} = \left[  \begin{array}{ccc} -1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & -1 \end{array}  \right]  $$

Thus, simply integrating the angular velocities will not produce a meaningful representation of orientation.

Now, personally I disagree with saying the angular velocity is "not the derivative of any particular time-varying quantity". It is well-known that the time-derivative of a rotation matrix can be solved for by using the angular velocity (here), defined as follows

$$ \dot{{}_{a}\mathbf{R}_{b}} = {}_{a}\mathbf{R}_{b} [\omega]_{\times} $$

where ${}_{a}\mathbf{R}_{b}$ is the rotation matrix relating frame $b$ to frame $a$ and $[\omega]_{\times}$ is the skew-symmetric matrix formed from the angular velocity vector $\omega$. To relate this to robotics, the rotation matrix relating the end-effector frame to the world frame has a clear physical representation. Each of its columns represent the current values of the end-effector's x-axis, y-axis, and z-axis as represented in the world frame. So, the time derivative of this matrix represents how these values are going to change over time, which sounds an awfully lot like a time-varying quantity to me. So, it seems that the only chance this statement has at being correct would be if it is meaning that each component of the angular velocity vector does not correspond to a single orientation variable.

Title: Is the angular velocity vector the derivative of a time-varying quantity?

Body:
On page 111 (section 4.6) of Robot Modeling and Control (Second Edition) by Spong, Hutchinson and Viyasagar, the authors define a "body velocity" vector $\xi$ of the end-effector as follows:

$\xi = \begin {bmatrix} v_n^0 \\ \omega_n^0 \end{bmatrix}$

where $\omega_n^0$ and $v_n^0$ both belong to $\mathbb{R^3}$. (This is in the context of a derivation of the Jacobian.)  It is then stated:

"Note that this velocity vector is not the derivative of a position variable, since the angular velocity vector is not the derivative of any particular time-varying quantity."

I don't understand the statement.  Why isn't the angular velocity vector the derivative of a time-varying quantity?  In particular, why isn't $\omega_n^0$ the derivative of the end-effector's orientation with respect to the basis vectors of the base frame?


问:
How are Interference Avoidance and Collision Avoidance different?
Someone told me when explaining about a controller module named CollisionDetector that it only checks self-interference and moves accordingly without detecting collision. To me both sounds the same. How are they different?

答:
One is internal, one is external.

Self-interference refers to instances where something like a robot arm (with many degrees of freedom) may attempt to move in a path that crosses part of its own body.  Your CollisionDetector is likely keeping track of the joint angles in a planned arm movement and seeing if any of them result in such a condition.  The robot doesn't need any information about its environment to do this, just a reliable measurement of its own position (and possibly the shape of whatever it may be gripping).

"Collision Avoidance" usually refers to the detection of transient objects with externally-facing sensors.  For example, a robot has planned a path based on a map of a room but other robots (or people) might be moving around in that same space; the robot detects them with some sort of sensor, and adjusts its planned path (or just stops) until the risk of collision has gone away.  This is usually more difficult than detecting self-interference, because modeling the external environment is a bit more complicated than modeling a robot's internal state.


问:
URScript - how to get the actual TCP pose in tool space coordinate system?
I am writing a simple script for universal robots UR10 robotic arm.

I am trying to find a way to to see if the tool current position is outside of a 3D bounding box. the 3D bounding box is defined in the coordinate system of the tool. (y is up, x right, z backwards).

The get_actual_tcp_pose() function returns the tool pose in the 'base frame' coordinate system. it is my understanding that this is the coordinate system where the origin is at the base of the robotic arm.

So my questions are:

How do I get the actual tcp pose in the TCP coordinate system (tool space)?

Alternatively, how do I convert the pose returned by get_actual_tcp_pose() to the cooridnate system of the TCP using URScript?

答: The actual TCP pose in TCP coordinate system will always be [0,0,0,0,0,0] because the TCP Coordinate system is defined in the current tool orientation.</p>


问:
How do I make a robot imported using urdf and ROS2 gravity? It just floats
I can't seem to find any examples with imported URDFs (the universal robot examples don't seem to have any physics settings beyond joint inertias etc).

My robot has mass from the urdf:

But it seems to just float:

If I manually add physics in webots (by right clicking on physics and adding a physics node) it falls as expected but the wheels fall off (despite still moving around with the controllers).

While amusing, this isn't exactly what I'd like it to do. Is there a physics tag or something I might be missing in the urdf?

These are the only webots sections I have in the urdf at the moment because it's all I could find reference to in the examples.

```<code>  <webots>
    <plugin type="webots_ros2_control::Ros2Control"/>
  </webots>

  <ros2_control name="WebotsControl" type="system">
    <hardware>
        <plugin>webots_ros2_control::Ros2ControlSystem</plugin>
    </hardware>

    <joint name="left_wheel_joint">
        <command_interface name="velocity">
          </command_interface>
        <state_interface name="position"/>
    </joint>
    <joint name="right_wheel_joint">
        <state_interface name="position"/>
        <command_interface name="velocity"/>
    </joint>
  </ros2_control>
</code>```

Edit:
This is the full urdf (I'll be generating it from a xacro eventually but I'm using just a single exported urdf at the moment to get the basics working before I complicated things). It's based on Josh's ROS 2 tutorials on his Articulated Robotics channel.

```<code><?xml version="1.0" ?>
<!-- =================================================================================== -->
<!-- |    This document was autogenerated by xacro from robot.urdf.xacro               | -->
<!-- |    EDITING THIS FILE BY HAND IS NOT RECOMMENDED                                 | -->
<!-- =================================================================================== -->
<robot name="articubot_one">

  <!-- BASE LINK -->
  <link name="base_link" />
  <!-- BASE_FOOTPRINT LINK -->
  <joint name="base_footprint_joint" type="fixed">
    <parent link="base_link"/>
    <child link="base_footprint"/>
    <origin rpy="0 0 0" xyz="0 0 0"/>
  </joint>
  <link name="base_footprint">
    </link>
  <!-- CHASSIS LINK -->
  <joint name="chassis_joint" type="fixed">
    <parent link="base_link"/>
    <child link="chassis"/>
    <origin xyz="-0.226 0 -0.01"/>
  </joint>
  <link name="chassis">
    <visual>
      <origin xyz="0.1675 0 0.069"/>
      <geometry>
        <box size="0.335 0.265 0.138"/>
      </geometry>
      <material name="orange"/>
    </visual>
    <collision>
      <origin xyz="0.1675 0 0.069"/>
      <geometry>
        <box size="0.335 0.265 0.138"/>
      </geometry>
    </collision>
    <inertial>
      <origin rpy="0 0 0" xyz="0.1675 0 0.069"/>
      <mass value="0.5"/>
      <inertia ixx="0.003719541666666667" ixy="0.0" ixz="0.0" iyy="0.005469541666666668" iyz="0.0" izz="0.007602083333333334"/>
    </inertial>
  </link>
  <!-- LEFT WHEEL LINK -->
  <joint name="left_wheel_joint" type="continuous">
    <parent link="base_link"/>
    <child link="left_wheel"/>
    <origin rpy="-1.5707963267948966 0 0" xyz="0 0.1485 0"/>
    <axis xyz="0 0 1"/>
  </joint>
  <link name="left_wheel">
    <visual>
      <geometry>
        <cylinder length="0.026" radius="0.033"/>
      </geometry>
      <material name="blue"/>
    </visual>
    <collision>
      <geometry>
        <sphere radius="0.033"/>
      </geometry>
    </collision>
    <inertial>
      <origin rpy="0 0 0" xyz="0 0 0"/>
      <mass value="0.05"/>
      <inertia ixx="1.642916666666667e-05" ixy="0.0" ixz="0.0" iyy="1.642916666666667e-05" iyz="0.0" izz="2.7225000000000004e-05"/>
    </inertial>
  </link>

  <!-- RIGHT WHEEL LINK -->
  <joint name="right_wheel_joint" type="continuous">
    <parent link="base_link"/>
    <child link="right_wheel"/>
    <origin rpy="1.5707963267948966 0 0" xyz="0 -0.1485 0"/>
    <axis xyz="0 0 -1"/>
  </joint>
  <link name="right_wheel">
    <visual>
      <geometry>
        <cylinder length="0.026" radius="0.033"/>
      </geometry>
      <material name="blue"/>
    </visual>
    <collision>
      <geometry>
        <sphere radius="0.033"/>
      </geometry>
    </collision>
    <inertial>
      <origin rpy="0 0 0" xyz="0 0 0"/>
      <mass value="0.05"/>
      <inertia ixx="1.642916666666667e-05" ixy="0.0" ixz="0.0" iyy="1.642916666666667e-05" iyz="0.0" izz="2.7225000000000004e-05"/>
    </inertial>
  </link>

  <!-- CASTER WHEEL LINK -->
  <joint name="caster_wheel_joint" type="fixed">
    <parent link="chassis"/>
    <child link="caster_wheel"/>
    <origin xyz="0.075 0 -0.013"/>
  </joint>
  <link name="caster_wheel">
    <visual>
      <geometry>
        <sphere radius="0.01"/>
      </geometry>
      <material name="white"/>
    </visual>
    <collision>
      <geometry>
        <sphere radius="0.01"/>
      </geometry>
    </collision>
    <inertial>
      <origin rpy="0 0 0" xyz="0 0 0"/>
      <mass value="0.01"/>
      <inertia ixx="4.0000000000000003e-07" ixy="0.0" ixz="0.0" iyy="4.0000000000000003e-07" iyz="0.0" izz="4.0000000000000003e-07"/>
    </inertial>
  </link>

  <webots>
    <plugin type="webots_ros2_control::Ros2Control"/>
  </webots>

  <ros2_control name="WebotsControl" type="system">
    <hardware>
        <plugin>webots_ros2_control::Ros2ControlSystem</plugin>
    </hardware>

    <joint name="left_wheel_joint">
        <command_interface name="velocity">
          </command_interface>
        <state_interface name="position"/>
    </joint>
    <joint name="right_wheel_joint">
        <state_interface name="position"/>
        <command_interface name="velocity"/>
    </joint>
  </ros2_control>
</robot>
</code>```

Any thoughts would be appreciated.

Thanks

答:
I see you have a <joint>  for "left_wheel_joint" and "right_wheel_joint", but what I'm not seeing are parent or child links. I'm also not seeing the joint type. All of these (type/parent/child) are required for a valid joint definition. From the documentation, the smallest possible joint definition you could use is the one that specifies only the required fields, which would look like the following:

```<code> <joint name="left_wheel_joint" type="revolute">
    <parent link="body"/>
    <child link="left_wheel"/>
 </joint>
</code>```

When I look back at your question, I'm wondering if you've given us the full URDF, or a plugin definition, or something else? I'm not seeing definitions for the body, caster, or wheels.

Body:
I see you have a <joint>  for "left_wheel_joint" and "right_wheel_joint", but what I'm not seeing are parent or child links. I'm also not seeing the joint type. All of these (type/parent/child) are required for a valid joint definition. From the documentation, the smallest possible joint definition you could use is the one that specifies only the required fields, which would look like the following:

 <joint name="left_wheel_joint" type="revolute">
    <parent link="body"/>
    <child link="left_wheel"/>
 </joint>

When I look back at your question, I'm wondering if you've given us the full URDF, or a plugin definition, or something else? I'm not seeing definitions for the body, caster, or wheels.


答:
You can start by checking the e-puck URDF. It can be a good source of inspiration. The problem may come from the conversion of the URDF, which is not creating any physics for the whole robot node. One possible solution is to remove the chassis link and place its visual, collision and inertial tags in the base_link instead.

The converter will automatically create a child for the visual but will use the collision and inertial tags to define the BoundingObject and Physics of the Robot.

In addition, you should change the collision tag of the wheels to a cylinder instead of a sphere. origin tags should obviously be adapted to keep the initial design when applying those modifications.

I haven't tested to adapt the whole URDF but my suggested changes above are removing the problem of gravity and "detached" wheels.

Disclaimer: I am a Webots developer working at Cyberbotics.

Title: How do I make a robot imported using urdf and ROS2 gravity? It just floats

Body:
I can't seem to find any examples with imported URDFs (the universal robot examples don't seem to have any physics settings beyond joint inertias etc).

My robot has mass from the urdf:

But it seems to just float:

If I manually add physics in webots (by right clicking on physics and adding a physics node) it falls as expected but the wheels fall off (despite still moving around with the controllers).

While amusing, this isn't exactly what I'd like it to do. Is there a physics tag or something I might be missing in the urdf?

These are the only webots sections I have in the urdf at the moment because it's all I could find reference to in the examples.

```<code>  <webots>
    <plugin type="webots_ros2_control::Ros2Control"/>
  </webots>

  <ros2_control name="WebotsControl" type="system">
    <hardware>
        <plugin>webots_ros2_control::Ros2ControlSystem</plugin>
    </hardware>

    <joint name="left_wheel_joint">
        <command_interface name="velocity">
          </command_interface>
        <state_interface name="position"/>
    </joint>
    <joint name="right_wheel_joint">
        <state_interface name="position"/>
        <command_interface name="velocity"/>
    </joint>
  </ros2_control>
</code>```

Edit:
This is the full urdf (I'll be generating it from a xacro eventually but I'm using just a single exported urdf at the moment to get the basics working before I complicated things). It's based on Josh's ROS 2 tutorials on his Articulated Robotics channel.

```<code><?xml version="1.0" ?>
<!-- =================================================================================== -->
<!-- |    This document was autogenerated by xacro from robot.urdf.xacro               | -->
<!-- |    EDITING THIS FILE BY HAND IS NOT RECOMMENDED                                 | -->
<!-- =================================================================================== -->
<robot name="articubot_one">

  <!-- BASE LINK -->
  <link name="base_link" />
  <!-- BASE_FOOTPRINT LINK -->
  <joint name="base_footprint_joint" type="fixed">
    <parent link="base_link"/>
    <child link="base_footprint"/>
    <origin rpy="0 0 0" xyz="0 0 0"/>
  </joint>
  <link name="base_footprint">
    </link>
  <!-- CHASSIS LINK -->
  <joint name="chassis_joint" type="fixed">
    <parent link="base_link"/>
    <child link="chassis"/>
    <origin xyz="-0.226 0 -0.01"/>
  </joint>
  <link name="chassis">
    <visual>
      <origin xyz="0.1675 0 0.069"/>
      <geometry>
        <box size="0.335 0.265 0.138"/>
      </geometry>
      <material name="orange"/>
    </visual>
    <collision>
      <origin xyz="0.1675 0 0.069"/>
      <geometry>
        <box size="0.335 0.265 0.138"/>
      </geometry>
    </collision>
    <inertial>
      <origin rpy="0 0 0" xyz="0.1675 0 0.069"/>
      <mass value="0.5"/>
      <inertia ixx="0.003719541666666667" ixy="0.0" ixz="0.0" iyy="0.005469541666666668" iyz="0.0" izz="0.007602083333333334"/>
    </inertial>
  </link>
  <!-- LEFT WHEEL LINK -->
  <joint name="left_wheel_joint" type="continuous">
    <parent link="base_link"/>
    <child link="left_wheel"/>
    <origin rpy="-1.5707963267948966 0 0" xyz="0 0.1485 0"/>
    <axis xyz="0 0 1"/>
  </joint>
  <link name="left_wheel">
    <visual>
      <geometry>
        <cylinder length="0.026" radius="0.033"/>
      </geometry>
      <material name="blue"/>
    </visual>
    <collision>
      <geometry>
        <sphere radius="0.033"/>
      </geometry>
    </collision>
    <inertial>
      <origin rpy="0 0 0" xyz="0 0 0"/>
      <mass value="0.05"/>
      <inertia ixx="1.642916666666667e-05" ixy="0.0" ixz="0.0" iyy="1.642916666666667e-05" iyz="0.0" izz="2.7225000000000004e-05"/>
    </inertial>
  </link>

  <!-- RIGHT WHEEL LINK -->
  <joint name="right_wheel_joint" type="continuous">
    <parent link="base_link"/>
    <child link="right_wheel"/>
    <origin rpy="1.5707963267948966 0 0" xyz="0 -0.1485 0"/>
    <axis xyz="0 0 -1"/>
  </joint>
  <link name="right_wheel">
    <visual>
      <geometry>
        <cylinder length="0.026" radius="0.033"/>
      </geometry>
      <material name="blue"/>
    </visual>
    <collision>
      <geometry>
        <sphere radius="0.033"/>
      </geometry>
    </collision>
    <inertial>
      <origin rpy="0 0 0" xyz="0 0 0"/>
      <mass value="0.05"/>
      <inertia ixx="1.642916666666667e-05" ixy="0.0" ixz="0.0" iyy="1.642916666666667e-05" iyz="0.0" izz="2.7225000000000004e-05"/>
    </inertial>
  </link>

  <!-- CASTER WHEEL LINK -->
  <joint name="caster_wheel_joint" type="fixed">
    <parent link="chassis"/>
    <child link="caster_wheel"/>
    <origin xyz="0.075 0 -0.013"/>
  </joint>
  <link name="caster_wheel">
    <visual>
      <geometry>
        <sphere radius="0.01"/>
      </geometry>
      <material name="white"/>
    </visual>
    <collision>
      <geometry>
        <sphere radius="0.01"/>
      </geometry>
    </collision>
    <inertial>
      <origin rpy="0 0 0" xyz="0 0 0"/>
      <mass value="0.01"/>
      <inertia ixx="4.0000000000000003e-07" ixy="0.0" ixz="0.0" iyy="4.0000000000000003e-07" iyz="0.0" izz="4.0000000000000003e-07"/>
    </inertial>
  </link>

  <webots>
    <plugin type="webots_ros2_control::Ros2Control"/>
  </webots>

  <ros2_control name="WebotsControl" type="system">
    <hardware>
        <plugin>webots_ros2_control::Ros2ControlSystem</plugin>
    </hardware>

    <joint name="left_wheel_joint">
        <command_interface name="velocity">
          </command_interface>
        <state_interface name="position"/>
    </joint>
    <joint name="right_wheel_joint">
        <state_interface name="position"/>
        <command_interface name="velocity"/>
    </joint>
  </ros2_control>
</robot>
</code>```

Any thoughts would be appreciated.

Thanks


问:
Nav2 makes obstacles where there are none
I'm using Jammy and Humble and Nav2. The robot is beginning to do waypoint following and driving on his own. However, sometimes the Nav2 program is making black dots, as obstacles, appear where there were none on the map provided. The area was clean white. The floor is carpet, and apparently the laser is seeing something? It's a Velodyne puck, and I understand only one scan laser is in use in Nav2, of the 16 in the unit. Is there a setting I can adjust to stop the mapping/navigation from finding and developing these obstacles in robot's way?</p>

答:
check your sensor outputs for noise. Things don't just appear without reason. It might be necessary for your to lightly filter the output of your sensor data if you're noticing erroneous measurements that are causing a problem. The laser filters package might be useful for you to look into and are commonly used to model and remove common sources of laser scanner noise.

http://wiki.ros.org/laser_filters


问:
Gravity compensation
I am just getting curious about this gravity compensation technique.
If we could compensate the force generated by the gravity (by feeding in the exact amount of force into the opposite direction), will the mass of the robot be 0 kg?

Could we then just swing a 1000kg robot arm with our hand?

答:
I'm afraid not, actually. Even if you have a perfect friction compensation and a perfect gravity compensation, you still need to deal with inertia. It will be extremely hard to swing it in arbitrary direction due to large inertia (and Coriolis and centrifugal forces, if your robot arm is multi-dof system).

Using equations, a generic manipulator equations of motion is given as:

$$M(q)q"+C(q,q')q'+g(q)+tau_{fric}=u_motor + u_{user}$$

Suppose perfect gravity/friction compensator, i.e., $u_{motor} = g(q) + tau_{fric}$. You are left with

$$M(q)q"+C(q,q')q'=u_{user}$$

To generate arbitrary motion, i.e., arbitrary $q(t)$, you need sufficient amount of effort to overcome inertia $M(q)$ and Coriolis/centrifugal $C(q,q')$, both of which are approximately proportional to mass.

Title: Gravity compensation


问:
The choice of using quaternions and using gyro & accel separately in EKF
I am working on realising the self-navigation of a vehicle.

I have already written an extended Kalman filter with a state vector using position, velocity, Euler angle, acceleration, and angular velocity. However, I have recently read alternative papers using quaternions as a whole to represent the orientation of the body.

Are there any differences between using quaternions and using acceleration and angular velocity individually in the state vector? If there are, what is the advantage of doing that?

答:
Quaternions offers 2 advantages.  It mitigates the risk of gimbal lock and the math is easier for computers to handle than trig functions.  Look for "Advantages of quaternions" in this wikipedia page.

Your question "Are there any differences between using quaternions and using acceleration and angular velocity ..." is confusing.  You are using the accelerometer (acceleration) and gyroscope (angular velocity) now.  And still will be if you change your math from using (it is assumed) trigonometry functions to using quaternions.


问:
What should I study if I want to get into robotics?
I understand this is a broad question but I'm taking the risk to ask anyway.  Robotics, from what I can tell so far, is a detailed, diverse, and thorough field. However, if there are better areas of research to invest time into, what would those areas be?</p>

答:
Arduino really helped me get started. Tons of support and great products these days.

Parallax is another good company offering great starter kits.
PBasic is a good starter programing language which runs on the Basic Stamp. The Activity Robot Kit was very useful for me.


问:
Webots - Copy Paste a Robot
In Webots: I want to do a Predator/Prey simulation and need to spawn the exact same robot when an event occurs. How do I copy/paste a robot I have in my world scene tree. I build it my self therefore I can not use a Webots PROTO. When I use the "Import EXTERNPROTO" function only my TexturedBackground and my Arena node are visible in my world file. They appear purple and the other nodes in the scene tree are green.</p>

答:
You should probably turn your robot into a PROTO file, store it into your local protos folder and add it to the list of Importable EXTERNPROTO. This way, your supervisor process will be able to spawn it dynamically in the simulation by using the wb_supervisor_field_import_mf_node_from_string function. This tutorial explains in details how to proceed.

Disclaimer: I am a Webots developer working at Cyberbotics.

Title: Webots - Copy Paste a Robot


问:
How to convert Gazebo SDF worlds to Webots?
We are in the process of moving our warehouse simulation from Gazebo to Webots. We would like to set up a "realistic" warehouse environment in Webots. The factory sample already provides a lot of props for this, but we have not yet found warehouse shelf models for Webots.

One option would be to convert the AWS RoboMaker worlds from SDF to Webots: https://github.com/aws-robotics/aws-robomaker-small-warehouse-world

Is there a tool to make this conversion, or do we have to do it manually?

If no automated solution is available, what is the best approach to import the models manually?

答:
Although not automatic, it should be pretty straightforward to re-use the shelf object from this AWS RoboMaker world by simply re-using its meshes to create a Shelf.proto file in your local protos folder:

#VRML_SIM R2023a utf8
# A shelf.

PROTO Shelf [
  field SFVec3f    translation 0 0 0
  field SFRotation rotation    0 0 1 0
  field SFString   name        "shelf"
  field SFBool     locked      FALSE            # Is `Solid.locked`.
]
{
  Solid {
    translation IS translation
    rotation IS rotation
    children [
      CadShape {
        url "https://raw.githubusercontent.com/aws-robotics/aws-robomaker-small-warehouse-world/ros1/models/aws_robomaker_warehouse_ShelfD_01/meshes/aws_robomaker_warehouse_ShelfD_01_visual.DAE"
      }
    ]
    name IS name
    model "shelf"
    boundingObject Mesh {
      url "https://raw.githubusercontent.com/aws-robotics/aws-robomaker-small-warehouse-world/ros1/models/aws_robomaker_warehouse_ShelfD_01/meshes/aws_robomaker_warehouse_ShelfD_01_collision.DAE"
    }
    locked IS locked
  }
}
```
<p>Here is what it looks like in Webots:
<img src="https://i.stack.imgur.com/umt8M.png" alt="Shelf.proto" />
Here is the <code>sample.wbt</code> world file showing it in Webots:</p>
<pre class="lang-javascript prettyprint-override"><code>#VRML_SIM R2023a utf8

EXTERNPROTO "webots://projects/objects/backgrounds/protos/TexturedBackground.proto"
EXTERNPROTO "webots://projects/objects/backgrounds/protos/TexturedBackgroundLight.proto"
EXTERNPROTO "../protos/Shelf.proto"

WorldInfo {
}
Viewpoint {
  orientation -0.11384659601330234 -0.3187749829101217 0.9409683644240309 5.557715208500585
  position -5.776529177279546 4.724710358949437 2.980453565305262
}
TexturedBackground {
}
TexturedBackgroundLight {
}
Shelf {
  rotation 0 0 1 1.5708003061004252
}
</code>```

You can also view it in 3D online on webots.cloud.

Note: Using meshes for the bounding object is not optimal, especially in this case where the bounding object could be replaced with a compound object made up of simple boxes, e.g., using a Group node that contains a series of Transform nodes containing a Box node in their Shape node.

Disclaimer: I am a Webots developer working at Cyberbotics.

Body:
Although not automatic, it should be pretty straightforward to re-use the shelf object from this AWS RoboMaker world by simply re-using its meshes to create a Shelf.proto file in your local protos folder:

#VRML_SIM R2023a utf8
# A shelf.

PROTO Shelf [
  field SFVec3f    translation 0 0 0
  field SFRotation rotation    0 0 1 0
  field SFString   name        "shelf"
  field SFBool     locked      FALSE            # Is `Solid.locked`.
]
{
  Solid {
    translation IS translation
    rotation IS rotation
    children [
      CadShape {
        url "https://raw.githubusercontent.com/aws-robotics/aws-robomaker-small-warehouse-world/ros1/models/aws_robomaker_warehouse_ShelfD_01/meshes/aws_robomaker_warehouse_ShelfD_01_visual.DAE"
      }
    ]
    name IS name
    model "shelf"
    boundingObject Mesh {
      url "https://raw.githubusercontent.com/aws-robotics/aws-robomaker-small-warehouse-world/ros1/models/aws_robomaker_warehouse_ShelfD_01/meshes/aws_robomaker_warehouse_ShelfD_01_collision.DAE"
    }
    locked IS locked
  }
}

Here is what it looks like in Webots:

Here is the sample.wbt world file showing it in Webots:

#VRML_SIM R2023a utf8

EXTERNPROTO "webots://projects/objects/backgrounds/protos/TexturedBackground.proto"
EXTERNPROTO "webots://projects/objects/backgrounds/protos/TexturedBackgroundLight.proto"
EXTERNPROTO "../protos/Shelf.proto"

WorldInfo {
}
Viewpoint {
  orientation -0.11384659601330234 -0.3187749829101217 0.9409683644240309 5.557715208500585
  position -5.776529177279546 4.724710358949437 2.980453565305262
}
TexturedBackground {
}
TexturedBackgroundLight {
}
Shelf {
  rotation 0 0 1 1.5708003061004252
}

You can also view it in 3D online on webots.cloud.

Note: Using meshes for the bounding object is not optimal, especially in this case where the bounding object could be replaced with a compound object made up of simple boxes, e.g., using a Group node that contains a series of Transform nodes containing a Box node in their Shape node.

Disclaimer: I am a Webots developer working at Cyberbotics.


问:
SLAM Toolbox Mapping Issue?
I am currently using ROS2 Humble and RP Lidar. I want to use SLAM with this so I am trying the Slam toolbox. So first I am doing: ros2 launch rplidar_ros rplidar.launch.py

Then in another terminal, I am doing: ros2 launch slam_toolbox online_async_launch.py

I don't have any urdf file, I just want to do static slam in RP lidar. I am getting the error:[async_slam_toolbox_node-1] [INFO] [1679982623.449307761] [slam_toolbox]: Message Filter dropping message: frame 'laser' at time 1679982623.312 for reason 'discarding message because the queue is full'

Please help me or guide to do SLAM. My rqt graph is also attached for more informationRQT GraphOutput

I am expecting to do slam or its related projects in which we do mapping using lidar and SLAM

答: You probably don't have the proper TF tree setup for this to work, so the node is telling you that its dropping data because it can't do anything with it. You need to provide laser scanner frame to base frame transforms and base frame to odometry frame transforms. This is covered well in documentation.</p>

Title: SLAM Toolbox Mapping Issue?


问:
What frequency does my quadcopter output-sense-calculate-output update loop need to stay stable?
With a 600 mm (2 foot) motor-to-motor quadcopter, what frequency does my output-sense-calculate-output update loop need to stay stable?

I'm estimating a total takeoff weight of very roughly 2 pounds ( 0.9 kg ),
which I expect to be mostly motors and batteries.

答:
As Rocketmagnet suggests, what frequency you "need" will depend on a lot of things. The more responsive your rotors are, the more sensitive your craft will be to random spikes in motor commands. These random spikes may be caused by noisy sensor readings caused by physical imperfections, which means you would need to lower your controller gains, which in turn might mean your quadrotor may become more unstable. Some other factors include the rotational inertias of the quadrotor, the propellers' blade pitch, the location of the center of mass, and the motor-to-motor distance.

I programmed a flight controller from scratch for my 2 kg tricopter running on an ATmega1280 and found that at:

50 Hz: It will stay in the air but is nigh impossible to control.

100 Hz: It will at least avoid immediately tipping to one side.

200 Hz: I can let it loose indoors at hover throttle and it will stay more or less in one spot.

It may be of interest to note that the higher the control frequency, the more effective your rotor inertias become at being physical dampers, which helps nullify IMU noise and improve flight stability.

But if I had to give a hard number for a minimum flight controller update frequency for a quadrotor of that size suitable for indoor navigation, based on personal experience...

I'd say 80 Hz.


问:
Robotic arm simulation in MikroC
I am supposed to control a robotic arm with a servo motor. The angle of rotation of the servo motor depends on the voltage of a potentiometer.

A0 can read analog inputs and C2 can hold a PWM signal.

Here is my setup:

And here is my code:

```<code>void main()
{
  int sensorReading;
  float x;

  TRISA = 0xFF;
  TRISC = 0x00;

  ADC_Init();
  PWM2_Init(3000);

  while(1)
  {
    sensorReading = ADC_Read(0);

    x = 500 + (sensorReading * 1500) / 1024;

    PWM2_Set_Duty(x/3000);
    PWM2_Start();
  }
}
</code>```

However my robotic arm (servo motor) doesn't move at all

I am using the MikroC IDE  and PIC18F452 as my microchip.

What am I doing wrong?

答:
:EDIT:

Here's (I think) the solution. For servo control, typically you would want a 50 Hz frequency. For that, you'd want

```<code>PWM2_Init(50);
</code>```

Then you'd want a range of values to use for the servo. Again, typically, it'd be 1000 to 2000 microseconds, but in your code it looks like maybe 500 to 2000 microseconds.

When I look at the manual, it's wanting a value from 0 to 255 for the duty cycle. The problem is that the duty cycle the manual refers to is for the full frame, but your application needs just a small subset of the frame.

Doing the math, if the carrier frequency is 50 Hz, then you have a frame width of 20 ms, or 20000 microseconds. Your band of operation is from 500 to 2000 microseconds, which means you want:

$$
\begin{array}{l}
\text{min_val} &=& (500/20000)*255 \\
\text{min_val} &=& 0.025*255 \\
\text{min_val} &=& 6.375 \\
\end{array}
$$
$$
\begin{array}{l}
\text{max_val} &=& (2000/20000)*255 \\
\text{max_val} &=& 0.1*255 \\
\text{max_val} &=& 25.5 \\
\end{array}
$$

You are expecting a value from 0 to 1023 on your sensor, and you need to map that range to 6.375 to 25.5, so you get:

$$
\begin{array}{l}
\text{pwm_command} &=& 6.375 + \left(\frac{25.5-6.375}{1023-0}\right)*\text{sensorReading} \\
\text{pwm_command} &=& 6.375 + 0.0187 * \text{sensorReading} \\
\end{array}
$$

Checking the math here:

Sensor reading of 0 gives 6.375. 6.375 divided by 255 gives 0.025, and multiplied by the frame width of 20 ms gives 500 microseconds

Sensor reading of 512 gives 15.95. 15.95 divided by 255 gives 0.06255, and multiplied by the frame width of 20 ms gives 1251 microseconds (halfway between min/max values)

Sensor reading of 1023 gives 25.5. 25.5 divided by 255 gives 0.1, and multiplied by the frame width of 20 ms gives 2000 microseconds.

So that should all work, except you are using a float for the command and it takes an unsigned short. The documentation at least makes no reference to allowing floats as inputs.

Does this work? I don't know. It depends on the servo you're using and how it handles out-of-bounds values. Some may vibrate/oscillate at values just beyond the acceptable ranges, some might bind, others could fail to respond.

Your safest bet would be to operate within the allowable limits there, meaning instead of trying to go to 6.375 as the minimum value, you go to the "safe" value of 7, because it's the first integer inside the [6.375, 25.5] range. Similarly, pick the maximum value to be 25, again because it's the last integer inside the range of values.

This also means that your neutral position of 15.95 isn't achievable, and you'll need to go for 16 instead. You're lucky that this is very very close to the calculated neutral position!

If I re-work the numbers with these values, I get:

$$
\begin{array}{l}
\text{pwm_command} &=& 7 + \left(\frac{25-7}{1023-0}\right)*\text{sensorReading} \\
\text{pwm_command} &=& 7 + 0.0176 * \text{sensorReading} \\
\end{array}
$$

Without writing out everything again, sanity check passes - A reading of 0 gives 7, 512 gives 16, and 1023 gives 25.

Putting this all together:

```<code>void main()
{
  int sensorReading;
  int x; // <--- New, was float, now it is int

  TRISA = 0xFF;
  TRISC = 0x00;

  ADC_Init();
  PWM2_Init(50); // <--- New, was 3000 Hz, now 50 Hz

  while(1)
  {
    sensorReading = ADC_Read(0);

    x = 7 + 0.0176 * sensorReading; // <--- new mapping

    PWM2_Set_Duty(x); // <--- no division here
    PWM2_Start();
  }
}
</code>```

Title: Robotic arm simulation in MikroC

Body:
:EDIT:

Here's (I think) the solution. For servo control, typically you would want a 50 Hz frequency. For that, you'd want

PWM2_Init(50);

Then you'd want a range of values to use for the servo. Again, typically, it'd be 1000 to 2000 microseconds, but in your code it looks like maybe 500 to 2000 microseconds.

When I look at the manual, it's wanting a value from 0 to 255 for the duty cycle. The problem is that the duty cycle the manual refers to is for the full frame, but your application needs just a small subset of the frame.

Doing the math, if the carrier frequency is 50 Hz, then you have a frame width of 20 ms, or 20000 microseconds. Your band of operation is from 500 to 2000 microseconds, which means you want:

$$
\begin{array}{l}
\text{min_val} &=& (500/20000)*255 \\
\text{min_val} &=& 0.025*255 \\
\text{min_val} &=& 6.375 \\
\end{array}
$$
$$
\begin{array}{l}
\text{max_val} &=& (2000/20000)*255 \\
\text{max_val} &=& 0.1*255 \\
\text{max_val} &=& 25.5 \\
\end{array}
$$

You are expecting a value from 0 to 1023 on your sensor, and you need to map that range to 6.375 to 25.5, so you get:

$$
\begin{array}{l}
\text{pwm_command} &=& 6.375 + \left(\frac{25.5-6.375}{1023-0}\right)*\text{sensorReading} \\
\text{pwm_command} &=& 6.375 + 0.0187 * \text{sensorReading} \\
\end{array}
$$

Checking the math here:

Sensor reading of 0 gives 6.375. 6.375 divided by 255 gives 0.025, and multiplied by the frame width of 20 ms gives 500 microseconds

Sensor reading of 512 gives 15.95. 15.95 divided by 255 gives 0.06255, and multiplied by the frame width of 20 ms gives 1251 microseconds (halfway between min/max values)

Sensor reading of 1023 gives 25.5. 25.5 divided by 255 gives 0.1, and multiplied by the frame width of 20 ms gives 2000 microseconds.

So that should all work, except you are using a float for the command and it takes an unsigned short. The documentation at least makes no reference to allowing floats as inputs.

Does this work? I don't know. It depends on the servo you're using and how it handles out-of-bounds values. Some may vibrate/oscillate at values just beyond the acceptable ranges, some might bind, others could fail to respond.

Your safest bet would be to operate within the allowable limits there, meaning instead of trying to go to 6.375 as the minimum value, you go to the "safe" value of 7, because it's the first integer inside the [6.375, 25.5] range. Similarly, pick the maximum value to be 25, again because it's the last integer inside the range of values.

This also means that your neutral position of 15.95 isn't achievable, and you'll need to go for 16 instead. You're lucky that this is very very close to the calculated neutral position!

If I re-work the numbers with these values, I get:

$$
\begin{array}{l}
\text{pwm_command} &=& 7 + \left(\frac{25-7}{1023-0}\right)*\text{sensorReading} \\
\text{pwm_command} &=& 7 + 0.0176 * \text{sensorReading} \\
\end{array}
$$

Without writing out everything again, sanity check passes - A reading of 0 gives 7, 512 gives 16, and 1023 gives 25.

Putting this all together:

void main()
{
  int sensorReading;
  int x; // <--- New, was float, now it is int

  TRISA = 0xFF;
  TRISC = 0x00;

  ADC_Init();
  PWM2_Init(50); // <--- New, was 3000 Hz, now 50 Hz

  while(1)
  {
    sensorReading = ADC_Read(0);

    x = 7 + 0.0176 * sensorReading; // <--- new mapping

    PWM2_Set_Duty(x); // <--- no division here
    PWM2_Start();
  }
}


问:
How do I integrate webots sensor plugins into a ros2 URDF/Xacro file?
I am trying to set up a Lidar, IMU, and depth camera in Webots on a ROS 2 robot in its xacro file (starting with just the Lidar).

I currently have the following:

```<code><webots>

  <plugin type="webots_ros2_driver::Ros2Lidar">
    <frameName>laser_frame</frameName>
    <enabled>true</enabled>
    <scanRate>10</scanRate>
    <topicName>/scan</topicName>
    <alwaysOn>true</alwaysOn>
  </plugin>

  <plugin type="webots_ros2_control::Ros2Control"/>

</webots>
</code>```

I'm not sure about the parameters since I just adapted it from the IMU plugin from the turtlebot webots_ros2 example. But the only error I have is this:

```<code>[driver-2] ModuleNotFoundError: No module named 'webots_ros2_driver::Ros2Lidar'
[driver-2] terminate called after throwing an instance of 'std::runtime_error'
[driver-2]   what():  The webots_ros2_driver::Ros2Lidar plugin cannot be found (C++ or Python).
</code>```

I've found the Ros2Lidar plugin locally (I think), but it doesn't seem to be able to find it. The demos all work, but the vast majority are just from robots built IN Webots .proto files. But I need to use ROS for the robot itself that uses a xacro file.

Any hints would be appreciated.

Thanks in advance,
Craig

答:
We are aware that there is a lack of documentation on current implemented device interfaces and how to use them. We are currently working on new tutorials for the official ROS 2 documentation.

Currently, there are 10 devices that have an automatic interface with ROS 2:

Camera

Compass

Distance Sensor

Emitter

GPS

LED

Lidar

Light Sensor

Ranger Finder

Receiver

For these devices, webots_ros2_driver will automatically load the static plugin. This means that associated topics and services will be created. You can have a look at each of these plugins in webots_ros2_driver/src/plugins/static. You can overwrite multiple parameters like topic names or the update rate in your URDF file in the <webots> tag. In your example, it would be:

<device reference="lidar_name_in_webots" type="Lidar">
  <ros>
    <frameName>laser_frame</frameName>
    <enabled>true</enabled>
    <scanRate>10</scanRate>
    <topicName>/scan</topicName>
    <alwaysOn>true</alwaysOn>
  </ros>
</device>
```
<p>There is also a plugin provided with <code>webots_ros2_driver</code> that interfaces IMU sensors. You can find it in <code>webots_ros2_driver/src/plugins/dynamic</code>. This plugin can be loaded in the exact way you did in your question:</p>
<pre class="lang-xml prettyprint-override"><code><plugin type="webots_ros2_driver::Ros2IMU">
  <enabled>true</enabled>
  <topicName>/imu</topicName>
  <alwaysOn>true</alwaysOn>
  <frameName>imu_link</frameName>
  <inertialUnitName>inertial unit</inertialUnitName>
  <gyroName>gyro</gyroName>
</plugin>
</code>```

If the default interfaces don't suit you or is not enough, you can create your own custom plugin. Please take a look at the following links to do so in C++ or Python: Tutorial-Creating-a-Custom-Cpp-Plugin and Tutorial-Creating-a-Custom-Python-Plugin.

Body:
We are aware that there is a lack of documentation on current implemented device interfaces and how to use them. We are currently working on new tutorials for the official ROS 2 documentation.

Currently, there are 10 devices that have an automatic interface with ROS 2:

Camera

Compass

Distance Sensor

Emitter

GPS

LED

Lidar

Light Sensor

Ranger Finder

Receiver

For these devices, webots_ros2_driver will automatically load the static plugin. This means that associated topics and services will be created. You can have a look at each of these plugins in webots_ros2_driver/src/plugins/static. You can overwrite multiple parameters like topic names or the update rate in your URDF file in the <webots> tag. In your example, it would be:

<device reference="lidar_name_in_webots" type="Lidar">
  <ros>
    <frameName>laser_frame</frameName>
    <enabled>true</enabled>
    <scanRate>10</scanRate>
    <topicName>/scan</topicName>
    <alwaysOn>true</alwaysOn>
  </ros>
</device>

There is also a plugin provided with webots_ros2_driver that interfaces IMU sensors. You can find it in webots_ros2_driver/src/plugins/dynamic. This plugin can be loaded in the exact way you did in your question:

<plugin type="webots_ros2_driver::Ros2IMU">
  <enabled>true</enabled>
  <topicName>/imu</topicName>
  <alwaysOn>true</alwaysOn>
  <frameName>imu_link</frameName>
  <inertialUnitName>inertial unit</inertialUnitName>
  <gyroName>gyro</gyroName>
</plugin>

If the default interfaces don't suit you or is not enough, you can create your own custom plugin. Please take a look at the following links to do so in C++ or Python: Tutorial-Creating-a-Custom-Cpp-Plugin and Tutorial-Creating-a-Custom-Python-Plugin.


问:
Dead reckoning or SLAM for localization with unusual locomotion?
I am working on a senior design project with a robot that moves in an unusual way: it rolls around in a single spherical body, similar to BB-8 from the Star Wars sequels. My personal task for the project is to create a localization system for estimating the robot's current location based on its starting position and previous movement, with the primary processor of the robot being a Raspberry Pi 4B mounted in the "head" of BB-8.

So far, I have tried to make this work by using readings from an RSX-UM7 IMU from Redshift Labs to perform dead reckoning, but this has been unreliable. Minor fluctuations in acceleration result in the estimated position rapidly drifting from the actual location, even while sitting completely still. My advisor has suggested that I instead use a depth sensor or similar device for localization, since I still haven't found reliable success with dead reckoning. As far as I can tell, using a depth sensor would involve setting up a SLAM algorithm to estimate a map of the robot's surroundings.

Which of these would be a more reliable option? Should I continue trying to debug my dead reckoning algorithm to minimize the effects of minor drifts, or should I try to implement SLAM with the depth sensor?

答:
Consider deriving Pitch, Yaw and Roll from the IMU's accelerometer.  From this plot the contact point between the robot's spherical body and the (flat) surface the robot travels on.  From this derive the direction of travel and distance of traveled.

Consider using Quaternion rather than Euler angles to avoid Gimbal lock.


答:
Minor fluctuations in acceleration result in the estimated position rapidly drifting from the actual location, even while sitting completely still.

Yup.  Welcome to the real world, kid*.

If you assume an otherwise perfect IMU, and a perfect knowledge of your local acceleration due to the earth's** gravity***, the noise of a typical IMU that you can afford will mess you up.  This is because even if it's just white noise, you have to integrate twice to get from acceleration to position.

Regardless of anything else, you can use an IMU to augment an existing position or velocity sensor, but if you're going to use it for dead reckoning you can only do so over periods of time that are roughly proportional to the amount of error you can stand divided by the accelerometer error squared (and modified by the gyro error in a non-trivial way).  I'd say "you can't use an IMU for navigation" except you can -- purely inertial navigation systems have been in use in airplanes and submarines for decades.

So -- abandon any notions of doing the navigation purely from an IMU, unless you happen to have a hundred pounds of export-restricted**** IMU laying around, and you don't mind building a really BIG version of BB-8.

What you can do, at least theoretically, is combine the short-term good, long-term bad IMU readings with long-term good, short-term bad position sensor readings to get a really good position readout.  This is basically what IMU/GPS fusion is all about, or IMU-aided SLAM.

I say theoretically because you're trying to fit this into the space of a senior project, and you already have the design of the robot on your plate.  Unless there's some depth-sensor-based, IMU-aided SLAM project already out there in the Internet somewhere, just getting that part working is worthy of a senior project.

So:

Renegotiate the project to just doing the navigation, perhaps with your BB-8 head on a stick.

Shop around for a video-based SLAM (probably much more reliable, and not much more expensive than depth sensors) -- then renegotiate that part of your project.

Shop around for my probably-mythical depth-sensor-based SLAM, with or without IMU assistance.

* Listen to that in Han Solo's voice.

** Assuming earth.

*** Which varies too much from point to point to assume as being constant, even with cheap cell-phone IMU chips.

**** They're called "strategic-grade" IMUs, if you want to go shopping for them on eBay.  Hence the export restriction -- if they're rugged enough, they're just what you need for a guidance system in a GPS-independent ICBM.

Title: Dead reckoning or SLAM for localization with unusual locomotion?

Body:
I am working on a senior design project with a robot that moves in an unusual way: it rolls around in a single spherical body, similar to BB-8 from the Star Wars sequels. My personal task for the project is to create a localization system for estimating the robot's current location based on its starting position and previous movement, with the primary processor of the robot being a Raspberry Pi 4B mounted in the "head" of BB-8.

So far, I have tried to make this work by using readings from an RSX-UM7 IMU from Redshift Labs to perform dead reckoning, but this has been unreliable. Minor fluctuations in acceleration result in the estimated position rapidly drifting from the actual location, even while sitting completely still. My advisor has suggested that I instead use a depth sensor or similar device for localization, since I still haven't found reliable success with dead reckoning. As far as I can tell, using a depth sensor would involve setting up a SLAM algorithm to estimate a map of the robot's surroundings.

Which of these would be a more reliable option? Should I continue trying to debug my dead reckoning algorithm to minimize the effects of minor drifts, or should I try to implement SLAM with the depth sensor?


答:
Yes this is a broad question, you answered it partially is depends on your project.

If you are working on a team, you probably would be responsible for the electrical, or mechanical, or navigation, and goes on, so you can go more deep inside the topic.

But, anyway, you should know sufficient about the other team topics to integrate things together.

If you are managing a project, working not in a big team, or want to get more specialized, there's so much things related to robotics. And as a base I would say: Electronics, mechanics, electro-mechanic, programming. This will include for example in mechanics, all the basic concepts, tons of literature and the experience you gain with time, and this includes how the things you study are manufactured. That includes (but not only) how the material is cut, welded, molded, each type of the processes and their pros and cons, etc.

Kits will help with this, but it will take some years to get all together, as the kits have the pieces manufactured, you probably don't experience the more manufacturing questions. You would not get complicated by "will this method of joining" two materials will be the correct choice for this type of application? Will the stress on it be a problem?

This is just about mechanical, now take that to electrical, electro-mechanical, and programming, as you see, it takes time and effort. This means you would not know all about just one, you probably want to specialize in one subject once you get a project that will require it, but with the base and experience in this topics, it should be a more easily learning curve to get on the subject.

As robotic is a wide topic, you probably won't get all in small time, this would go with the experience, literature, already implemented solutions, and goes on.

Title: What should I study if I want to get into robotics?

Body: I understand this is a broad question but I'm taking the risk to ask anyway.  Robotics, from what I can tell so far, is a detailed, diverse, and thorough field. However, if there are better areas of research to invest time into, what would those areas be?</p>


答:
Are there any differences between using quaternions and using acceleration and angular velocity individually in the state vector?

It's not either/or.  A "universal" state vector would be $\vec x = \begin{bmatrix}\vec p & \vec v & \vec \theta \end{bmatrix}^T$, where $\vec \theta$ is your choice of any rotation representation, be it Euler angles, quaternions, axis + rotation, or whatever.

Title: The choice of using quaternions and using gyro & accel separately in EKF

Body:
I am working on realising the self-navigation of a vehicle.

I have already written an extended Kalman filter with a state vector using position, velocity, Euler angle, acceleration, and angular velocity. However, I have recently read alternative papers using quaternions as a whole to represent the orientation of the body.

Are there any differences between using quaternions and using acceleration and angular velocity individually in the state vector? If there are, what is the advantage of doing that?


问:
Derivative Block Diagrams
I am a newbie in Control Theory. I am solving an exercise found on-line. I do not expect anyone to solve it for me. I would just ask for a clarification about the block "p+a". I suppose it represents a derivative operator, with the input being "-theta". What is the output? The "a" term confuses me.
Thanks in advance.

dealingHow should a

答:
The "a" term confuses me.

A is the proportional gain of the controller.

Actually, a proportional controller is the most basic feedback controller. The output ($u$ in the diagram) is just: $$ u=  Kp \cdot error = Kp ( \theta_{desired} - \theta_{measured} ) $$ In your case, $\theta_{desired} = 0, \ \theta_{measured} = \theta, \ Kp= a$. (But usually the notation used is $Kp$ or $P$, not $a$)

What is the output?

The controller in the exercise is a PD controller, that is a proportional ( $a$ term) - derivative ($1\cdot p$ term) controller, where the output/command is:
$$ u=  Kp \cdot error + Kd \cdot \frac{d}{dt}(error) $$
In your case, $ \ Kp= a, Kd = 1$.

You can find out more information, searching for a PID controller.

Extra I would suggest you pick a book if you want to learn control theory, like nise or ogata (Ogata is actually a pdf). Not only will the information be presented in a structured manner, but also the notation will be more modern. (I have never seen $p$ used as a symbol for the laplace complex variable, usually $s$ is used. Also, the gains are either $Kp,Kd,Ki$ or $P,D,I$) And reading material with the common notation will help you understand other sources you find online.

Title: Derivative Block Diagrams


问:
symbol lookup error: /snap/core20/current/lib/x86_64-linux-gnu/libpthread.so.0: undefined symbol: __libc_pthread_init, version GLIBC_PRIVATE
I was  trying to setup a simple transform broadcaster by following Write a broadcaster (Python) from ROS2 Humble documentation.

I created the package, nodes, launch files, and everything else, including the addition of entry points, data files etc., and the package was successfully built using colcon. But when I tried to launch the node using the below command, an error occurred. I don't know what went wrong; but, in order to rectify any human error in following the steps, I tried doing the same thing multiple times and resulted in the same error.

Launch command I executed (given in the docs)

ros2 launch learning_tf2_py turtle_tf2_demo.launch.py
```
<p><strong>ERROR Log</strong></p>
<pre class="lang-bash prettyprint-override"><code>jishnu@Legion:~/robotics/ros-git/tf2$ ros2 launch learning_tf2_py turtle_tf2_demo.launch.py
[INFO] [launch]: All log files can be found below /home/jishnu/.ros/log/2023-04-07-19-06-58-821889-Legion-2160358
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [turtlesim_node-1]: process started with pid [2160368]
[INFO] [turtle_tf2_broadcaster-2]: process started with pid [2160370]
[turtlesim_node-1] QSocketNotifier: Can only be used with threads started with QThread
[turtlesim_node-1] /opt/ros/humble/lib/turtlesim/turtlesim_node: symbol lookup error: /snap/core20/current/lib/x86_64-linux-gnu/libpthread.so.0: undefined symbol: __libc_pthread_init, version GLIBC_PRIVATE
[ERROR] [turtlesim_node-1]: process has died [pid 2160368, exit code 127, cmd '/opt/ros/humble/lib/turtlesim/turtlesim_node --ros-args -r __node:=sim'].
</code>```

答:
From Java: symbol lookup error: /snap/core20/current/lib/x86_64-linux-gnu/libpthread.so.0: undefined symbol: __libc_pthread_init, version GLIBC_PRIVATE on Stack Overflow:

Though I have already answered it here

The issue with how the VSCode Snap package libraries are configured to be used. They are setting the following environment variable GTK_PATH, which gets inherited by the VSCode Terminal.

Unsetting the environment variable in the VSCode terminal does seem to work for me.

```<code>unset GTK_PATH
</code>```

Or you can clear out the environment variable by using the VSCode Configuration, as mentioned in the other answer.

You will probably need to run unset GTK_PATH each new session/login/reboot. To set it permanently, put the command in your profile.

Note: It is a good idea to make a note of what the value of GTK_PATH is, prior to unsetting it - that way you can revert it back to its previous value, should you encounter any issues. To see what its "usual" value is, run echo $GTK_PATH, prior to unsetting it... If you have already unset it, open a new terminal window, which should have the unset value of GTK_PATH (if not, try a reboot).

Body:
From Java: symbol lookup error: /snap/core20/current/lib/x86_64-linux-gnu/libpthread.so.0: undefined symbol: __libc_pthread_init, version GLIBC_PRIVATE on Stack Overflow:

Though I have already answered it here

The issue with how the VSCode Snap package libraries are configured to be used. They are setting the following environment variable GTK_PATH, which gets inherited by the VSCode Terminal.

Unsetting the environment variable in the VSCode terminal does seem to work for me.

unset GTK_PATH

Or you can clear out the environment variable by using the VSCode Configuration, as mentioned in the other answer.

You will probably need to run unset GTK_PATH each new session/login/reboot. To set it permanently, put the command in your profile.

Note: It is a good idea to make a note of what the value of GTK_PATH is, prior to unsetting it - that way you can revert it back to its previous value, should you encounter any issues. To see what its "usual" value is, run echo $GTK_PATH, prior to unsetting it... If you have already unset it, open a new terminal window, which should have the unset value of GTK_PATH (if not, try a reboot).


问:
Connecting a Raspberry Pi to a roomba via an FTDI cable
I have a Raspberry Pi with this FTDI cable and a Roomba 560. The Roomba has an SCI port to allow for control of the roomba via serial. I installed the PySerial library on the pi and send valid commands to Roomba, but the roomba doesn't respond. I have the TXD of the cable attached to the TXD of the roomba, the RXD on the cable wired to the RXD on the roomba, and a ground on the cable wired to the ground on the roomba (everything in  it's respective port). I do not have power going from the cable to the roomba or vice-versa.

What I can't figure out is why the commands aren't working. There's no error message upon running the python code. This is the information sheet for the Roomba's SCI port.

Code:

```<code>import serial

ser = serial.Serial('/dev/ttyUSB0')
# this is the defualt Roomba baud rate
ser.baudrate = 57600

# Start SCI - puts into safe mode
ser.write(chr(128))
# Enable full mode
ser.write(chr(131))
# Spot clean
ser.write(chr(134))

print 'Done'
</code>```

答:
Try:

```<code>ser = serial.Serial('/dev/ttyUSB0', 57600)
</code>```

(though from a quick look at the docs your way should work too).

A very common mistake is switching RX and TX.  The TX from your board need to go into the Roomb'a RX. Given your note about connecting TX to TX you've almost certainly wired this wrong.  TXD in your cable (JP1-4) is an output and needs to go into RXD in the Roomba which is the corresponding input.  Looks like reversing these shouldn't cause any damage as your cable schematic shows a 100ohm resistor in series with TXD.

I see there's also a "device detect" input on the Roomba which seems to only be needed when the Roomba is "sleeping" but you may want to wire it to RTS so you can control it.

Body:
Try:

ser = serial.Serial('/dev/ttyUSB0', 57600)

(though from a quick look at the docs your way should work too).

A very common mistake is switching RX and TX.  The TX from your board need to go into the Roomb'a RX. Given your note about connecting TX to TX you've almost certainly wired this wrong.  TXD in your cable (JP1-4) is an output and needs to go into RXD in the Roomba which is the corresponding input.  Looks like reversing these shouldn't cause any damage as your cable schematic shows a 100ohm resistor in series with TXD.

I see there's also a "device detect" input on the Roomba which seems to only be needed when the Roomba is "sleeping" but you may want to wire it to RTS so you can control it.


问:
How are these equivalent rotation coordinates related?
I am using a 6 DOF UR5 robotic arm. I am successfully sending it commands in the [X,Y,Z,RX,RY,RZ] format. When I read back these coordinates, I find that the X, Y, Z values are the same but the RX, RY, and RZ values are not. When I type the read values into my pendant, the preview shows that the orientation actually is what I want but I can not figure out how these RX, RY, RZ values can possibly be equivalent to each other. How can [X, Y, Z, -2.871, 0.539, -0.714] be equivalent to [X, Y, Z, 3.128, -0.587, 0.778]?

This picture from the pendant shows the rotated axes are the same: (original image)

答: They are written in the angle-axis representation. In the angle axis representation, the direction of the 3d vector gives the axis of rotation (rotates counter clockwise around it). These two rotations are equivalent because the axes are the same but one is flipped (if you notice, one vector is approx -1.08 times the other). And because the axis is flipped and the rotation is no longer counterclockwise with respect to the original axis, the equivalent rotation is $2\pi - \theta$ radians compared to the $\theta$ of the other. So if you flip the axis, and adjust the magnitude appropriately, you can get the same rotation.


问:
Instantaneous Center of Rotation of Skid-Steering Mobile Robot
Is there a instantaneous center of rotation (ICR) for 4-wheeled skid steering mobile robot (such as Husky , Pioneer 3-AT) if the center of mass is located at the geometric center of the robot? What if it is not located at the geometric center of the robot?</p>

答: If the context is differential drive calculations, the robot's z-axis center-of-rotation has nothing to do with the robot's mass.</p>


答:
Even though the port is automatically opened when the Serial object is created, make sure that is open using ser.isOpen(). If it is not opened, then open it with ser.open()

Try to add a small pause between the ser.write commands

Make sure you connected the ground to the correct pin. Maybe you connected it to pin 5 (on the roomba connector) instead on 6 or 7

Title: Connecting a Raspberry Pi to a roomba via an FTDI cable

Body:
I have a Raspberry Pi with this FTDI cable and a Roomba 560. The Roomba has an SCI port to allow for control of the roomba via serial. I installed the PySerial library on the pi and send valid commands to Roomba, but the roomba doesn't respond. I have the TXD of the cable attached to the TXD of the roomba, the RXD on the cable wired to the RXD on the roomba, and a ground on the cable wired to the ground on the roomba (everything in  it's respective port). I do not have power going from the cable to the roomba or vice-versa.

What I can't figure out is why the commands aren't working. There's no error message upon running the python code. This is the information sheet for the Roomba's SCI port.

Code:

```<code>import serial

ser = serial.Serial('/dev/ttyUSB0')
# this is the defualt Roomba baud rate
ser.baudrate = 57600

# Start SCI - puts into safe mode
ser.write(chr(128))
# Enable full mode
ser.write(chr(131))
# Spot clean
ser.write(chr(134))

print 'Done'
</code>```


问:
work envelope volume calculation using reach and stroke values
What is the volume of the work envelope of a Cartesian
robot whose x,y,z axes each have maximum reach 1.2m
and maximum stroke 80cm?

current thinking is V= lxbxh as Cartesian.

答:
Yes, that's exactly right.  The envelope is the maximum space it can reach and move within (i.e. the volume encompassed).

The x-axis can move from -1.2m to +1.2m, covering a distance of 2.4m.

The y-axis can move from -1.2m to +1.2m, covering a distance of 2.4m.

The z-axis can move from 0m to 0.8m, covering a distance of 0.8m.

So the total envelope is 2.4m x 2.4m x 0.8m = 4.608 cubic meters.


问:
How can I set the sample rate/frequency for a Webots GPS module?
I'm trying to simulate a GPS module I have on a real robot (using ROS 2) which has a position update rate of 1Hz. Is it possible to set this in a GPS device? I'm importing the device directly to Webots from a URDF (I had to modify the urdf2webots script to include the GPS() device), but I can't find a sample_rate option in Webots so I can change that too.

These are the only settings available (this one was imported from URDF):

None of these options seem to affect sample-rate for just the GPS.

Is my only option to write a ROS node that captures the 30Hz Webots sim rate and only republishes at the desired rate? Or can this be set in Webots somehow?

Thanks all

答:
In Webots the sensor update rate is defined in the controller side when enabling the device by specifying the sampling period in ms (1Hz = 1000ms) and not in the model definition.

For the GPS device, here is the documentation of the enable function:
https://www.cyberbotics.com/doc/reference/gps#wb_gps_enable

If you are using ROS, then the update rate is specified using the sampling period value using the webots_ros::set_int argument of the /<device_name>/enable service.

Disclaimer: I am a Webots developer working at Cyberbotics.


问:
Spawning robot from URDF Xacro file in webots
I am trying to import my xacro model like it's shown in the https://github.com/cyberbotics/webots_ros2/wiki/Tutorial-Ros2Supervisor-Import-your-Urdf-Robot tutorial, changing only the xacro and world file, however I can launch the project but the robot does not appear in the webots simulation, only the world does, my terminal says : "WARNING: the Ros2Supervisor was not able to spawn this URDF robot" and nothing more, I can't see what I have done wrong as I changed almost nothing... I'm not sure if I'm missing tags in my urdf xacro file as I also tried using one in the tutorials (humble urdf tutorial - 07-physics.urdf) that should be good but the problem still occurs. Thanks !
I'm using Webots R2023a, ros2 humble, on VirtualBox Ubuntu</p>

答:
First of all, I have updated the linked tutorial to the most recent version of the package. The Ros2Supervisor is not spawned the same way as it was in previous versions of the package. Also, I opened a Pull Request on the repository to restrict the message "WARNING: the Ros2Supervisor was not able to spawn this URDF robot" as it was always triggered, even if the URDF is correctly spawned. If you want to benefit from this change, although it is not mandatory, you can build the package from sources (master branch). More information is available in this tutorial. In any case, you should use the 2023.0.2 version of the package, which is the latest stable binary release on Humble.

Getting back to your issue, it is weird that you don't get any other error messages. The Ros2Supervisor node should provide information on why the URDF could not be spawned. Are you able to launch the universal robot example?

```<code>ros2 launch webots_ros2_universal_robot multirobot_launch.py
</code>```

If you still encounter the issue after updating the launch file to the new version of the tutorial, you can post the content of your files so that I can investigate further.

Disclaimer: I am a Webots developer working at Cyberbotics.

Body:
First of all, I have updated the linked tutorial to the most recent version of the package. The Ros2Supervisor is not spawned the same way as it was in previous versions of the package. Also, I opened a Pull Request on the repository to restrict the message "WARNING: the Ros2Supervisor was not able to spawn this URDF robot" as it was always triggered, even if the URDF is correctly spawned. If you want to benefit from this change, although it is not mandatory, you can build the package from sources (master branch). More information is available in this tutorial. In any case, you should use the 2023.0.2 version of the package, which is the latest stable binary release on Humble.

Getting back to your issue, it is weird that you don't get any other error messages. The Ros2Supervisor node should provide information on why the URDF could not be spawned. Are you able to launch the universal robot example?

ros2 launch webots_ros2_universal_robot multirobot_launch.py

If you still encounter the issue after updating the launch file to the new version of the tutorial, you can post the content of your files so that I can investigate further.

Disclaimer: I am a Webots developer working at Cyberbotics.


问:
What Robot Type is depicted?

What type of robot is depicted in the below picture. I can rule out Cartesian as there is revolute joints.

答:
It seems to be basically a SCARA robot.  It's just that the tool tip has an odd extra degree of freedom.

Is the axis of rotation of $\theta_3$ really about the tip, or is it further up at the $L_2$ joint?

Title: What Robot Type is depicted?


问:
Gazebo Garden sensor plugins for ROS 2 URDF files
I have a Gazebo Garden simulation and I struggle to make it work with Gazebo plugins for the URDF file.

Context

I have a URDF file of my robot, but I first could not find an obvious way to make it work in Gazebo Garden, so I created a simplified SDF version of the robot.

I first made the simulation work with an SDF file for the robot, but I could not get it to work with the robot_state_publisher. I could not find any example of how to publish the robot_description and the tf from Gazebo directly so I could use it without launching the robot_state_publisher manually through a ROS 2 launch file. (I wanted to avoid this as then I needed to recreate my SDF file as URDF file to give it to the state publisher node.

I then figured out how to use the URDF version of my model and I made a launch file that loads the URDF of the robot and gives it to Gazebo. The simulation launches fine, the robot model is there, and I can use the robot_state_publisher to get the proper tf of the robot and the robot_description.

BUT: I fail to load any plugins written inside the URDF file since I can't find any examples on how to do this.

Current state

I found this comment that I could load the plugins the same way as I would in the classic Gazebo: https://github.com/gazebosim/ros_gz/issues/109

I receive the following error messages related to my problem:

```<code>[ruby $(which gz) sim-1] [Wrn] [SystemPaths.cc:168] Finding plugins using deprecated IGN_ prefixed environment variable [IGN_GAZEBO_SYSTEM_PLUGIN_PATH]. Please use the GZ_ prefix instead.
[ruby $(which gz) sim-1] [Err] [SystemLoader.cc:118] Failed to load system plugin: (Reason: Could not find shared library)
[ruby $(which gz) sim-1] - Requested plugin name: [camera_controller]
[ruby $(which gz) sim-1] - Requested library name: [libgazebo_ros_camera.so]
[ruby $(which gz) sim-1] - Library search paths:
[ruby $(which gz) sim-1]   - /home/leo/.gz/sim/plugins/
[ruby $(which gz) sim-1]   - /usr/lib/x86_64-linux-gnu/gz-sim-7/plugins/
[ruby $(which gz) sim-1]   - /home/leo/.ignition/gazebo/plugins/
[ruby $(which gz) sim-1]   - /
[ruby $(which gz) sim-1]   - /home/leo/ros2_ws/install/sdformat_urdf/lib/
[ruby $(which gz) sim-1]   - /home/leo/ros2_ws/install/ros_gz_sim/lib/
[ruby $(which gz) sim-1]   - /home/leo/ros2_ws/install/ros_gz_bridge/lib/
[ruby $(which gz) sim-1]   - /home/leo/ros2_ws/install/ros_gz_interfaces/lib/
[ruby $(which gz) sim-1]   - /opt/ros/humble/lib/x86_64-linux-gnu/
[ruby $(which gz) sim-1]   - /opt/ros/humble/lib/
[ruby $(which gz) sim-1]   - (Deprecated) /
[ruby $(which gz) sim-1]   - (Deprecated) /home/leo/ros2_ws/install/sdformat_urdf/lib/
[ruby $(which gz) sim-1]   - (Deprecated) /home/leo/ros2_ws/install/ros_gz_sim/lib/
[ruby $(which gz) sim-1]   - (Deprecated) /home/leo/ros2_ws/install/ros_gz_bridge/lib/
[ruby $(which gz) sim-1]   - (Deprecated) /home/leo/ros2_ws/install/ros_gz_interfaces/lib/
[ruby $(which gz) sim-1]   - (Deprecated) /opt/ros/humble/lib/x86_64-linux-gnu/
[ruby $(which gz) sim-1]   - (Deprecated) /opt/ros/humble/lib/
</code>```

Maybe the following information is important to know:

When I set the variable GZ_SIM_RESOURCE_PATH, it did not work, I also had to set the variable IGN_GAZEBO_RESOURCE_PATH for Gazebo to be able to load the robot model as URDF.

What I need

I need examples of how to add different sensors to my URDF (actually the XACRO) file. I want to add the differential drive controller to move the robot, a regular RGB camera, a depth camera and a LiDAR. They all work fine in the SDF file, but I do not know how to translate them into the URDF file.

I am using ROS 2 Humble with Gazebo Garden inside a Docker container.

My Files

My files are available for inspection on GitHub: https://github.com/Dave-van-der-Meer/leorover_gazebo_sim_docker

The latest changes are on the "add_sensors_to_URDF" branch.

答: IMO, the best way to debug this is to first generate your final URDF from the xacro files and then running gz sdf -p path/to/your/urdf_file. This will generate the SDF file that Gazebo will consume when you spawn a URDF file. Also take a look at http://sdformat.org/tutorials?tut=sdformat_urdf_extensions&cat=specification& to see how to use the <gazebo> tag in URDF. Generally, the <gazebo> tag (without the reference attribute) is where you want to put your plugins.


问:
Deprecating a ROS 2 parameter name
ros-perception/image_transport_plugins was ported across from ROS 1 to ROS 2 a while back. During the port, some parameters were given the wrong parameter name. We are trying to revert the parameter names to what they were in ROS 1, and want to deprecate the current parameter names. This is tracked in this issue.

To give an example, we have a node with the parameter name foo, but we want this parameter to be named bar instead. Other packages may depend on calling get/set on the foo parameter, so we can't simply rename it and break other packages. We want to notify these callers that they should be calling get/set on bar instead in the new version.

Is there a graceful deprecation strategy here? I believe this is possible for the setting of parameters, but is there a way to give a warning when another node tries to get a deprecated parameter in rclcpp?

答:
I don't believe that there is a way to warn the caller specifically.

We can't always provide full notifications of deprecations. Compile time or build time are optimal, but runtime ones are helpful but can be annoying sometimes if to verbose. The main thing to provide is good strong documentation with ample verbosity in changelogs and release notes. As well the callers can remap relatively quickly when they discover the mismatch. And if you're clear when setting, that will hopefully inform most of the applications that are getting the parameters too. We could extend the getParameter API to be able to register a callback but that's potentially a lot of overhead and complexity to trade off against.

Title: Deprecating a ROS 2 parameter name


问:
Two State Linear Actuator
I need two state linear actuator. You can have a look at the picture to understand what I mean.

Don't care about the hand !

(source: robaid.com)

I need to electrically move the things like this squares up and down. Bidirectional linear actuators are needed.
What is the cheapest and tiniest actuator (or sth else) that I can use to move this squares up and down. There are just two states ('up','down'). Don't care how much higher a square rises, when it is up.

答: The problem is simple if you are using a coil and a pin (solenoid) but the size (diameter) of the coil would be the limiting factor to how closely your pins could be nested. Pneumatics (pressure= up and vacuum = down) could also be used and achieve a tighter nesting.  The valve configuration would be the limiting factor with pneumatics.</p>

Title: Two State Linear Actuator


答:
It turns out that the statement in the Roomba SCI spec sheet about ports is either outdated or incorrect. The Roomba 5XX series (and 7XX series) uses port 115200 to communicate, and that's what was wrong.

Wiring: I wired the TXD of the cable to the RXD of the roomba (so the orange cable would go into port 3 on the roomba), and vice versa. I also wired the ground and that was all that was needed.


问:
Measure processor loading in Webots
Is there a way to measure the CPU usage or the processor loading per simulation time step? I essentially want a way to compare the computational cost of different controller implementations

I reckon I can get an indication of CPU usage on my Mac's Activity Monitor, but was wondering if there's a better and more quantitative way

For context, I am simulating different kinds of controllers for a swarm robot system consisting of ~40 e-puck robots

答:
You can use the --log-performance command line option of Webots. According to the Webots user guide:

```<code>  --log-performance=<file>[,<steps>]
    Measure the performance of Webots and log it in the file specified in the
    <file> argument. The optional <steps> argument is an integer value that
    specifies how many steps are logged. If the --sysinfo option is used, the
    system information is prepended into the log file.
</code>```

If that is not sufficient, I would recommend you to recompile Webots from the source and add your own timers inside the code of Webots.

Disclaimer: I am a Webots developer working at Cyberbotics.

Title: Measure processor loading in Webots

Body:
You can use the --log-performance command line option of Webots. According to the Webots user guide:

  --log-performance=<file>[,<steps>]
    Measure the performance of Webots and log it in the file specified in the
    <file> argument. The optional <steps> argument is an integer value that
    specifies how many steps are logged. If the --sysinfo option is used, the
    system information is prepended into the log file.

If that is not sufficient, I would recommend you to recompile Webots from the source and add your own timers inside the code of Webots.

Disclaimer: I am a Webots developer working at Cyberbotics.