问:
How does dense mapping/voxel occupancy grid map work with bundle adjustment?
When running for example some version of Orb Slam with stereo vision you're using sparse features for tracking but you can also infer a full depth map. I am curious how you use that full depth map to build a dense 3d map? Do you just run bundle adjustment on the sparse feature set to get the optimized positions and then re-run your depth perception algorithm on the key frames to generate a bunch of point clouds/voxels or is something else done?</p>

答: Most commonly, for the new relative poses of the nodes containing depth data after you optimize your pose-graph, you re-generate your dense representation using that stored sensor data. So each time you optimize the graph, you're essentially generating a new dense representation instance. The same is done in most 2D laser scanner graph SLAMs to create the occupancy grid. This is typically why we try to reduce the frequency of rastering the occupancy grid (or in your case, the voxel grid or similar) as much as reasonably possible. That generation process is not cheap if you're doing probabilistic modeling of free / occupied spaces.</p>


问:
Can ROS run on a Raspberry Pi?
Can ROS run on a Raspberry Pi?

ROS is resigned to run on a network of machines, with different machines, even different cores on the same machine doing different jobs. Can one of those machines be a Raspberry Pi?

I am considering using an R-Pi as the EtherCAT master on a mobile robot, communicating with the main PC over WiFi, using a dongle.

Can an R-Pi even run ROS at all?

Would an R-Pi have enough processing power to do some 1kHz servoing?

Would it be possible to run some servoing on the host through the WiFi connecion?

答: I would check out the rosserial project. Basically, it generates some code for Arduino for communicating over serial to a ROS node on the computer. I bet you can convert it to the Raspberry Pi, so that you can use some other protocol to communicate between the Pi and the host computer. </p>

ContentLicense: CC BY-SA 3.0

Title: Can ROS run on a Raspberry Pi?


问:
Connections on a Baby Orangutang B-328 board
I am new to robotics and planning my first purchase.
I'm looking at the Baby Orangutang B-328. Here is information about the microcontroller: http://www.hobbytronics.co.uk/baby-orangutan-328.

The pin headers come unmounted, so you have to do the soldering yourself. My problem is that I don't know what the pin connections are for. Here is a picture of the board:

http://www.ca.diigiit.com/image/cache/data/pololu/1220/Pololu-Baby-orangutan-b-328-6-500x500.png.

Could someone briefly tell me what the different connections are for, or link a website that does?

答:
Look at the bottom of the page on your first link:  http://www.hobbytronics.co.uk/baby-orangutan-328. under "Documents relating to the Baby Orangutan B-328".

There you will find links to the Baby Orangutan B Users Guide as well as other useful links.

The user's guide contains the pin descriptions you need on page 5.


问:
Pico W does not connect to my phone's hotspot
I am trying to connect my Pico W to the hotspot that I have. The password and the name of the hotspot are in a file called "secret." I found the code online and when I try to run the code here is what I get:

```<code>    # Webserver to send RGB data
# Tony Goodhew 5 July 2022
import network
import socket
import time
from machine import Pin, ADC
from secret import ssid,password
import random

wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(ssid, password)

# Wait for connect or fail
max_wait = 10
print(wlan.status())
while max_wait > 0:

    if wlan.status() < 0 or wlan.status() >= 3:
        break
    max_wait -= 1
    print('waiting for connection...')
    time.sleep(1)
    print(wlan.status())

# Handle connection error
if wlan.status() != 3:
    raise RuntimeError('network connection failed')
else:
    print('connected')
    status = wlan.ifconfig()
    print( 'ip = ' + status[0] )

# Open socket
addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]

s = socket.socket()
s.bind(addr)
s.listen(1)

print('listening on', addr)

# Listen for connections
while True:
    try:
        cl, addr = s.accept()
        print('client connected from', addr)
        request = cl.recv(1024)
        print(request)
        # Do not unpack request
        # We reply to any request the same way
        # Generate 3 values to send back
        r = random.randint(0,255)
        g = random.randint(0,255)
        b = random.randint(0,255)
        # Join to make a simple string with commas as separators
        rgb = str(r) + "," + str(g) + ","+str(b)

        response = rgb # This is what we send in reply

        cl.send(response)
        print("Sent:" + rgb)
        cl.close()

    except OSError as e:
        cl.close()
        print('connection closed')
</code>```

And the output is:

```<code>1
waiting for connection...
-2
Traceback (most recent call last):
File "<stdin>", line 29, in <module>
RuntimeError: network connection failed
</code>```

答: GOT IT!!! My Hotspot setting was messed up. I had to change the settings to the general compatibility</p>

ContentLicense: CC BY-SA 4.0


问:
How to design a representative drive cycle based on speed, acceleration, and torque requirements?
I recently came across the topic of "drive cycle design".  I would like to learn more about this as I delve into motor and RC vehicle design.

Given: the RC vehicle must achieve 25mph max/top speed.

Given: the vehicle's acceleration is not as important, as in it would be okay for the vehicle to use up to 30-60 feet to reach top speed.

Given: the vehicle must be able to achieve top speed while traveling up a 10* slope on asphalt.

The question is how do I conduct a drive cycle design given these requirements?  Specifically, what calculations based on these requirements will help determine required motor specs, drive wheel size, and transmission options, etc.?

Unless additional system-level design considerations exist due to the other requirements, I believe this Q&A helps answer the torque requirement, depending on how it affects the other requirements.

答:
What you've given are performance specifications, not really a full drive cycle, so you can do some analysis on requirements based on those performance specs but you can't, for example, use those performance specifications to specify the battery pack that should be used because the drive cycle isn't given. You'd need to specify how many times it should accelerate/decelerate, how long it operates at each speed, how many ramps it climbs and descends, how fast it operates on those ramps, etc.

For developing product specifications based on performance specs, you need to evaluate the product requirement for each use case, and then you take the product specification from the most demanding use case. From your specifications:

Vehicle top speed. This should be a negligible demand because it only requires overcoming the rolling friction in the wheels and other drivetrain losses.

Acceleration. Need to figure out the force required to get from 0 to 25 mph in the course of 60 feet (lowest acceleration). To do that:

Starting speed is zero, ending speed is 25 mph (36.67 feet per second). If there's constant acceleration then it must move at an average speed of 18.335 feet per second. To cover 60 feet, it must take (60/18.335)=3.27 seconds.

Considering the constant acceleration equation:

$$
x_f = x_0 + v_0t + \frac{1}{2}at^2 \\
$$

Assuming the vehicle starts stationary ($v_0=0$) at position $x_0=0$ then, for constant acceleration,

$$
x_f = \frac{1}{2}at^2 \\
\frac{2x_f}{t^2} = a \\
\frac{2(60 \text{ft})}{3.27^2 \text{s}^2} = a \\
\frac{120}{10.69} \text{ft/s}^2 = a \\
\boxed{a = 11.23 \text{ft/s}^2}
$$

Given Imperial units, gravity on Earth is $\approx 32.2 \text{ft/s}^2$, so you're looking at an acceleration of (11.23/32.2) = 0.35g.

Climbing an incline. You say the vehicle must be able to achieve top speed, which is a little unclear, because I can't tell if it should just maintain top speed on the incline, or if it should accelerate to top speed on the incline. I'll assume it's just maintaining the top speed up the incline. This goes back to point 1, where maintaining the speed should be trivial; the real work happens to prevent the "falling" force down the incline.

You already linked my other, related answer, so I'll just skip to the punchline there - the force you need to go up an incline is $mg\sin{\theta}$.

We can compare the acceleration case with the incline-climbing case if we regroup the result as $m\left(g\sin{\theta}\right)$. At 10 degrees (0.1745 radians), $\sin{\left(10^{\circ}\right)}g$ = 0.17g.

So, in looking at this, your easiest acceleration case requires 0.35g and maintaining speed on an incline requires 0.17g, so acceleration is the limiting case here - any motor capable of meeting your acceleration specification will be sufficient to also maintain speed up a 10 degree ramp.

Now the question is, how big of a motor do you need? The acceleration values are given here, in terms of the gravitational constant $g$, and $F=ma$, so you need to decide on a vehicle mass. But you don't have the mass because you haven't picked the motor, and you can't pick the motor until you have the mass, so now you're into "iterative design," where you guess a vehicle weight, then see what size motor you need, then use that motor mass in your design, and if it's more than your estimated weight then you need to re-run the equations and see what the expected performance is, choose a different motor, etc. etc.

You can avoid some or all of this by being overly conservative in your guesses. If you honestly think that the RC car will weigh 1 kg, then you can use 2 kg for your engineering calculations, find a motor that will do it, and if everything works out to be <2 kg then your vehicle will exceed the design specs.

One of the last items to return to would be that "vehicle top speed" criteria. Looking at Wikipedia for some estimates on rolling friction, it gives "ordinary car tires on concrete" as 0.01 to 0.015. This is used in the equation

$$
F_{\text{friction}} = \mu N \\
$$

where $\mu$ is the friction coefficient (0.01 to 0.015) and $N$ is the "normal force", or force pointing toward the driving surface, which is $N = mg$ for flat surfaces. You can use $N = mg\cos{\theta}$ for the ramp, but I'll refer you back to my earlier comment on being conservative with your estimates so you don't have to keep re-running these calculations. The flat surface will give you the bigger normal force, so use that version for performance specifications and anything that meets that value will exceed it for the ramp.

Now you can look at the power your motor needs to deliver, which is force times speed for linear motion. This means that your motor needs to deliver (conservatively) a force of $0.015 mg$ to overcome rolling friction, while moving at 25 miles per hour, which I'll just convert now to 11.2 meters per second because engineering is much easier in metric.

You can compare the output force requirements, too - the faster acceleration (30 feet) is double the 60-foot acceleration requirement, 0.7 g, the 60-foot acceleration is 0.35 g, climbing the incline is 0.17 g, and maintaining top speed is 0.015 g. This is typical, and why top speed was considered "negligible" at the top.

So now back to the motor power, you need $P = Fv$, or $P = (0.015mg)(11.2 \text{m/s})$. Now you plug in a mass, find the power required, find the force required, work back through the tires and gearbox to find the motor torque required, find a motor that meets or exceeds those specifications, update the estimated weight with the actual motor weight, repeat until your design stabilizes.

For example, if we assume 2.5 kg (about 5.5 pounds), then you find that your mechanical power needs to be (0.0152.59.81*11.2) = 4 watts. If you assume 80 percent efficiency in the drivetrain, then the motor needs to be (4/0.8) = 5 watts. If I google around I find a motor like this (no affiliation or endorsement of the supplier, just a Google result), there's a 5 W motor with a rated speed of 3000 rpm.

3000 rev/min is 50 rev/s, which is 314.15 rad/s, and to get to 25 mph (11.2 m/s), I need $v = r\dot{\theta}$ so $r = v/\dot{\theta}$, so $r = 11.2/314.15$ or wheels with a radius is 3.5 centimeters, or about 1.3 inches.

When I look at tires, I find something like this (again, no affiliation or endorsement), which have an outer diameter of 5.75 inches, or a radius of 2.875 inches. To be able to use those tires, I need to slow the motor by a factor of about (2.875/1.3) = 2.2, while preserving the motor output power. This means I need lower RPM, but higher torque, which is what you get with a gearbox. We'll need a gearbox with a ratio of about 2.2:1, which seems to be in a reasonable range according to this post on an RC forum.

Then you go looking for that transmission, and then you add up the frame, transmission, tires, motor, and batteries, then see if you're above or below 2.5 kg, then keep iterating on designs.

You'll need the drive cycle, or the representative route you plan on taking, in order to determine things like average and peak power draw, which you'll need to specify the power electronics and battery, and then also how long it needs to operate, which you'll need along with the average and peak power draws to specify the battery.

Then you add the batteries and power electronics to the weight and do it all over again.


问:
Question about getting global coordinates of lidar point cloud from relative in Webots
I need to do custom mapping of surroundings with lidar using mobile robot in Webots. What I use for that:

GPS for getting robot position.

Compass for getting direction robot.

Lidar for getting info about surroundings.

I did translation and rotation of relative points from lidar, which worked well when robot is on flat surface.

But no matter how much I tried I can't figure out how to get accurate global coordinates from point cloud relative points, when robot is even a bit tilted.

My guess is that it suppose to use spatial transformation matrices, but I not sure how to use Webots Compass values in rotation matrix.

Maybe someone can show code example or explain the math behind it or there is a method that I missed in Webots?

答:
Basic Example of solution on Python:

```<code>from scipy.spatial.transform import Rotation as Rotation

RobotPoint = gps.getValues()
STR = Rotation.from_quat(InertialUnit.getQuaternion())
for RelativeCloudPoint in lidar.getPointCloud():
  Point2 = STR.apply(RelativeCloudPoint)
  GlobalCloudPoint = RelativeCloudPoint + RobotPoint
</code>```

Using InternalUnit to get Quaternion for spartial rotation matrix. Then apply it to relative coordinates. After that add to it real robot coordinates from GPS. In the end you will get global coordinates of points you need.

Body:
Basic Example of solution on Python:

from scipy.spatial.transform import Rotation as Rotation

RobotPoint = gps.getValues()
STR = Rotation.from_quat(InertialUnit.getQuaternion())
for RelativeCloudPoint in lidar.getPointCloud():
  Point2 = STR.apply(RelativeCloudPoint)
  GlobalCloudPoint = RelativeCloudPoint + RobotPoint

Using InternalUnit to get Quaternion for spartial rotation matrix. Then apply it to relative coordinates. After that add to it real robot coordinates from GPS. In the end you will get global coordinates of points you need.


问:
How much weight can DC Motor carry?
How much weight can following Brushed Motors carry together?

4X 12 Volt 100rpm supplied voltage => (5/17)*12

2X 12 Volt 100rpm supplied voltage => (7/17)*12

These motors are basically the wheels for my battle bot.

Here is the link to the Motor.

I am new to this so please tell me if I'm wrong somewhere.

答:
Below is my motor specification:

Model    : PGM45775-99.5K

Motor Type: HD Planetary DC Motor

Gear Ratio: 99.5:1

Operating Voltage (VDC): 12

Rated Current(A): 4.28

Rated Power (W): 50.97

Rated Base Motor RPM: 6000

Rated Speed (RPM): 50

Rated Torque (N-cm): 392.4

Operating Temperature (°C):-40 to 100

Opt. Relative Humidity(RH)   : 20% ～ 85%

Gear Material: Metal

Housing Material: Copper

Motor Body Size (Diameter) (mm): 45

Motor Length (mm): 136.3

Shaft Diameter (mm): 10

Shaft Length (mm): 25

Shaft Type: Keyed Shaft

Motor Weight(gm): 852

Shipment Weight: 0.9 kg

I am using this motor in a mini robot and I want to know what should be the maximum weight of the bot that this motor will carry. I am using 2 motors.

Title: How much weight can DC Motor carry?


问:
Webots cannot download objects and textures
After installing the newest version of Webots, I find that the objects (PROTO) and textures of the scene cannot be downloaded. The console throws many errors about download failures and the 3D scene misses objects. It may come from a local firewall problem preventing Webots to download the textures. Is it possible to get a local copy of the Webots resources (PROTO files and textures) to avoid this problem and run Webots off-line?</p>

答:
Yes, firewalls may prevent Webots to download the resources.

In this case, you can download and install manually the Webots assets (PROTO files, textures, etc.) using the instructions described here:

https://cyberbotics.com/doc/guide/installation-procedure#asset-cache-download

Once installed, Webots won't download the textures and other resources from the Internet, but use the ones cached locally.

The assets for the latest version Webots R2023a can be downloaded as ZIP archive (named assets-R2023a.zip) from the GitHub download page of Webots:

https://github.com/cyberbotics/webots/releases/tag/R2023a

Disclaimer: I am a software developer at Webots.


问:
Determine the maximum joint velocities for a PTP-Movement
Assuming an industrial robot performs a PTP movement with a speed of 100% for each joint, it often happens that the joints never reach 100% of speed because the torque limits of the actuators are violated and the movement stops.

My approach was to get the torques at each joint with the general equation of motion using reverse Newton-Euler-Algorithm (RNEA):

$T = M(q)*\ddot q + C(q,\dot q)\dot q + G(q)$.
With $\dot q$ being the the joint velocity.
My idea was to convert this equation so that it calculates the velocity. But I'm not sure if that is even possible.

Basic Algorithm idea:
Iterating over each torque the robot would reach when performing the movement to identify the point where it reaches its maximum. Using this maximum torque to calculate the corresponding maximum velocity. Also I'm not sure if maximum torque equals maximum velocity.

Is there an approach that delivers the maximum reachable velocity for a PTP-Movement before the actual movement starts to avoid an error?

答:
I see a few practical issues and things that should be made clear with this approach, but overall I think this could work.

Issues:

The dynamics model you have listed is a "disturbance-free" model - i.e. it does not take into account joint friction, external forces, etc. This usually is not too big of a problem for simulating smaller robots, but if you are working with industrial robots I would imagine they have more impactful disturbances.

Joint friction is largely important for what you are looking to solve for here. imagine a simpler form of the robot dynamics: $\tau = \mathbf{M}(\mathbf{q})\ddot{\mathbf{q}}$. Now, the friction term will be part of $\tau$, so our equation becomes: $\tau_{c} + \mathbf{B}\dot{\mathbf{q}} = \mathbf{M}(\mathbf{q})\ddot{\mathbf{q}}$, where $\tau_{c}$ is the controller torque and $\mathbf{B}$ is some negative definite damping (friction) matrix. As we can see, we cannot increase joint velocity if a joint is moving at a speed which creates friction equal to the max torque of that given motor. Note that friction is notoriously difficult to model, and is not as simple as a constant matrix. This should hopefully illustrate that there is at least a maximum velocity of a real robot, although not necessarily with the disturbance-free model.

Considerations:

You do not need to convert the equation to calculate velocity. If you would like to use this approach, you should numerically integrate your acceleration "into" velocity. If you are familiar with matlab, this would essentially be ode45 or other functions of the same family.

Does max torque equal max velocity? No. Max torque equals max change in velocity, but you would need to apply this torque over time to continue increasing velocity to achieve the maximum velocity.

Basic algorithm:

Inputs:

Trajectory torques: $\tau_{i}$ for $0 \le i \le N$,

Robot model: $\mathbf{M}$, $\mathbf{C}$, $\mathbf{G}$

Maybe some sort of friction estimation (we'll call it $\mathbf{B}$ for consistency)

Initial starting states $\mathbf{q}(0)$ and $\dot{\mathbf{q}}(0)$

Difference in time between torque inputs, $\Delta t$

$\mathbf{v}_{\text{max}} \leftarrow \mathbf{0}$

$\mathbf{q} \leftarrow \mathbf{q}(0)$

$\dot{\mathbf{q}} \leftarrow \dot{\mathbf{q}}(0)$

$\ddot{\mathbf{q}} \leftarrow \mathbf{0}$

for $i \leftarrow 0$ to $N$

$\ddot{\mathbf{q}} \leftarrow \mathbf{M}(\mathbf{q})^{-1}(\tau_{i} -\mathbf{C}(\mathbf{q},\dot{\mathbf{q}})\dot{\mathbf{q}} - \mathbf{G}(\mathbf{q}) + \mathbf{B}(\mathbf{q},\dot{\mathbf{q}})\dot{\mathbf{q}})$

$\mathbf{q} \leftarrow \mathbf{q} + \dot{\mathbf{q}} \Delta t$

$\dot{\mathbf{q}} \leftarrow \dot{\mathbf{q}} + \ddot{\mathbf{q}} \Delta t$

if $v_{\text{max},j} < |\dot{q}_{j}|$ (assuming you are looking for max absolute velocity)

$v_{\text{max},j} \leftarrow |\dot{q}_{j}|$

Return: $\mathbf{v}_{\text{max}}$

This algorithm simply uses the Euler method to perform numerical integration, but there exist more accurate methods (most commonly used methods are Runge-Kutta). The general idea of the algorithm is that you want to simulate your trajectory, then pick out the max velocity as the simulation progresses. You can also calculate the torque values during each step of the simulation - for instance if you are using a PID controller, the torque is just the error of the robot with respect to a desired trajectory.


问:
Are the DH parameters in this text wrong?
An example problem in the textbook I'm reading from has the spherical wrist system and the DH parameter table as shown below:

giving us the transformation matrices as below

$$
A_4=\left(\begin{array}{cccc} c_{4} & 0 & -s_{4} & 0\\ s_{4} & 0 & c_{4} & 0\\ 0 & -1 & 0 & 0\\ 0 & 0 & 0 & 1 \end{array}\right)
$$
$$
A_5=\left(\begin{array}{cccc} c_{5} & 0 & s_{5} & 0\\ s_{5} & 0 & -c_{5} & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 0 & 1 \end{array}\right)
$$
$$
A_6=\left(\begin{array}{cccc} c_{6} & -s_{6} & 0 & 0\\ s_{6} & c_{6} & 0 & 0\\ 0 & 0 & 1 & d_{6}\\ 0 & 0 & 0 & 1 \end{array}\right)
$$
giving us the final transformation matrix as
$$
T_6^3=A_4A_5A_6=\left(\begin{array}{cccc} c_{4}\,c_{5}\,c_{6}-s_{4}\,s_{6} & -c_{6}\,s_{4}-c_{4}\,c_{5}\,s_{6} & c_{4}\,s_{5} & c_{4}\,d_{6}\,s_{5}\\ c_{4}\,s_{6}+c_{5}\,c_{6}\,s_{4} & c_{4}\,c_{6}-c_{5}\,s_{4}\,s_{6} & s_{4}\,s_{5} & d_{6}\,s_{4}\,s_{5}\\ -c_{6}\,s_{5} & s_{5}\,s_{6} & c_{5} & c_{5}\,d_{6}\\ 0 & 0 & 0 & 1 \end{array}\right)
$$
per the textbook.

I think $A_5$ given in the text is wrong. Shouldn't the $\theta$ parameter against link 5 be $\theta_5-90^\circ$? That would give us
$$
A_5=\left(\begin{array}{cccc} s_{5} & 0 & -c_{5} & 0\\ -c_{5} & 0 & -s_{5} & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 0 & 1 \end{array}\right)
$$
and the final transformation matrix as
$$
T_6^3=\left(\begin{array}{cccc} c_{4}\,c_{6}\,s_{5}-s_{4}\,s_{6} & -c_{6}\,s_{4}-c_{4}\,s_{5}\,s_{6} & -c_{4}\,c_{5} & -c_{4}\,c_{5}\,d_{6}\\ c_{4}\,s_{6}+c_{6}\,s_{4}\,s_{5} & c_{4}\,c_{6}-s_{4}\,s_{5}\,s_{6} & -c_{5}\,s_{4} & -c_{5}\,d_{6}\,s_{4}\\ c_{5}\,c_{6} & -c_{5}\,s_{6} & s_{5} & d_{6}\,s_{5}\\ 0 & 0 & 0 & 1 \end{array}\right)
$$
which I think is the right one.

PS:

I did tried my method with different orientation for frame 4 (x-axis flipped 180) and frame 5 (x-axis flipped 180) and I get the same final transformation matrix. If I try the one give by the textbook, I end up getting different answer.

答: If the only problem you see in the DH parameters presented is with the $\theta$ values, it is common practice to drop any offset associated with this value. In other words, $\theta = 0$ is not necessarily the same pose as what is presented in diagrams.


问:
Gazebo Garden Lidar Visualization
I am trying to visualize a point cloud of the lidar so I used the file in the Gazebo Garden tutorials (link: https://gazebosim.org/docs/garden/sen...) and I added these two lines for the Vsiualize Lidar plugin

```<code><plugin filename="gui/libVisualizeLidar.so"
     name="gz::sim::v7::VisualizeLidar">
</plugin>
</code>```

but when I run the simulation, I get a segmentation fault that looks like this:

```<code>Warning: Ignoring XDG_SESSION_TYPE=wayland on Gnome. Use QT_QPA_PLATFORM=wayland to run on
Wayland anyway.
Stack trace (most recent call last):
#31   Object "/lib/x86_64-linux-gnu/libruby-3.0.so.3.0", at 0x7fa3b9eea327, in
#30   Object "/lib/x86_64-linux-gnu/libruby-3.0.so.3.0", at 0x7fa3ba07f31c, in rb_vm_exec
#29   Object "/lib/x86_64-linux-gnu/libruby-3.0.so.3.0", at 0x7fa3ba079ca6, in
#28   Object "/lib/x86_64-linux-gnu/libruby-3.0.so.3.0", at 0x7fa3ba076fd5, in
#27   Object "/lib/x86_64-linux-gnu/libruby-3.0.so.3.0", at 0x7fa3ba074c44, in
#26   Object "/lib/x86_64-linux-gnu/libruby-3.0.so.3.0", at 0x7fa3b9fc0a2e, in
#25   Object "/lib/x86_64-linux-gnu/libruby-3.0.so.3.0", at 0x7fa3b9eeb9bc, in rb_protect
#24   Object "/lib/x86_64-linux-gnu/libruby-3.0.so.3.0", at 0x7fa3ba083c71, in rb_yield
#23   Object "/lib/x86_64-linux-gnu/libruby-3.0.so.3.0", at 0x7fa3ba07f31c, in rb_vm_exec
#22   Object "/lib/x86_64-linux-gnu/libruby-3.0.so.3.0", at 0x7fa3ba079ca6, in
#21   Object "/lib/x86_64-linux-gnu/libruby-3.0.so.3.0", at 0x7fa3ba076fd5, in
#20   Object "/lib/x86_64-linux-gnu/libruby-3.0.so.3.0", at 0x7fa3ba074c44, in
#19   Object "/usr/lib/x86_64-linux-gnu/ruby/3.0.0/fiddle.so", at 0x7fa3b566444b, in
#18   Object "/lib/x86_64-linux-gnu/libruby-3.0.so.3.0", at 0x7fa3ba042098, in rb_nogvl
#17   Object "/usr/lib/x86_64-linux-gnu/ruby/3.0.0/fiddle.so", at 0x7fa3b5663d6b, in
#16   Object "/lib/x86_64-linux-gnu/libffi.so.8", at 0x7fa3b5603492, in
#15   Object "/lib/x86_64-linux-gnu/libffi.so.8", at 0x7fa3b5606e2d, in
#14   Object "/home/mariam/workspace/install/lib/libgz-sim7-gz.so.7.1.0", at 0x7fa3b4b56957,
in runServer
#13   Object "/home/mariam/workspace/install/lib/libgz-sim7.so.7", at 0x7fa3b47a2b59, in
gz::sim::v7::Server::Server(gz::sim::v7::ServerConfig const&)
#12   Object "/home/mariam/workspace/install/lib/libgz-sim7.so.7", at 0x7fa3b47b00ba, in
#11   Object "/home/mariam/workspace/install/lib/libgz-sim7.so.7", at 0x7fa3b47c11a7, in
gz::sim::v7::SimulationRunner::SimulationRunner(sdf::v13::World const*,
std::shared_ptr<gz::sim::v7::SystemLoader>
const&, gz::sim::v7::ServerConfig const&)
#10   Object "/home/mariam/workspace/install/lib/libgz-sim7.so.7", at 0x7fa3b473dded, in
gz::sim::v7::LevelManager::LevelManager(gz::sim::v7::SimulationRunner*, bool)
#9    Object "/home/mariam/workspace/install/lib/libgz-sim7.so.7", at 0x7fa3b473c8a1, in
gz::sim::v7::LevelManager::ReadLevelPerformerInfo()
#8    Object "/home/mariam/workspace/install/lib/libgz-sim7.so.7", at 0x7fa3b4747c16, in void
gz::common::EventT<void (unsigned long, std::vector<sdf::v13::Plugin,
std::allocator<sdf::v13::Plugin> >),
gz::sim::v7::events::LoadPluginsTag>::Signal<unsigned long&, std::vector<sdf::v13::Plugin,
std::allocator<sdf::v13::Plugin> > const&>(unsigned long&, std::vector<sdf::v13::Plugin,
std::allocator<sdf::v13::Plugin> > const&)
#7    Object "/home/mariam/workspace/install/lib/libgz-sim7.so.7", at 0x7fa3b47ba618, in
gz::sim::v7::SimulationRunner::LoadPlugins(unsigned long, std::vector<sdf::v13::Plugin,
std::allocator<sdf::v13::Plugin> > const&)
#6    Object "/home/mariam/workspace/install/lib/libgz-sim7.so.7", at 0x7fa3b47d64d4, in
gz::sim::v7::SystemManager::LoadPlugin(unsigned long, sdf::v13::Plugin const&)
#5    Object "/home/mariam/workspace/install/lib/libgz-sim7.so.7", at 0x7fa3b47ce7cf, in
gz::sim::v7::SystemLoader::LoadPlugin(sdf::v13::Plugin const&)
#4    Object "/home/mariam/workspace/install/lib/libgz-plugin2.so.2", at 0x7fa3b1ba9e5c, in
gz::plugin::Plugin::~Plugin()
#3    Object "/home/mariam/workspace/install/lib/libgz-plugin2.so.2", at 0x7fa3b1ba9d61, in
gz::plugin::Plugin::~Plugin()
#2    Object "/home/mariam/workspace/install/lib/libgz-plugin2.so.2", at 0x7fa3b1bab013, in
gz::plugin::PluginWithDlHandle::~PluginWithDlHandle()
#1    Object "/home/mariam/workspace/install/lib/gz-sim-7/plugins/gui/libVisualizeLidar.so",
at 0x7fa38f0feb98, in
std::_Function_handler<void (void*), gz::plugin::detail::MakeInfo<gz::sim::v7::VisualizeLidar,
gz::gui::Plugin>()::
{lambda(void*)#2}>::_M_invoke(std::_Any_data const&, void*&&)
#0    Object "/home/mariam/workspace/install/lib/gz-sim-7/plugins/gui/libVisualizeLidar.so",
at 0x7fa38f0ef3f0, in
gz::sim::v7::VisualizeLidar::~VisualizeLidar()
Segmentation fault (Address not mapped to object [(nil)])
</code>```

I am using Gazebo garden (installed from source by following this tutorial https://gazebosim.org/docs/garden/install_ubuntu_src) and I'm running it on ubuntu 22.04 on VMware

Any idea what's the problem ?

Thanks!

答:
you should include these lines inside the <gui> tag

            <plugin filename="VisualizeLidar" name="Visualize Lidar">
            </plugin>
```

You can also load the plugin using the right top browser menu:

Title: Gazebo Garden Lidar Visualization

Body:
you should include these lines inside the <gui> tag

            <plugin filename="VisualizeLidar" name="Visualize Lidar">
            </plugin>

You can also load the plugin using the right top browser menu:


问:
Kuka iiwa LBR locks up while waiting
I'm working with a Kuka iiwa LBR 14 R820 arm, doing research stuff at a university. I'm writing code in their Sunrise application and pushing Java programs to the Kuka controller box, where I run them on the "smartPad" pendant and observe the results. That all works.

My problem is that if I sit thinking for a bit (between 2 and 30 minutes?), the arm will make a loud click (brakes engaging?), and after that it will not move until I reboot the controller box. Running any application will either throw a Java exception or finish happily without actually moving. Even manual movements in their T1 safety mode won't happen. Nothing fixes it aside from rebooting. Which is very tiresome when it happens for the dozenth time in a day and very embarrassing if it happens during a demo.

It seems to take a random amount of time since last use (in that 2 to 30 minutes range). The arm is always stationary when it happens -- it's never stopped mid-movement. It seems to happen whether an application is actively running (but not moving) or it is running nothing. There is no external load on the arm, just gravity of the arm itself, so I don't think it is overloaded and I presume not overheated.

Is there some trigger that I can avoid?

Is there a command to unstick it?

Is there a parking mode? I had thought that leaving it in position hold helped, but no. I had thought that canceling the last motion helped, but no.

答:
This is only a partial answer.

You need to run the brake tests after system startup. There is a sample brake testing app in the Kuka software distribution, and that will suffice. Or you can write your own in Java.

Without running the brake test, the safety system will eventually decide to stop you from continuing. At that point, only the brake test app (or others that override the safeties) can run.

Unfortunately this does not fix all of the reasons the arm locks, but it does reduce the frequency. Further answers are welcome to address other sources of this symptom.

Title: Kuka iiwa LBR locks up while waiting


问:
Why would you use direct SLAM over feature-based?
I am curious, why would you ever choose direct slam(photometric consistency, etc) over feature based slam? Particularly for dynamic scenes?

It seems you're always better off aligning fewer points which you have a high confidence in over a lot of points you have low confidence in and are prone to poor data association - am I wrong?

For dense reconstruction this can be done after bundle adjustment, etc.

答:
You can take a look at this paper: Feature-based or Direct

The choice would depend on the application and I would prefer direct methos when we don’t have a good source of odometry.

For example, in a drone with monocamera, we might have GPS and IMU, but they are typically not accurate enough for SLAM. I this case, direct methos like DSO will have an initial estimate for depth and minimize the error over time, converging to a good solution over time.

I automotive for example, vehicle have a good source of odemetry to start with and it’s common to use the ground plane to get the scale of the motion. In that case, it’s more efficient to use feature-based methods. Specialty, because features can be used for other functions running in parallel like calibration or free space detection.


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

答:
Your mechanism will depend on the type of dispenser you want. Like if its gravity feed or not. I will assume it is, so I make this sketch to give you some idea:

The hole size will depend on how many candy you want to dispense at each stroke. (Of course its related to the candy size). The electro-mechanical actuator can be a crankshaft one, a solenoid, a linear motor, and goes on.

You can use a vibrator attached to the cup if the candy tends to get stuck.

Title: Robotic part to dispense candy


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

Anyone have experience with this?

答:
It sounds like maybe you're looking for UTM projections. From the Wiki article:

The Universal Transverse Mercator (UTM) is a map projection system for assigning coordinates to locations on the surface of the Earth.

You're not clear with your purpose here so it's not really possible to give you more context related to your use case. Generally speaking, though, you convert latitude and longitude to a UTM easting (x) and northing (y) value. Your altitude can stay as elevation, and you've got x/y/z values.

This is a projection, so like with any project there is distortion. Again quoting the Wiki entry:

By using narrow zones of 6° of longitude (up to 668 km) in width, and reducing the scale factor along the central meridian to 0.9996 (a reduction of 1:2500), the amount of distortion is held below 1 part in 1,000 inside each zone. Distortion of scale increases to 1.0010 at the zone boundaries along the equator.

You can get into trouble when you cross UTM zones, but then it's your choice on how you want to handle that, if it's swapping zones or extending the origin zone's projection to the outlier point(s).

Title: GPS to Cartesian


问:
Webots Ros2 Docker Extern controller plugin silently crashes when asking for keyboard
I am using webots 2022b inside of a docker container. In my vs code, it runs fine, but when I try to run the command straight from the docker container, I am running into an issue where the controller program instantly exits with code-11 but no output or error message.

```<code>[ERROR] [driver-2]: process has died [pid 66, exit code -11, cmd '/opt/ros/galactic/lib/webots_ros2_driver/driver __log_level:=debug --log-level debug --ros-args --params-file /tmp/launch_params_ec8xrm55'].
</code>```

With rclcpp print statements, I have narrowed the crash down to occur on this line:

```<code>keyboard_ = node_->robot()->getKeyboard();
</code>```

I've been stuck on this for a couple days now; I have a couple directions the solution may go: either enable some lower level of logging that will let me see an error message I can work with (I have tried adding
arguments=[('__log_level:=debug'), '--log-level', 'debug'] to the driver node in the launch file but those don't seem to work),

or alternatively maybe there is some setting in docker I can give to pass the keyboard through to the container in a way that webots expects? I have tried a couple things like using docker run -it to give terminal emulation.

答:
It turns out that as Oliver Michel had said, there was a version mismatch between the compiling version of webots and the executing. In this case, it was as simple as I was colcon building in a window of vs code that I had opened weeks ago, and as such was still using webots 2022a, even though I had long since updated the dockerfile to force using 2022b.

Compiling with one version and running against another perhaps predictably caused these unusual errors. Rebuilding my vscode container so I could colcon build in the newer version solved my problem.


问:
Webots simulation, damped world
I am a master's student at the physics department of the Goethe University Frankfurt am Main. I started to learn about Webots, which I intend to use for my master's thesis. I am at the very beginning, so I am still figuring out how different details of the program work.

I encountered an issue, which source I cannot find. In the simplest simulations, like a ball bouncing off the ground, or a pendulum, there seems to be energy loss. All the parameters responsible for damping and friction (in "contact properties" and "damping" node) are zero. The elasticity ("bounce" node) is set to 1, so 100% elasticity. Nevertheless, the systems lose energy. Can it be that this happens purely because the time is discrete? For example, when the ball hits the wall, its velocity after the bounce is equal to the one a time step before the bounce? So it wouldn't be the exact velocity that a real ball would have in the moment it reaches the wall, but a short moment before? Do my questions make any sense to You? I am new to the world of simulations in general, so I don't know if this is a common issue.

答: Discretization of time will cause energy losses in simulations due to numerical errors, as the simulation cannot perfectly replicate the continuous dynamics of a system. This can be addressed by using more sophisticated numerical integration methods that are more accurate. In Webots, you can try using the Runge-Kutta numerical integration method, which should help reduce the energy losses. You can find more information about the different integration methods in the Webots documentation. Additionally, you may want to look into using a more realistic model of friction and damping, which can help reduce the energy losses due to discretization.</p>

Title: Webots simulation, damped world


问:
Why is analysis required to study robotics?
I am studying Informatics and I am interested in doing a Masters in Robotics and I was checking out some unis and their courses and I saw that Robotics contains analysis and a lot of math.

Why is that?

答:
Math is the way that roboticists translate our understanding of the world into something that a computer can understand. Since this is not how humans do it, this requires a lot of rather difficult math. How would you tell a computer what a pencil is? How does that description change if the pencil is rotated?

Robot control also needs a lot of math. If I move this shoulder joint by 5 degrees how much does that move the hand? If I the robot sees the world through a camera and I want the robot to move an object 5 pixels to the right, how much do I need to move each joint? If the object weighs 5 kg how much torque do I need on the motors to hold it? How do I make sure this works even if I measured wrong and the object is really 6kg?

Also, robots have to deal with a lot of uncertainty. The sensors it uses to "see" the world have a lot of random noise so all the algorithms need to somehow model this noise so the robot can react properly. This involves a lot of probability theory.

Finally, since it's not possible to test every environment you have to use math to prove that your algorithms will always work.


问:
Resetting Turtlebot3 odometery to zero without rebooting it [ROS2 Foxy- Turtlebot3]
I am using a Turtlebot3 with an Raspberry Pi 3B+ for my masters degree project, running ROS2 Foxy. I am finding it rather difficult to restart the robot every time I need the odometery to be reset to zero or when the odometery outputs some strange huge values at the start.

Hence, I would like to ask if there is a way to reset the odometery to zero in ROS2 Foxy using some script or command(s). This way there is not a need to reboot the robot to reset the odometery.

答:
There is no built-in way to reset the odometry to zero in ROS2 Foxy. However, you could create a script that does this by resetting the odometry topic to 0.0 in the robot's namespace. You can find the topic by running the command "ros2 topic list" in the robot's namespace.

To reset the odometry, you could publish a message to the odometry topic with the x and y coordinates set to 0.0. You can do this with the command:

```<code>ros2 topic pub /<robot_namespace>/odom geometry_msgs/Twist "linear:
  x: 0.0
  y: 0.0"
</code>```

This should reset the odometry to zero and the robot should be ready to move again.

Body:
There is no built-in way to reset the odometry to zero in ROS2 Foxy. However, you could create a script that does this by resetting the odometry topic to 0.0 in the robot's namespace. You can find the topic by running the command "ros2 topic list" in the robot's namespace.

To reset the odometry, you could publish a message to the odometry topic with the x and y coordinates set to 0.0. You can do this with the command:

ros2 topic pub /<robot_namespace>/odom geometry_msgs/Twist "linear:
  x: 0.0
  y: 0.0"

This should reset the odometry to zero and the robot should be ready to move again.


问:
Infinite world that wraps around
In webots: Is it possible for an infinite arena where your mobile robot can drive out left of the arena an come back on the right? Like a wrapping world.</p>

答: Yes, it is possible to create an infinite arena where your mobile robot can drive out left of the arena and come back on the right. This type of arena is called a "wraparound" arena and it is created by setting the boundaries of the arena in such a way that if the robot moves beyond the left edge of the arena, it reappears on the right edge. The same is true for the top and bottom edges. This type of arena can be useful for testing algorithms that require a robot to explore an unknown environment.</p>

Title: Infinite world that wraps around


问:
How to control a servo using ROS2 and MICRO-ROS
I am currently using a raspberry pi pico and a raspberry pi 4, So far I have established a connection between the two using micro-ros-agent I have also successfully built and ran the example provided here https://ubuntu.com/blog/getting-started-with-micro-ros-on-raspberry-pi-pico

so I wanted to try it out on a simple servo how do I do it as there is no servo.h library here to use.

答:
Install ROS2 on both the Raspberry Pi Pico and the Raspberry Pi 4.

Connect the Raspberry Pi Pico and the Raspberry Pi 4 with a USB cable.

Install the micro-ros-agent package on both devices.

Create a ROS2 workspace and source the ROS2 environment on both devices.

On the Raspberry Pi 4, create a ROS2 package for your servo.

Write a ROS2 node to control your servo. This node should subscribe to the desired servo angle topic and publish the actual servo angle topic.

On the Raspberry Pi Pico, create a micro-ROS package for your servo.

Write a micro-ROS node to control your servo. This node should handle the servo hardware commands needed to move the servo to the desired angles.

Connect the servo to the Raspberry Pi Pico and configure the GPIO pins.

Build and run the micro-ROS node on the Raspberry Pi Pico, and the ROS2 node on the Raspberry Pi 4.

Publish the desired servo angle on the ROS2 topic, and your servo should move to the desired angle.


问:
Webots world built from sources environment not working in distributions
I made a simulation of a farm in Webots using the new animals objects released with R2023a.

I first developed my simulation using these instruction to build Webots from sources: https://github.com/cyberbotics/webots/wiki/Linux-installation/
I did that to have access to the animals before R2023a was released.

However, now that R2023a is out, I installed the snap package to continue my project. But the world is completely broken.

The world loads, but the screen is black and the terminal is flooded with errors like that:

```<code>ERROR: URL '/snap/webots/24/usr/share/webots/projects/objects/animals/protos/Horse.proto' changed by fallback mechanism. Ensure you are opening the correct world.
ERROR: Skipped PROTO 'Horse' as it is not available at: /snap/webots/24/usr/share/webots/projects/objects/animals/protos/Horse.proto.
ERROR: URL '/snap/webots/24/usr/share/webots/projects/objects/animals/protos/Horse.proto' changed by fallback mechanism. Ensure you are opening the correct world.
ERROR: 'agriProj.wbt':11:1: error: Skipped unknown 'Horse' node or PROTO.
ERROR: URL '/snap/webots/24/usr/share/webots/projects/objects/animals/protos/Horse.proto' changed by fallback mechanism. Ensure you are opening the correct world.
</code>```

Operating system: ubuntu 22.04

What I have tried so far:

I tried to install Webots with the .deb and also the .tar.bz2 but I had the same issue.

I made a minimal example of just a horse, viewpoint and worldinfo but it is still bugging.

I tried to add a new horse and it works as if the horse from the Webots built from sources is not compatible with the horse from the distributions, which is really strange.

It seems to affect only PROTO, not base node like Transform, Solid, Background ans so on.

Is there something specific to do when switching from sources to released packages?

答:
It seems like your Webots installation is looking for the PROTO locally instead of remotely.

Short answer:

-Open agriProj.wbt in a text editor.

-Replace all occurences of webots:// by https://raw.githubusercontent.com/cyberbotics/webots/R2023a/.

-Save the .wbt file

-Open it again in Webots and it should work.

Long answer:

When you install webots from the sources, all the assets (textures, protos,...) are available locally in the Webots folder.
However, the assets are not distributed in the released version of Webots to reduce the size of the package (https://cyberbotics.com/doc/blog/Webots-2021-b-release#reduce-package-size).

I think that the protos you are trying to load do not have the right path.

Since R2022b, the keyword EXTERNPROTO is used in worlds to determine where Webots needs to look for a specific asset.
If you insert a Horse in a world you will have the line:
EXTERNPROTO "https://raw.githubusercontent.com/cyberbotics/webots/R2023a/projects/objects/animals/protos/Horse.proto"
at the top of your worldfile.

However, when using webots from sources, there is a special case.
As developing from sources is thought for the developpers of Webots, a direct access to the assets is needed to be able to quickly modify and test them.
That what the webots:// prefix does: it tells Webots to look in its installation directory.

So what I suspect is that when you built your world in the Webots development environment, you got the webots:// urls written in your world.
Then when you try to open it in your snap installation, it will look locally in the snap folder (where there are no assets) instead of downloading them.

To fix this you need to change all the webots:// prefixes by https://raw.githubusercontent.com/cyberbotics/webots/R2023a/ in your world (.wbt) file

In the future, if you want to use features that were not released yet and you want to avoid this issue, I recommend you to use the nightly builds available here: https://github.com/cyberbotics/webots/releases


问:
The Matlab controller doesn't work for the Webots robot
I create a bipedal robot and I would like to use MATLAB to control two rotational motors. The code for controller is simple but some warning just shows up.

Does anyone know how to solve this?

WARNING: Unable to find the 'matlab' executable in the current PATH. Please check your matlab installation. It should be possible to launch matlab from a terminal by typing 'matlab'. It may be necessary to add the matlab bin directory to your PATH environment variable. More information about the matlab installation is available in Webots' User guide.

I am using Webots R2019a on Windows 11.

Thanks

答:
Before the R2022b version of Webots, MATLAB was simply started with the command line 'matlab'. For this to be possible, it is necessary that the Webots installation folder is in the PATH.

This way of starting MATLAB has been modified with R2022b, because there was a bug on macOS which uses different PATHs depending on if Webots was started from a terminal or from the graphical interface.

As indicated in the Webots documentation (Using MATLAB) and in the console error message, MATLAB is now started from its executable file. By default, if no version is specified in the preferences (Tools > Preferences > General), Webots looks for the most recent MATLAB version in the default installation folder, depending on the OS:

Windows: C:\Program Files\MATLAB\R20XXx\bin\win64\MATLAB.exe

Linux: /usr/local/MATLAB/R20XXx/bin/matlab

MacOS: /Applications/MATLAB_R20XXx.app

In order to specify a particular version of MATLAB to start, the absolute path to the executable can be specified in the Webots preferences, as shown above.


问:
Retrieving the global 3d position of a robot or object in Webots
In the context of my simulation, I need to programmatically get the position of robots and objects in the world (in global coordinate system). How can this be done?

I'm using Webots R2023a.

答:
There are different functions depending whether this information must be accessed in a normal controller, in a Supervisor controller or in a physics plugin. All the functions described below will return the 3D position in meters and expressed in the global (world) coordinate system.

Get position using the robot's controller

If one is not available already, you need to first add a GPS node to your robot.
You can get a reference to this device using the wb_robot_get_device function, enable it with wb_gps_enable and retrieve the values with wb_gps_get_values. Note that the GPS's resolution field must be 0 (the default), otherwise the results will be noisy. It should also be noted that the GPS can be placed on a robot's part (arm, foot, etc.) to get the world/global coordinates of that particular part.

Get position using a Supervisor

To get the 3D position of any Transform (or derived) node using the Supervisor API you can use the wb_supervisor_node_get_position function.
Another possible approach of getting the 3D position of any Transform (or derived) node placed at the root of the Scene Tree (the nodes visible when the Scene Tree is completely collapsed), is to use the wb_supervisor_field_get_sf_vec3f to read the value of the translation field of that object.

Get position using a physics plugin

After adding a physics plugin to your world (under the WorldInfo node), you can retrieve the information directly from the physics engine by using ODE's dBodyGetPosition function. Note that this function returns the position of the center of mass of the body, which may be different from the center of the Solid.

Lastly, the position of a robot can also be approximated by using odometry or SLAM techniques. This is usually more realistic because most robots don't have a GPS and therefore have no mean of precisely determining their position.

Disclaimer: I'm a software developer of Webots


问:
looking for a miniature joystick, but in reverse
Does anyone know if small mechanical actuators exist which can be controlled electrically, sort of like a miniature joystick, but in reverse.  Instead of it picking up mechanical movement and outputting electrical signals, I want it to generate mechanical movement controlled via my electrical input signals.  I’ve searched for : electromechanical actuators, not finding what I need. Think of a pencil attached to a surface which can pivot to point anywhere in its half dome.  I’m thinking small, on the order of an inch.  It will not be load bearing.

My goal is to programmatically control the normal pointed to by a small flat surface attached to the end of each joystick rod.  Accuracy is more important than speed.  From across a small room, say 10' by 10', I'd like the surface normal to accurately point to arbitrary objects in the room, say a person walking across the room.  If I can cheaply buy/build such mechanisms to control the movement of these small flat surfaces, I would like dozens places across the walls of the room.

Its for an electromechanical sound project I’m planning.

答: The device you are looking for is a "pan-tilt" unit.  They are typically used for pointing security cameras.  If you find a "PTZ", i.e. pan-tilt-zoom security camera used, you could butcher it an just use the Pan/Tilt part.</p>


问:
How to make the output axis of hingejoint with rotational motor not affected by physics?
I want the rotational motors be affected only by my controller, not by the physics of the world. The problem is shown in this video. How to fix this?</p>

答:
The problem comes from the fact that the environment is applying some forces and torques on your motor and the motor cannot hold its position because it is not strong enough. To fix this problem, you should simply increase the strength of the motor. For a RotationalMotor, increasing the maxTorque value should resolve the problem.

You should also ensure that you didn't override this value with a lower value using wb_motor_set_available_torque or wb_motor_set_torque. That means that you should not perform torque/force control, but either position control or velocity control (so that you don't limit the motor torque).

For a LinearMotor, the same applies with the force settings of the motor instead of torque. But I believe that in your case, you only have rotational motors.


问:
robotic arm controlled by mouse
I want to create a webot simulation for robotic arm. The entire arm should be controlled by the mouse. Is it possible to implement in webots?
I am trying simulation for this https://youtu.be/nz_tgDD8FNw</p>

答:
In Webots there is the mouse node, with this you can capture the mouse events, but only the events that happen in the 3D window.

Link Reference Manual: https://cyberbotics.com/doc/reference/mouse?tab-language=c

Example to get status of mouse: https://drive.google.com/file/d/1xERoBf7CTFZpdXwBVb5UOtROao8F8Npd/view?usp=sharing

Video of example:
https://youtu.be/9QlW7n98oro

Upgrade: january 19 2023

Basic Arm V1 - Controlled by mouse and keyboard:
Video: https://youtu.be/CRfqlA7r0aA

Basic Arm V2 - Controlled by mouse and keyboard:
Video: https://youtu.be/ebUXBYJDIBE

Worlds Examples (Full: V1 & V2): https://github.com/DrakerDG/Webotz/tree/master/Basic_Arm

Evolution! Basic Arm V2

Title: robotic arm controlled by mouse


问:
Webots: Increase Calculation Speed On Supercomputer
I am using a supercomputer (MSI, Minnesota Supercomputing Institute) to run my Webots simulations. However, on my own laptop (MacOS) the amount of time necessary to calculations is much shorter. I was wondering if there was an optimal configuration (i.e., minimum number of cores, memory, etc.) that I should have to limit performance issues due to computation time?

Right now, I have allocated 25 GB of memory, 48 GB of temporary memory, and 8 cores on the supercomputer using the same environment as my Mac.

Info regarding this computer found below:

```<code>  Model Name:                 MacBook Air
  Model Identifier:           MacBookAir8,2
  Processor Name:             Dual-Core Intel Core i5
  Processor Speed:            1.6 GHz
  Number of Processors:       1
  Total Number of Cores:      2
  L2 Cache (per Core):        256 KB
  L3 Cache:                   4 MB
  Hyper-Threading Technology: Enabled
  Memory:                     8 GB
</code>```

Any insights into how to limit this problem would be greatly appreciated!

答:
It is very likely that your supercomputer has no GPU whereas your laptop has a GPU with OpenGL hardware acceleration. Webots relies a lot on the GPU, in particular for rendering camera images, lidars data, range-finder images, etc. If your simulation makes use of such devices, the performance will be impacted greatly if the supercomputer doesn't have any GPU.

In any case, you should be careful to launch Webots with the --no-rendering command line option to avoid rendering the main 3D view. This will speed-up your simulation. Also, you should use the --mode=fast option to ensure the simulation runs as fast as possible.

With these command line options and if your simulation is not using any GPU-related devices, it should normally run faster on the supercomputer.


问:
Transparent Interior of Mesh in Gazebo
I am trying to use a tunnel-like mesh in gazebo as a model of its own. I have the pointcloud and I followed this tutorial to transform it to a mesh https://gazebosim.org/api/gazebo/3.3/pointcloud.html

My problem is that on gazebo, the inside of the mesh is completely transparent so the inside of the tunnel cannot be detected by a lidar. Any idea how to fix it ?

答:
Sounds like you're seeing backface culling, where faces that don't point toward the viewer aren't rendered. Here's what it looks like when face normals aren't rendered correctly (from this page):

There are typically a couple ways around this:

Invert the normals in CloudCompare, but this will mean the outside of the mesh is transparent and the inside is visible.

Duplicate the mesh and flip the normals to get a "two-faced" mesh. With Blender, open the mesh, select the mesh, hit "tab" to go to edit mode, hit "a" to select all, "shift + D" to duplicate the mesh, "esc" to cancel moving it, then go to Mesh -> Normals -> Flip and flip the normals.

It might be possible to disable backface culling in gazebo but the link in that post is dead, and I don't get any results when I search for backface culling.

That's it, typically - either the normals exist (options 1 and 2) or you tell the engine to ignore the normals (option 3). The lidar itself will generally render only what the engine allows to be rendered, and if the normals are getting culled then there's nothing there for the lidar to detect.

I have not used Gazebo, though, so things might be different there.

Title: Transparent Interior of Mesh in Gazebo


答: The issue is likely that your normals are flipped the wrong way. Polygons only face one direction and for a tunnel they need to be facing inward. Fortunately flipping normals is a pretty quick operation. Load the mesh in blender then select all the faces and got to Mesh > Normals > Flip. This should flip all normals so they are facing inward.</p>

Title: Transparent Interior of Mesh in Gazebo

Body:
I am trying to use a tunnel-like mesh in gazebo as a model of its own. I have the pointcloud and I followed this tutorial to transform it to a mesh https://gazebosim.org/api/gazebo/3.3/pointcloud.html

My problem is that on gazebo, the inside of the mesh is completely transparent so the inside of the tunnel cannot be detected by a lidar. Any idea how to fix it ?


问:
Why are installed ROS 2 humble python packages split in two directories
Cross-post on ROS answer

Since ROS 2 Humble on Ubuntu 22.04, I noticed that now ROS 2 Humble python packages are split between two directories.

/opt/ros/humble/lib/python3.10/site-packages

And

/opt/ros/humble/local/lib/python3.10/dist-packages

For example, tf2_ros is installed under /opt/ros/humble/lib/python3.10/site-packages/tf2_ros
and tf2_py is installed under /opt/ros/humble/local/lib/python3.10/dist-packages/tf2_py

From what I can see, it was not the case before (for Foxy and Galactic, at least). And I was wondering why is it split like this?

This brings the issue that if you source your ROS 2 Humble installation before installing any packages, installing files in local/lib/python3.10/dist-packages this subdirectory won't be added to your PYTHONPATH environment variable.

This force to resource the environment.

答:
The destination of site-packages versus dist-packages depends on which installation and packaging system you use.

site-packages is the default for python native installers. dist-packages is an alternative location that is mandated by Debian to avoid conflicts. There's some discussion here

Third party Python software installed from Debian packages goes into dist-packages, not site-packages. This is to reduce conflict between the system Python, and any from-source Python build you might install manually. From the Debian Python Page

This means that it depends on which installation mechanism is used they may use the different default situation. If you look at tf2_py It's a c++ compiled package which is installed via cmake which defaults to the debian conventions. Whereas tf2_ros_py which provides the tf2_ros libraries uses the native python installer, thus defaulting to the upstream python convention.

This does look like a change from earlier. Unfortunately python installation is currently going through several changes in mechanisms I'm not sure why this behavior has changed.

This force to resource the environment.

In general when you install new software you should expect to need to re-source your setup files. In the case of python, there may be a new PYTHONPATH needed. Similarly, there may be new resources installed and available based on other configurations or other <*>_PATH variables extended.

Edit:
Slightly extending this discussion. I missed that content was going into local/ in addition to being site-packages vs dist-packages difference I talked about above.

There's some unfortunate tweaks that various Linux distributions are doing to patch their Python libraries to inject local/ into the paths. It should never have local/ in it - some of our hooks don't work if packages end up there. If you find deb packages or rpms with local/ in them please file a ticket. We've been working to make sure that colcon-core can detect and avoid those cases of locally patched python libraries. If you're installing from source make sure that colcon-core is up to date.


问:
SLAM with multiple cameras and asynchronous sensors
I'm pretty sure this is the right place for this question, but if not, please point me in the right direction!

Basically, I would like to know how do SLAM using multiple cameras and sensors that are asynchronous. Along with this, I'm curious if there's any way to use the SLAM information—or any way in general—to automatically align the pose data from multiple devices into the same coordinate system.

My specific situation is that I have devices that each have 2 cameras, 2 IMUs without built-in magnetometers, a magnetometer, and a GPS. The cameras use fisheye lenses, point different directions (but have a little overlap on their images), and capture images at the same time. However, all other sensors take measurements at different times. The IMUs have similar capture rates but don't capture at the same time, the magnetometer takes measurements much less often that the IMUs do, etc. I have the transformation matrices to convert between the sensors' local coordinate systems, along with other intrinsic and extrinsic data.

I'd like to get the orientations and positions from all of this data as well as a mapping of the environment. I also have recordings of the devices in the same location, so I want to put the devices' poses in the same reference frame so that they can be visualized at the same time. The algorithm doesn't have to do online / real-time SLAM, since I'm only analyzing the data after it's all been captured. Furthermore, it's not necessary for the algorithm to use all of the sensors, but I would like it to at least use both cameras. If possible, I'd also prefer the algorithm to not rely on ROS.

Most of the algorithms I found online didn't match my case exactly, and the one that I think might've doesn't have a public implementation that I can use.

答:
I have done many multi-modal sensor fusions with LiDAR, IMU, and cameras. Obviously, synchronization is the hardest problem if it is not synchronized at the HW level.

To be able to do SLAM with multi-modal asynchronous sensors, you need a few things in your SLAM system.

Continuous time trajectory representation

1.1 If your trajectory can be represented as a function of time, you can represent your sensor estimation w.r.t the system time. And you need to have cost functions that take sensor data + sensor time.

E.g the poupular P2P ICP error is represented as e = Tp-p' where your continuous time representation of this equation is simply e = T(t)p-p'.

Look at my papers if you want to know the details. I have done it for LiDAR, camera, and IMU in the paper but it works for Stereo-Inertial problems too.

https://scholar.google.com.au/citations?view_op=view_citation&hl=en&user=2orHutwAAAAJ&authuser=2&citation_for_view=2orHutwAAAAJ:MXK_kJrjxJIC

https://scholar.google.com.au/citations?view_op=view_citation&hl=en&user=2orHutwAAAAJ&authuser=2&citation_for_view=2orHutwAAAAJ:kNdYIx-mwKoC

1.2 An alternative way is integrating IMU and assuming that the cameras are synchronized by the trigger signal. This mitigates small differences but you still need to measure the time difference between IMU and cameras. The most popular reference for this method would be OpenVINS.

Time-lag estimation

Now you have a tool that represents the trajectory in continuous time to deal with the asynchronous estimation. But you also have to find the time lag between the sensors. Thanks to the continuous-time representation you just have to add the estimated time lag dt to each sensor's estimation.

Just add the time lag to your system state. Now your cost function will look like
e = T(t+dt)p-p'

Enough motion that can observe the time lag between the sensorsNote that estimating the time lag between the sensors won't be possible unless you move the sensor. The time lag is observable only when you move the sensor


问:
Why a car is sinking into the ground in my Webots simulation?
I added a car from the Webots library into my scene, but when I start the simulation the car is sinking into the ground.
This is the same BmwX5 car model used in the sample simulation "city.wbt" (I just changed the color).

What am I missing?

Why the car lies correctly on the road in "city.wbt" but not in my world?

I already checked that the boundingObject of the road is enabled (StraightRoadSegment.roadBoundingObject is set to TRUE).

Disclaimer:
I am part of the development team of Webots and this is a question it is frequently asked by users so I hope it will help some people!

答:
This problem is due to the default value of some contact property between the car wheels and the road. The soft Constraint Force Mixing (softCFM) used by the ODE physics engine to manage local contacts joints affects directly the inter-penetration of bodies. Its default value was set for light robots, so in case of heavy weight robots, it has to be adjusted.

You can override this default value in the WorldInfo node of the world file. Basically, you should reduce the value of the softCFM field in the ContactProperties node which defines the contact between the robot (typically the robot wheels or feet) and the ground. You can check the values for the softCFM parameter in the city.wbt world file. Simply copying/pasting the same values in your world file should resolve the problem.

You may also fine tune these values to adjust the level of body inter-penetration to suit your needs. This can be useful to roughly simulate different levels of tire pressure.


问:
Transform problem with rviz map display when using the SLAMTEC Mapper M2M2 with ROS
I am working on a project using the SLAMTEC Mapper M2M2 with ROS to map an area of interest. I am using Oracle Virtualbox to run ROS Noetic with Ubuntu 20.04, and my host machine is running on Windows 10. However, when running rviz, there seems to be a problem with the map display. Below is what I did from the beginning.

After downloading the Slamware ROS SDK (GCC 9) from the SLAMTEC website, I moved the folders to the src folder in my catkin_ws. I connected the device to a power bank, and then connected my PC to its built-in WiFi. After that, I launched the relevant nodes in the 'slamware_ros_sdk' package as follows.

```<code>roslaunch slamware_ros_sdk slamware_ros_sdk_server_node.launch ip_address:=192.168.11.1

roslaunch slamware_ros_sdk view_slamware_ros_sdk_server_node.launch
</code>```

Everything seems to be working fine, the map of the area of interest can be viewed, however, there is a status error in the map display under transform. The error is as follows.

No transform from [/slamware_map] to [slamware_map].

Because of this, I am unable to view the location of the device within the map generated (the axes are located outside of the map). I also cannot save the map in a pgm file via the map_server package. Maybe this is due to the map not being generated properly. I attached a picture below.

I am just using the SLAMTEC Mapper on its own, without any other devices or robots, as I just require the map to work with.

Would appreciate any help and support I can get. Apologies as I am still new to ROS, so I might not know a lot of things.

答:
No transform from [/slamware_map] to [slamware_map].

I'm not familiar with Slamware in particular, but I can tell you what the error means. RViz is trying to display data that has a frame_id of /slamware_map in a frame with id slamware_map. It does not see these as the same (or related) frames because one of them has a leading / and one does not. This might mean that your map topic and your /tf topic disagree on the frame name.

The simplest resolution for you is probably to modify the code that's producing the data, so all nodes are using the exact same frame_id. It could also be related to the setting of fixed frame that you've chosen in RViz, so make sure to check that too.

You can read a (very old) post about leading slashes and prefixes in ROS here: https://answers.ros.org/question/43145/tf-namespace-resolution/

And on the wiki: http://wiki.ros.org/tf2/Migration

See also: https://github.com/ros2/geometry2/issues/219 "There should not be a slash."


问:
Question about bundle adjustment
When doing bundle adjustment do landmarks gets optimized as stand alone variables or are they viewed as a function of the robots first position when they are detected?</p>

答:
The points are assumed to be static in the global frame and optimized in the global frame. Each time the point is detected within the camera frame a measurement is taken relative to the camera. The process of reconciling the successive measurements of the same point across multiple frames by minimizing the reproduction error in each frame is what refines the location of the points in 3D space.

For more see: https://arxiv.org/pdf/1912.03858.pdf#:~:text=Bundle%20adjustment%20describes%20the%20sum,world%20frame)%20and%20camera%20parameters.

Title: Question about bundle adjustment


问:
Should I be using the old clutches with VEX 393 motors?
I am posting here because the "official" Vex forums don't seem to support EDR anymore :-( but anyhow...

I am teaching a class and we are using VEX parts to build a simple winch, the whole point is to experiment with gear ratios.

Well and good. We are using standard 393 motors hooked up to a VEX cortex with the standard 7.2 V battery.

In our experiment we will be loading up the VEX motor (using a simple spool) to lift a weight with a string. I was looking up the stall torque of the motors, and I wanted to get an idea of whether I should, for safety's sake (safety to the motor that is) use the clutches. I know at least one kid will try to lift a brick or something, and the first part of the experiment is using the Vex motor with no gearing, and we will be increasing the gear ratios as we go to demonstrate the increase in torque. The word I get is that the stall torque on a VEX 393 is somewhere around 1.67 N•m assuming full speed (set at 127 in RobotC, if I am reading this correctly) and that means that for the winches (which have a radius ~1 cm, 0.01 m) that means a 17 kg mass on the end will load it with 17•9.8•0.01 = 1.66 N•m, which is a lot! But while that gives me some confidence that even with a really heavy mass on the end the motor will work, I wanted to be sure we wouldn't damage it, hence the question about using the little green clutches VEX supplies. Should I use those just in case? Many VEX posts say they aren't necessary anymore...

Anyhow any insight is appreciated.

答:
The clutch isn't necessary. While you don't want to leave it stalled for a super long time, stalling your electric motor won't cause it any harm. It'll just act as a static electromagnet and generate some heat. Unless you leave it for a while you're not going to generate enough heat do damage anything.

The one thing I would look out for is only use the motor to lift off the ground. If you suspend a large weight and try to get the motor to pull or hold it, the weight defeating the motor will generate back EMF and enough current produced in that way could do damage to the motor or the controller.


问:
Why is analysis required to study robotics?
I am studying Informatics and I am interested in doing a Masters in Robotics and I was checking out some unis and their courses and I saw that Robotics contains analysis and a lot of math.

Why is that?

答:
The short answer is that learning robotics is easier with the math than without.

Here are a few areas of robotics and the field of mathematics that make them manageable:

Measuring data from sensors, with some level of uncertainty: statistics

Solving problems through reasoning: formal logic

Kinematics: linear algebra

Control theory: calculus

Algorithms: theory of computation, combinatorics

Mechanical design: physics

Sonar design: acoustics

Cooperative robotics, path planning: graph theory

This is a very incomplete list.

Being able to predict or explain why a system works the way it does is very difficult without the mathematical language to describe it.  The ideas are complicated, and you'd be hard pressed to find a more understandable way to communicate all but the simplest ideas in robotics without a mathematical language to rely on.  (Not to mention that it's a more objective process to simplify mathematical equations than an english description of the same system.)

You may find that studying robotics will make it easier to learn the math, because it will give you a practical application for what's ordinarily just a bunch of theory.


问:
How can such a small motor produce so much torque?
I have only recently gotten into robotics - so I'm not that familiar - please excuse me if this is a silly question.

I was looking at servo and stepper motors. I can see that a lot of servo motors basically look like this one:

This servo can produce 1.1Nm of force. I have seen it. It's very small, light and cute. It doesn't look as "professional" as the types below.

There are also much larger (stepper) motors that look like these:

This is significantly larger, heavier, yet produces only 0.4Nm of torque.

It's very shocking to me that such a small motor outperforms this larger one. Ignoring the differences between stepper and servo motors, is there any advantage to using this larger one?

Will it have better speed or reliability perhaps?

答:
While there are a lot of different ways to evaluate motors, what you're getting at is likely the power output of each. Power (Watts) is defined as (force x distance)/time. So while the servo may have a higher torque output, it moves much more slowly and has a lower overall power output.

There are other factors as well such as cost & quality of the motors, but I don't believe that's the core of your question based on your framing.


问:
does lidar sensor output data have spatial locality?
i have a question about the output of lidar sendor (like velodyne vlp-16, etc)

Is there any spatial or temporal locality for output data which is from lidar sensor?
Does the produced output data from lidar sensor are stored in memory position sequentially or randomly?
(which means that if a data from 0x000 and 0x001 point are spatially or temporally related.)

I see that lidar output data is obtained by spherical coordinate system and converted to cartesian coordiate system.
(FIG 9-1, https://greenvalleyintl.com/wp-content/uploads/2019/02/Velodyne-LiDAR-VLP-16-User-Manual.pdf)

And there is a driver code to make un-ordered point cloud data to ordered data
(https://github.com/ros-drivers/velodyne/blob/master/velodyne_pointcloud/include/velodyne_pointcloud/organized_cloudXYZIRT.h)

So, i guess lidar sensor is rotating 360' and sequentially produce the output and save them to certain memory location. So, is that possible to presume that memory address could give us hint for point cloud data information even before the ordering process?

Thank you.
If i have some lidar sensor, then this question could be solved easily. but i don't have one.

答:
For each given sample there is a spacial assumption that you can make. And for each sequential sample there are temporal and spacial assumptions that you can make. These assumptions might change slightly based on the operating parameters of the system, such as the scanning speed. Also keep in mind that the measurements may be interlaced in position across the scan. This was true of the HDL64 lasers I'm not familiar with the newer ones.

And if you're using processed or aggregated data you will want to make sure that you fully understand each of the previous steps in the pipeline to make sure that you understand the data structure.


问:
Headless mode with GPUs
I have tested Webots headless mode in docker as described here in Ubuntu 20.04.

In the headless mode, if we make gpus available to the docker container as follows

docker run --gpus=all -it cyberbotics/webots:latest
xvfb-run webots --stdout --stderr --batch --mode=realtime /path/to/your/world/file
```
<p>This seems to launch Webots without GPUs (hardware acceleration). This is, to my knowledge, because xvfb will use software acceleration.</p>
<p>I believe that GPUs will speed up the simulations for cameras and video recordings, so in that case, I'd like to use GPUs in the headless.</p>
<p>This is the output with xvfb-run webots....
You can see that Webots warns that the system is below minimum. With GUI + GPU in docker, I don't get warnings or it runs nearly as fast as a native installation.</p>
<pre class="lang-bash prettyprint-override"><code>
xvfb-run webots --stdout --stderr --batch --mode=fast /usr/local/webots/projects/robots/clearpath/moose/worlds/moose_demo.wbt
WARNING: It is not recommended to run Webots as root.
WARNING: System below the minimal requirements.

Webots has detected that your GPU vendor is 'Mesa/X.org'. A recent NVIDIA or AMD graphics adapter is highly recommended to run Webots smoothly. Webots has detected that your computer uses a slow 3D software rendering system. It is strongly recommended to install the latest graphics drivers provided by your GPU manufacturer. Webots will run much faster after the installation of the correct driver.

 - Shadows have been deactivated.
 - Anti-aliasing has been deactivated.
 - Main 3D view global ambient occlusion has been de-activated.
 - Texture quality has been reduced.
 - Texture maximum filtering has been reduced due to GPU limitations.
 - Anisotropic texture filtering is not supported by the GPU.

You can try to re-activate some OpenGL features from the Webots preferences.
WARNING: Cannot initialize the sound engine: Cannot initialize OpenAL default device 'OpenAL Soft'
</code>```

Are there any ways of using hardware acceleration in the headless mode?
Some use cases are running Webots containers through CI/CD on headless servers.

答:
You are right that the GPU allows to speed-up all the rendering part, including cameras.

Using xvfb-run to run Webots headless in the Docker is the recommended option. However, it won't take advantage of the GPU, as hardware acceleration is not supported by Xvfb.

Instructions in the Webots documentation (https://www.cyberbotics.com/doc/guide/installation-procedure#run-webots-in-docker-with-gui) show how to run Webots with hardware 3D acceleration in a Docker container. But this method starts Webots with GUI. It is possible to launch it with the --minimize option, so that it doesn't show-up at launch.

Concerning full headless mode with GPU acceleration, there is the possibility to use VNC server. These instructions explain how to use it to start Webots headless (see jumax-cpu section). This example is for an remote SSH server, but it should be equivalent to a Docker container. VNC server will create a virtual display in the container to run Webots headless. To take advantage of hardware acceleration with VNC, you can use VirtualGL to start Webots. See this documentation page for more information.

You can check that Webots is launched with the correct OpenGL version by using the --sysinfo option at launch.

Title: Headless mode with GPUs


问:
How can I make an invisible wall in Webots?
I need to create an invisible wall in Webots but I don't know how to do it. Could someone please help me?</p>

答:
In order to create an invisible wall, you can simply create a Solid node with no children field, so that it is invisible, no physics field, so that it is attached to the static world and a Box node as a boundingObject, so that collision detection will be based on this box:

Solid {
  translation 0 0 1
  rotation 0 0 1 0
  name "my invisible wall"
  boundingObject Box {
    size 0.2 4 2
  }
}
```

The above Solid node will act as an invisible wall located at the center of the world, with a height of 2 meters, a length of 4 meters and a thickness of 20 cm. You will be able to change its translation and rotation fields to move it around and rotate it.

Disclaimer: I am a Webots developer working at Cyberbotics.

Body:
In order to create an invisible wall, you can simply create a Solid node with no children field, so that it is invisible, no physics field, so that it is attached to the static world and a Box node as a boundingObject, so that collision detection will be based on this box:

Solid {
  translation 0 0 1
  rotation 0 0 1 0
  name "my invisible wall"
  boundingObject Box {
    size 0.2 4 2
  }
}

The above Solid node will act as an invisible wall located at the center of the world, with a height of 2 meters, a length of 4 meters and a thickness of 20 cm. You will be able to change its translation and rotation fields to move it around and rotate it.

Disclaimer: I am a Webots developer working at Cyberbotics.


问:
Multiple ROS installation on single machine
Can I have multiple versions of ROS or ROS2 installed on a single machine or PC?</p>

答:
Yes. See discussion here: https://answers.ros.org/question/187548/can-i-install-multiple-ros-version-on-the-same-machine/

Each ROS distro (both 1 & 2) installs its programs into /opt/ros/{distro}, so you can have them installed side-by-side with no conflict.

However you should only use one distro at a time. In order to use a distro, you source its setup script in your shell, e.g.:

```<code>$ source /opt/ros/humble/setup.bash
...the remainder of this session will be in the humble environment
</code>```

If you plan to have multiple ROS versions installed and use them regularly, I would not recommend doing this inside your .bashrc or equivalent login script, because you need to avoid having multiple distros sourced in the same shell. Whenever you want to start using a distro, just source its setup script manually.

Body:
Yes. See discussion here: https://answers.ros.org/question/187548/can-i-install-multiple-ros-version-on-the-same-machine/

Each ROS distro (both 1 & 2) installs its programs into /opt/ros/{distro}, so you can have them installed side-by-side with no conflict.

However you should only use one distro at a time. In order to use a distro, you source its setup script in your shell, e.g.:

$ source /opt/ros/humble/setup.bash
...the remainder of this session will be in the humble environment

If you plan to have multiple ROS versions installed and use them regularly, I would not recommend doing this inside your .bashrc or equivalent login script, because you need to avoid having multiple distros sourced in the same shell. Whenever you want to start using a distro, just source its setup script manually.


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

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

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

答:
Welcome to Robotics, Jonathan Ariel Callejas. You haven't provided your code, but I believe the problem you're having is with variable scope.

In your case, your error suggests you're trying to make a public variable that lives inside a method:

In function 'int main(int, char**)':  [...] public static double dist;

If the variable is defined inside main, then it can't be public because its scope is limited to main. (Note: It's possible to make a "global" variable, but global variables are never the right answer.)

The compiler is complaining because you're trying to make public static double dist inside main, and it's essentially invalidating that line of code and trying to compile the rest. But, because the declaration isn't valid, when it tries to evaluate the line that uses dist, it doesn't know what dist is and so also throws the second error:

error: 'dist' was not declared in this scope

Easy solution should be to just remove the public keyword, but you can also remove the static keyword because main should be the "outer-most" method; it won't go out of scope (and dist won't get destructed) until the program terminates.

Now, none of this really goes to your comment

I have been attempting to have two controllers be able to access information from each other in a way that is similar to object-oriented programming in UNITY

Unity is C#, and you're writing C++ code, and you can 100% do object-oriented code in both. In C# you can just plop everything in a file and be done with, but in C++ everything has to be declared before you can use it. Typically this is done with a header file, where you might define your class:

```<code>public class MyController
{
    public:
        float my_public_float;
        void DoSomethingNeat(float operand);
    private:
        float my_private_float;
};
</code>```

You then go wherever you've got your main and would include the header, which should generally have the same name as the class inside it, so something like #include<MyController.h>. This tells your program that there is such a thing as a class called MyController, that it has a public float called my_public_float, and a method called DoSomethingNeat that takes a single float as an input, but doesn't return anything.

It doesn't tell the program what those things are, just that they exist. This is kind of the beauty of the header file - you can tuck your definitions away somewhere else, and as long as you don't change the header file, you don't need to rebuild the main program because the interfaces to that class haven't changed.

Then you'd make a .cpp file that actually defines what the class is. That .cpp file would also #include<MyController.h>, and might look something like:

```<code>#include<MyController.h>
#include<iostream> // For std::cout
#include<string> // For std::to_string

void MyController::DoSomethingNeat(float operand)
{
    std::cout<<"I was passed: "<<std::to_string(operand)<<std::endl;
}
</code>```

Any variables that are part of the controller should be made part of the controller class, as public or private depending on whether something outside the class should be able to access it or not, and you can do the same with methods; they can be public/private as well.

All the other object-oriented concepts from Unity/C# apply - inheritance, polymorphism, etc. The syntax is a little different, but you just google the term and "c++" and should get to somewhere like cppreference that explains how to do it in C++.

I'd highly recommend reading some introductory C++ material to familiarize yourself with how concepts like these are implemented in the language.

Body:
Welcome to Robotics, Jonathan Ariel Callejas. You haven't provided your code, but I believe the problem you're having is with variable scope.

In your case, your error suggests you're trying to make a public variable that lives inside a method:

In function 'int main(int, char**)':  [...] public static double dist;

If the variable is defined inside main, then it can't be public because its scope is limited to main. (Note: It's possible to make a "global" variable, but global variables are never the right answer.)

The compiler is complaining because you're trying to make public static double dist inside main, and it's essentially invalidating that line of code and trying to compile the rest. But, because the declaration isn't valid, when it tries to evaluate the line that uses dist, it doesn't know what dist is and so also throws the second error:

error: 'dist' was not declared in this scope

Easy solution should be to just remove the public keyword, but you can also remove the static keyword because main should be the "outer-most" method; it won't go out of scope (and dist won't get destructed) until the program terminates.

Now, none of this really goes to your comment

I have been attempting to have two controllers be able to access information from each other in a way that is similar to object-oriented programming in UNITY

Unity is C#, and you're writing C++ code, and you can 100% do object-oriented code in both. In C# you can just plop everything in a file and be done with, but in C++ everything has to be declared before you can use it. Typically this is done with a header file, where you might define your class:

public class MyController
{
    public:
        float my_public_float;
        void DoSomethingNeat(float operand);
    private:
        float my_private_float;
};

You then go wherever you've got your main and would include the header, which should generally have the same name as the class inside it, so something like #include<MyController.h>. This tells your program that there is such a thing as a class called MyController, that it has a public float called my_public_float, and a method called DoSomethingNeat that takes a single float as an input, but doesn't return anything.

It doesn't tell the program what those things are, just that they exist. This is kind of the beauty of the header file - you can tuck your definitions away somewhere else, and as long as you don't change the header file, you don't need to rebuild the main program because the interfaces to that class haven't changed.

Then you'd make a .cpp file that actually defines what the class is. That .cpp file would also #include<MyController.h>, and might look something like:

#include<MyController.h>
#include<iostream> // For std::cout
#include<string> // For std::to_string

void MyController::DoSomethingNeat(float operand)
{
    std::cout<<"I was passed: "<<std::to_string(operand)<<std::endl;
}

Any variables that are part of the controller should be made part of the controller class, as public or private depending on whether something outside the class should be able to access it or not, and you can do the same with methods; they can be public/private as well.

All the other object-oriented concepts from Unity/C# apply - inheritance, polymorphism, etc. The syntax is a little different, but you just google the term and "c++" and should get to somewhere like cppreference that explains how to do it in C++.

I'd highly recommend reading some introductory C++ material to familiarize yourself with how concepts like these are implemented in the language.


答:
Building off from what Tully said, I can add a little more context.

For reasons I won't get into here, several distributors of Python have begun patching the sysconfig module of Python itself to inject local into the paths reported by sysconfig.get_path (et.al.). In my opinion, this change was implemented with a mallet when it should have been done with a scalpel, but we are where we are. Fedora has revised their approach in a way that corrected the behavioral regression here, but I haven't seen anything similar from Debian/Ubuntu or Homebrew yet.

On the colcon side, this issue resulted in these changes:

colcon/colcon-core#504

colcon/colcon-core#507

colcon/colcon-core#510

colcon/colcon-core#512

colcon/colcon-core#514

On the ament side, less changes are necessary, but we have yet to release a fix. The way that these distributor patches were structured, they never affect our debian or RPM builds, so the remaining bug happens when we build ament_cmake_python packages from source outside of a debian or RPM build. The issue you're facing is also less critical than the ones we were facing in colcon because hooks for dealing with the unexpected path were generated to ensure PYTHONPATH was updated appropriately. It's still not the intended behavior, but at least it's functional. The fix for the issue is being tracked as ament/ament_cmake#386. Now that discussion around the issue has been reignited, I think we'll drive the PR to a conclusion soon.

All this said, I think you should be cautious about installing packages into a workspace and expecting that you won't need to source that workspace again. Packages may define any arbitrary environment hooks for a variety of reasons, so it will always be safest to re-source the workspace after installing or updating packages.

Title: Why are installed ROS 2 humble python packages split in two directories

Body:
Cross-post on ROS answer

Since ROS 2 Humble on Ubuntu 22.04, I noticed that now ROS 2 Humble python packages are split between two directories.

/opt/ros/humble/lib/python3.10/site-packages

And

/opt/ros/humble/local/lib/python3.10/dist-packages

For example, tf2_ros is installed under /opt/ros/humble/lib/python3.10/site-packages/tf2_ros
and tf2_py is installed under /opt/ros/humble/local/lib/python3.10/dist-packages/tf2_py

From what I can see, it was not the case before (for Foxy and Galactic, at least). And I was wondering why is it split like this?

This brings the issue that if you source your ROS 2 Humble installation before installing any packages, installing files in local/lib/python3.10/dist-packages this subdirectory won't be added to your PYTHONPATH environment variable.

This force to resource the environment.